Add files via upload

more security patches
This commit is contained in:
Steve Seguin
2025-10-21 20:13:06 -04:00
committed by GitHub
parent 83c0ac753a
commit 20c815e607
6 changed files with 383 additions and 170 deletions

164
examples/chat.html Normal file
View File

@@ -0,0 +1,164 @@
<html>
<head>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>OBSN Chat Overlay</title>
<style>
@font-face {
font-family: 'Cousine';
src: url('fonts/Cousine-Bold.ttf') format('truetype');
}
body {
margin:0;
padding:0 10px;
height:100%;
border: 0;
display: flex;
flex-direction: column-reverse;
position:absolute;
bottom:0;
overflow:hidden;
max-width:100%;
}
div {
margin:0;
background-color: black;
padding: 8px 8px 0px 8px;
color: white;
font-family: Cousine, monospace;
font-size: 3.2em;
line-height: 1.1em;
letter-spacing: 0.0em;
text-transform: uppercase;
text-shadow: 0.05em 0.05em 0px rgba(0,0,0,1);
max-width:100%;
word-wrap: break-word;
overflow-wrap: break-word;
word-break: break-all;
hyphens: auto;
display:inline-block;
}
a {
color:white;
font-size:1.2em;
text-transform: none;
word-wrap: break-word;
overflow-wrap: break-word;
word-wrap: break-word;
word-break: break-all;
hyphens: auto;
}
</style>
<script>
(function (w) {
w.URLSearchParams =
w.URLSearchParams ||
function (searchString) {
var self = this;
self.searchString = searchString;
self.get = function (name) {
var results = new RegExp("[\?&]" + name + "=([^&#]*)").exec(
self.searchString
);
if (results == null) {
return null;
} else {
return decodeURI(results[1]) || 0;
}
};
};
})(window);
var urlParams = new URLSearchParams(window.location.search);
function loadIframe() {
var iframe = document.createElement("iframe");
var view= "";
if (urlParams.has("view")) {
view = "&view="+(urlParams.get("view") || "");
}
var room="";
if (urlParams.has("room")) {
room = "&room="+urlParams.get("room");
}
var password="";
if (urlParams.has("password")) {
password = "&password="+urlParams.get("password");
}
iframe.allow = "autoplay";
var srcString = "./?novideo&noaudio&label=chatOverlay&scene"+room+view+password;
iframe.src = srcString;
iframe.style.width="0";
iframe.style.height="0";
iframe.style.border="0";
document.body.appendChild(iframe);
//////////// LISTEN FOR EVENTS
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";
/// If you have a routing system setup, you could have just one global listener for all iframes instead.
eventer(messageEvent, function (e) {
if (e.source != iframe.contentWindow){return} // reject messages send from other iframes
console.log(e);
if ("gotChat" in e.data){
logData(e.data.gotChat.label,e.data.gotChat.msg);
}
});
}
function printValues(obj) {
var out = "";
for (var key in obj) {
if (typeof obj[key] === "object") {
out += "<br />";
out += printValues(obj[key]);
} else {
if (key.startsWith("_")) {
} else {
out += "<b>" + key + "</b>: " + obj[key] + "<br />";
}
}
}
return out;
}
function logData(type, data) {
var span = document.createElement('span');
var entry = document.createElement('div');
if (type){
var typeElement = document.createElement('i');
typeElement.textContent = type.replace(/_/g, ' ');
entry.appendChild(typeElement);
entry.appendChild(document.createTextNode(" "));
}
var message = document.createElement('span');
message.textContent = data;
entry.appendChild(message);
span.appendChild(entry);
document.body.prepend(span);
}
</script>
</head>
<body onload="loadIframe();">
</body>
</html>

View File

@@ -166,16 +166,21 @@
window.location.href = newUrl;
}
function logData(type, data) {
var entry = document.createElement('div');
if (type) {
type = "<i>" + type.replace(/_/g, ' ') + "</i>";
}
entry.innerHTML = type + data;
document.getElementById('chat-overlay').prepend(entry);
}
function logData(type, data) {
var entry = document.createElement('div');
if (type) {
var typeElement = document.createElement('i');
typeElement.textContent = type.replace(/_/g, ' ');
entry.appendChild(typeElement);
entry.appendChild(document.createTextNode(" "));
}
var message = document.createElement('span');
message.textContent = data;
entry.appendChild(message);
document.getElementById('chat-overlay').prepend(entry);
}
window.onload = loadIframe;
</script>
</body>
</html>
</html>

View File

