The MPL 2.0 license is a "file-level" copyleft license vs the
"project-level" nature of the L/GPL. The intention of noVNC has
always been that it should be easy to incorporate into existing
projects and sites whether free/open or proprietary/commercial. The MPL
2.0 is designed for this sort of combination project but still
requires that any distributed modifications to noVNC source files must
also be published under the same license.
In addition, the MPL 2.0 allows the code to be used in L/GPL projects
(the secondary license clause). This means that any projects that are
already incorporating noVNC should not be impacted by this change and
in fact it should clarify the licensing situation (the exact
application of the L/GPL to web applications and interpreted code is
somewhat ambiguous).
The HTML, CSS, image and font files continue to be under more
permissive licenses (see LICENSE.txt). The included websockify python
code remains under a LGPLv3 license although the include/websock.js
file from the websockify component is now under MPL 2.0 as well.
Permission was received from other noVNC authors to make this change to their
code license on the following dates:
- Chris Gordon (UI): Jun 24, 2012
- Antoine Mercadal (DOM,*util.js): Oct 10, 2012
- William Lightning (UltraVNC repeater): Oct 10, 2012
- Mike Tinglof (tight encoding): Oct 15, 2012
217 lines
5.8 KiB
JavaScript
217 lines
5.8 KiB
JavaScript
/*
|
|
* noVNC: HTML5 VNC client
|
|
* Copyright (C) 2012 Joel Martin
|
|
* Licensed under MPL 2.0 (see LICENSE.txt)
|
|
*
|
|
* See README.md for usage and integration instructions.
|
|
*/
|
|
|
|
"use strict";
|
|
/*jslint bitwise: false, white: false */
|
|
/*global Util, window, document */
|
|
|
|
// Globals defined here
|
|
var WebUtil = {}, $D;
|
|
|
|
/*
|
|
* Simple DOM selector by ID
|
|
*/
|
|
if (!window.$D) {
|
|
window.$D = function (id) {
|
|
if (document.getElementById) {
|
|
return document.getElementById(id);
|
|
} else if (document.all) {
|
|
return document.all[id];
|
|
} else if (document.layers) {
|
|
return document.layers[id];
|
|
}
|
|
return undefined;
|
|
};
|
|
}
|
|
|
|
|
|
/*
|
|
* ------------------------------------------------------
|
|
* Namespaced in WebUtil
|
|
* ------------------------------------------------------
|
|
*/
|
|
|
|
// init log level reading the logging HTTP param
|
|
WebUtil.init_logging = function(level) {
|
|
if (typeof level !== "undefined") {
|
|
Util._log_level = level;
|
|
} else {
|
|
Util._log_level = (document.location.href.match(
|
|
/logging=([A-Za-z0-9\._\-]*)/) ||
|
|
['', Util._log_level])[1];
|
|
}
|
|
Util.init_logging();
|
|
};
|
|
|
|
|
|
WebUtil.dirObj = function (obj, depth, parent) {
|
|
var i, msg = "", val = "";
|
|
if (! depth) { depth=2; }
|
|
if (! parent) { parent= ""; }
|
|
|
|
// Print the properties of the passed-in object
|
|
for (i in obj) {
|
|
if ((depth > 1) && (typeof obj[i] === "object")) {
|
|
// Recurse attributes that are objects
|
|
msg += WebUtil.dirObj(obj[i], depth-1, parent + "." + i);
|
|
} else {
|
|
//val = new String(obj[i]).replace("\n", " ");
|
|
if (typeof(obj[i]) === "undefined") {
|
|
val = "undefined";
|
|
} else {
|
|
val = obj[i].toString().replace("\n", " ");
|
|
}
|
|
if (val.length > 30) {
|
|
val = val.substr(0,30) + "...";
|
|
}
|
|
msg += parent + "." + i + ": " + val + "\n";
|
|
}
|
|
}
|
|
return msg;
|
|
};
|
|
|
|
// Read a query string variable
|
|
WebUtil.getQueryVar = function(name, defVal) {
|
|
var re = new RegExp('[?][^#]*' + name + '=([^&#]*)'),
|
|
match = document.location.href.match(re);
|
|
if (typeof defVal === 'undefined') { defVal = null; }
|
|
if (match) {
|
|
return decodeURIComponent(match[1]);
|
|
} else {
|
|
return defVal;
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
* Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html
|
|
*/
|
|
|
|
// No days means only for this browser session
|
|
WebUtil.createCookie = function(name,value,days) {
|
|
var date, expires;
|
|
if (days) {
|
|
date = new Date();
|
|
date.setTime(date.getTime()+(days*24*60*60*1000));
|
|
expires = "; expires="+date.toGMTString();
|
|
}
|
|
else {
|
|
expires = "";
|
|
}
|
|
document.cookie = name+"="+value+expires+"; path=/";
|
|
};
|
|
|
|
WebUtil.readCookie = function(name, defaultValue) {
|
|
var i, c, nameEQ = name + "=", ca = document.cookie.split(';');
|
|
for(i=0; i < ca.length; i += 1) {
|
|
c = ca[i];
|
|
while (c.charAt(0) === ' ') { c = c.substring(1,c.length); }
|
|
if (c.indexOf(nameEQ) === 0) { return c.substring(nameEQ.length,c.length); }
|
|
}
|
|
return (typeof defaultValue !== 'undefined') ? defaultValue : null;
|
|
};
|
|
|
|
WebUtil.eraseCookie = function(name) {
|
|
WebUtil.createCookie(name,"",-1);
|
|
};
|
|
|
|
/*
|
|
* Setting handling.
|
|
*/
|
|
|
|
WebUtil.initSettings = function(callback) {
|
|
var callbackArgs = Array.prototype.slice.call(arguments, 1);
|
|
if (window.chrome && window.chrome.storage) {
|
|
window.chrome.storage.sync.get(function (cfg) {
|
|
WebUtil.settings = cfg;
|
|
console.log(WebUtil.settings);
|
|
if (callback) {
|
|
callback.apply(this, callbackArgs);
|
|
}
|
|
});
|
|
} else {
|
|
// No-op
|
|
if (callback) {
|
|
callback.apply(this, callbackArgs);
|
|
}
|
|
}
|
|
};
|
|
|
|
// No days means only for this browser session
|
|
WebUtil.writeSetting = function(name, value) {
|
|
if (window.chrome && window.chrome.storage) {
|
|
//console.log("writeSetting:", name, value);
|
|
if (WebUtil.settings[name] !== value) {
|
|
WebUtil.settings[name] = value;
|
|
window.chrome.storage.sync.set(WebUtil.settings);
|
|
}
|
|
} else {
|
|
localStorage.setItem(name, value);
|
|
}
|
|
};
|
|
|
|
WebUtil.readSetting = function(name, defaultValue) {
|
|
var value;
|
|
if (window.chrome && window.chrome.storage) {
|
|
value = WebUtil.settings[name];
|
|
} else {
|
|
value = localStorage.getItem(name);
|
|
}
|
|
if (typeof value === "undefined") {
|
|
value = null;
|
|
}
|
|
if (value === null && typeof defaultValue !== undefined) {
|
|
return defaultValue;
|
|
} else {
|
|
return value;
|
|
}
|
|
};
|
|
|
|
WebUtil.eraseSetting = function(name) {
|
|
if (window.chrome && window.chrome.storage) {
|
|
window.chrome.storage.sync.remove(name);
|
|
delete WebUtil.settings[name];
|
|
} else {
|
|
localStorage.removeItem(name);
|
|
}
|
|
};
|
|
|
|
/*
|
|
* Alternate stylesheet selection
|
|
*/
|
|
WebUtil.getStylesheets = function() { var i, links, sheets = [];
|
|
links = document.getElementsByTagName("link");
|
|
for (i = 0; i < links.length; i += 1) {
|
|
if (links[i].title &&
|
|
links[i].rel.toUpperCase().indexOf("STYLESHEET") > -1) {
|
|
sheets.push(links[i]);
|
|
}
|
|
}
|
|
return sheets;
|
|
};
|
|
|
|
// No sheet means try and use value from cookie, null sheet used to
|
|
// clear all alternates.
|
|
WebUtil.selectStylesheet = function(sheet) {
|
|
var i, link, sheets = WebUtil.getStylesheets();
|
|
if (typeof sheet === 'undefined') {
|
|
sheet = 'default';
|
|
}
|
|
for (i=0; i < sheets.length; i += 1) {
|
|
link = sheets[i];
|
|
if (link.title === sheet) {
|
|
Util.Debug("Using stylesheet " + sheet);
|
|
link.disabled = false;
|
|
} else {
|
|
//Util.Debug("Skipping stylesheet " + link.title);
|
|
link.disabled = true;
|
|
}
|
|
}
|
|
return sheet;
|
|
};
|