@@ -94,21 +94,39 @@ if (urlParams.has("api")){
var href = window.location.href;
var arr = href.split('?');
var newurl;
if (arr.length > 1 && arr[1] !== '') {
newurl = href + '&api=' + WID;
} else {
newurl = href + '?api=' + WID;
if (arr.length > 1 && arr[1] !== '') {
newurl = href + '&api=' + encodeURIComponent(WID);
} else {
newurl = href + '?api=' + encodeURIComponent(WID);
}
window.history.pushState({path: newurl.toString()}, '', newurl.toString());
}
var path = "vdo.ninja"; //window.location.host+window.location.pathname.split("/").slice(0,-1).join("/");
var header = document.getElementById("header");
header.innerHTML += "Your Ninja Link: <a href='https://"+path+"/?api="+WID+"' target='_blank'>https://"+path+"/?api="+WID+"</a><br /><br />";
header.innerHTML += "<small>You can append your own VDO.Ninja parameters to this link, treating it like a normal VDO.Ninja link.</small>";
header.innerHTML += "<br /><br /><small>Code and documentation hosted at <a href='https://github.com/steveseguin/Companion-Ninja'>https://github.com/steveseguin/Companion-Ninja</a></small> <svg width='32' height='32' viewBox='0 0 1024 1024' fill='none' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z' transform='scale(64)' fill='#1B1F23'/></svg>";
var path = "vdo.ninja"; //window.location.host+window.location.pathname.split("/").slice(0,-1).join("/");
var header = document.getElementById("header");
var linkWrapper = document.createElement("div");
var linkLabel = document.createElement("span");
linkLabel.textContent = "Your Ninja Link: ";
var shareLink = document.createElement("a");
var shareURL = "https://" + path + "/?api=" + encodeURIComponent(WID);
shareLink.href = shareURL;
shareLink.target = "_blank";
shareLink.rel = "noopener";
shareLink.textContent = shareURL;
linkWrapper.appendChild(linkLabel);
linkWrapper.appendChild(shareLink);
header.appendChild(linkWrapper);
var info = document.createElement("small");
info.textContent = "You can append your own VDO.Ninja parameters to this link, treating it like a normal VDO.Ninja link.";
header.appendChild(info);
header.appendChild(document.createElement("br"));
header.appendChild(document.createElement("br"));
var repoInfo = document.createElement("small");
repoInfo.innerHTML = "Code and documentation hosted at <a href='https://github.com/steveseguin/Companion-Ninja'>https://github.com/steveseguin/Companion-Ninja</a>";
header.appendChild(repoInfo);
header.insertAdjacentHTML("beforeend", " <svg width='32' height='32' viewBox='0 0 1024 1024' fill='none' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z' transform='scale(64)' fill='#1B1F23'/></svg>");
var socket = null;
var connecting = false;
@@ -474,4 +492,4 @@ loadGuestCommands(3);
loadGuestCommands(4);
</script>
</body>
</html>
</html>

View File

@@ -99,8 +99,50 @@ function loadIframe(url=false){ // this is pretty important if you want to avoi
document.getElementById("container").appendChild(iframeContainer);
var videos = iframe.contentWindow.document.querySelectorAll("video");
var sensors = {};
var videos = iframe.contentWindow.document.querySelectorAll("video");
var sensors = {};
function appendTextLine(container, text, indentLevel){
var line = document.createElement("div");
if (indentLevel){
line.style.marginLeft = (indentLevel * 12) + "px";
}
line.textContent = text;
container.appendChild(line);
}
function appendKeyValueList(container, obj, indentLevel){
indentLevel = indentLevel || 0;
for (var key in obj) {
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
continue;
}
var value = obj[key];
if (typeof value === "object" && value !== null) {
appendTextLine(container, key + ":", indentLevel);
appendKeyValueList(container, value, indentLevel + 1);
} else {
appendTextLine(container, key + ": " + value, indentLevel);
}
}
}
function getOrCreateOutput(id, borderStyle){
var element = id ? document.getElementById(id) : null;
if (element){
element.textContent = "";
return element;
}
var div = document.createElement("div");
if (borderStyle){
div.style.border = borderStyle;
}
if (id){
div.id = id;
}
iframeContainer.appendChild(div);
return div;
}
function drawFrame(vid){
try {
@@ -159,122 +201,99 @@ function loadIframe(url=false){ // this is pretty important if you want to avoi
eventer(messageEvent, function (e) {
if (e.source != iframe.contentWindow){return} // reject messages send from other iframes
if ("stats" in e.data){
var outputWindow = document.createElement("div");
//console.log(e.data.stats);
var out = "<br />total_inbound_connections:"+e.data.stats.total_inbound_connections;
out += "<br />total_outbound_connections:"+e.data.stats.total_outbound_connections;
for (var streamID in e.data.stats.inbound){
out += "<br /><br /><b>streamID:</b> "+streamID+"<br />";
out += printValues(e.data.stats.inbound[streamID]);
}
outputWindow.innerHTML = out;
iframeContainer.appendChild(outputWindow);
}
if ("gotChat" in e.data){
var outputWindow = document.createElement("div");
outputWindow.innerHTML = e.data.gotChat.msg;
outputWindow.style.border="1px dotted black";
iframeContainer.appendChild(outputWindow);
}
if ("action" in e.data){
var outputWindow = document.createElement("div");
outputWindow.innerHTML = "child-page-action: "+e.data.action+"<br />";
outputWindow.style.border="1px dotted black";
iframeContainer.appendChild(outputWindow);
console.log(e.data.action);
if (e.data.action == "new-view-connection"){
setTimeout(function(){
videos = iframe.contentWindow.document.querySelectorAll("video");
console.log(videos);
},500);
}
}
if ("streamIDs" in e.data){
var outputWindow = document.createElement("div");
outputWindow.innerHTML = "child-page-action: streamIDs<br />";
for (var key in e.data.streamIDs) {
outputWindow.innerHTML += "streamID: " + key + ", label:"+e.data.streamIDs[key] + "\n";
}
outputWindow.style.border="1px dotted black";
iframeContainer.appendChild(outputWindow);
}
if ("loudness" in e.data){
//console.log(e.data);
if (document.getElementById("loudness")){
outputWindow = document.getElementById("loudness");
} else {
var outputWindow = document.createElement("div");
outputWindow.style.border="1px dotted black";
iframeContainer.appendChild(outputWindow);
outputWindow.id = "loudness";
}
outputWindow.innerHTML = "child-page-action: loudness<br />";
for (var key in e.data.loudness) {
outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n";
}
outputWindow.style.border="1px black";
}
if ("sensors" in e.data){
sensors = e.data.sensors;
if (document.getElementById("sensors")){
outputWindow = document.getElementById("sensors");
} else {
var outputWindow = document.createElement("div");
outputWindow.style.border="1px dotted black";
iframeContainer.appendChild(outputWindow);
outputWindow.id = "sensors";
console.log(sensors);
}
outputWindow.innerHTML = "child-page-action: sensors<br /><br />";
for (var key in e.data.sensors.lin) {
outputWindow.innerHTML += key + " linear: " + e.data.sensors.lin[key] + "<br />";
}
for (var key in e.data.sensors.acc) {
outputWindow.innerHTML += key + " acceleration: " + e.data.sensors.acc[key] + "<br />";
}
for (var key in e.data.sensors.gyro) {
outputWindow.innerHTML += key + " gyro: " + e.data.sensors.gyro[key] + "<br />";
}
for (var key in e.data.sensors.mag) {
outputWindow.innerHTML += key + " magnet: " + e.data.sensors.mag[key] + "<br />";
}
for (var key in e.data.sensors.ori) {
outputWindow.innerHTML += key + " orientation: " + e.data.sensors.ori[key] + "<br />";
}
outputWindow.style.border="1px black";
}
if ("stats" in e.data){
var statsBox = document.createElement("div");
appendTextLine(statsBox, "total_inbound_connections: " + e.data.stats.total_inbound_connections);
appendTextLine(statsBox, "total_outbound_connections: " + e.data.stats.total_outbound_connections);
for (var streamID in e.data.stats.inbound){
if (!Object.prototype.hasOwnProperty.call(e.data.stats.inbound, streamID)){
continue;
}
var streamHeader = document.createElement("div");
streamHeader.style.marginTop = "8px";
var streamLabel = document.createElement("strong");
streamLabel.textContent = "streamID:";
streamHeader.appendChild(streamLabel);
streamHeader.appendChild(document.createTextNode(" " + streamID));
statsBox.appendChild(streamHeader);
appendKeyValueList(statsBox, e.data.stats.inbound[streamID], 1);
}
iframeContainer.appendChild(statsBox);
}
if ("gotChat" in e.data){
var chatBox = document.createElement("div");
chatBox.textContent = e.data.gotChat.msg;
chatBox.style.border="1px dotted black";
iframeContainer.appendChild(chatBox);
}
if ("action" in e.data){
var actionBox = document.createElement("div");
appendTextLine(actionBox, "child-page-action: " + e.data.action);
actionBox.style.border="1px dotted black";
iframeContainer.appendChild(actionBox);
console.log(e.data.action);
if (e.data.action == "new-view-connection"){
setTimeout(function(){
videos = iframe.contentWindow.document.querySelectorAll("video");
console.log(videos);
},500);
}
}
if ("streamIDs" in e.data){
var streamBox = document.createElement("div");
streamBox.style.border="1px dotted black";
appendTextLine(streamBox, "child-page-action: streamIDs");
for (var key in e.data.streamIDs) {
if (!Object.prototype.hasOwnProperty.call(e.data.streamIDs, key)){
continue;
}
appendTextLine(streamBox, "streamID: " + key + ", label: " + e.data.streamIDs[key], 1);
}
iframeContainer.appendChild(streamBox);
}
if ("loudness" in e.data){
var loudnessBox = getOrCreateOutput("loudness", "1px dotted black");
appendTextLine(loudnessBox, "child-page-action: loudness");
for (var key in e.data.loudness) {
if (!Object.prototype.hasOwnProperty.call(e.data.loudness, key)){
continue;
}
appendTextLine(loudnessBox, key + " Loudness: " + e.data.loudness[key], 1);
}
loudnessBox.style.border="1px black";
}
if ("sensors" in e.data){
sensors = e.data.sensors;
var sensorsBox = getOrCreateOutput("sensors", "1px dotted black");
appendTextLine(sensorsBox, "child-page-action: sensors");
for (var sensorKey in e.data.sensors) {
if (!Object.prototype.hasOwnProperty.call(e.data.sensors, sensorKey)){
continue;
}
var sensorValue = e.data.sensors[sensorKey];
if (typeof sensorValue === "object" && sensorValue !== null){
appendTextLine(sensorsBox, sensorKey + ":", 0);
appendKeyValueList(sensorsBox, sensorValue, 1);
} else {
appendTextLine(sensorsBox, sensorKey + ": " + sensorValue, 0);
}
}
sensorsBox.style.border="1px black";
}
});
}
function printValues( obj) {
var out = "";
for (var key in obj) {
if (typeof obj[key] === "object") {
out +="<br />";
out += printValues(obj[key]);
} else {
out +="<b>"+key+"</b>: "+obj[key]+"<br />";
}
}
return out;
}
</script>
</body>
</html>
</script>
</body>
</html>

View File

@@ -147,21 +147,26 @@
return out;
}
function logData(type, data) {
var log = document.body.getElementsByTagName("ul")[0];
var entry = document.createElement('li');
if (type){
type = "<i>"+type+"</i>";
}
entry.innerHTML = type + data;
//setTimeout(function(entry){ // hide message after 60 seconds
// entry.innerHTML="";
// entry.remove();
// },60000,entry);
log.appendChild(entry);
}
function logData(type, data) {
var log = document.body.getElementsByTagName("ul")[0];
var entry = document.createElement('li');
if (type){
var typeElement = document.createElement("i");
typeElement.textContent = type;
entry.appendChild(typeElement);
entry.appendChild(document.createTextNode(" "));
}
var message = document.createElement("span");
message.textContent = data;
entry.appendChild(message);
//setTimeout(function(entry){ // hide message after 60 seconds
// entry.innerHTML="";
// entry.remove();
// },60000,entry);
log.appendChild(entry);
}
</script>
</head>
<body onload="loadIframe();">

View File

@@ -130,12 +130,13 @@ if (urlParams.get("a")){
}
document.getElementById("viewlinka").value = "https://"+path+"/?push="+urlParams.get("a");
if (urlParams.get("la")){
document.getElementById("viewlinka").value += "&label="+urlParams.get("la");
document.getElementById("a").innerHTML = urlParams.get("la")
}
}
if (urlParams.get("la")){
var labelA = urlParams.get("la");
document.getElementById("viewlinka").value += "&label="+encodeURIComponent(labelA);
document.getElementById("a").textContent = labelA;
}
}
if (urlParams.get("b")){
if (window.location.host){
var path = window.location.host+window.location.pathname.replace("/examples/","/").split("/").slice(0,-1).join("/");
@@ -144,11 +145,12 @@ if (urlParams.get("b")){
}
document.getElementById("viewlinkb").value = "https://"+path+"/?push="+urlParams.get("b");
if (urlParams.get("lb")){
document.getElementById("viewlinkb").value += "&label="+urlParams.get("lb");
document.getElementById("b").innerHTML = urlParams.get("lb")
}
}
if (urlParams.get("lb")){
var labelB = urlParams.get("lb");
document.getElementById("viewlinkb").value += "&label="+encodeURIComponent(labelB);
document.getElementById("b").textContent = labelB;
}
}
var iframeb = null;
var iframea = null;
@@ -193,15 +195,15 @@ function loadIframes(){
if (iframeb && (e.source === iframeb.contentWindow)) {
console.log(e.data);
if (e.data.action == "this-label"){
document.getElementById("a").innerHTML = e.data.value;
}
} else if (iframea && (e.source === iframea.contentWindow)) {
if (e.data.action == "this-label"){
document.getElementById("b").innerHTML = e.data.value;
}
}
document.getElementById("a").textContent = e.data.value;
}
} else if (iframea && (e.source === iframea.contentWindow)) {
if (e.data.action == "this-label"){
document.getElementById("b").textContent = e.data.value;
}
}
}, false);
</script>
</body>
</html>
</html>