From 6bc9cadaef9583ee142e869d4718cb9f6610f5c9 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 18 Jan 2017 16:57:20 +0100 Subject: [PATCH] Use RequireJS module system Use a standard module system rather than a home grown one, and RequireJS fits better with browsers than CommonJS. --- .gitignore | 2 + app/locale/de.js | 6 +- app/locale/el.js | 6 +- app/locale/nl.js | 6 +- app/locale/sv.js | 6 +- app/novnc.js | 22 + app/require.js | 5 + app/ui.js | 66 +- app/webutil.js | 641 +++++----- core/base64.js | 197 +-- core/des.js | 355 +++--- core/display.js | 180 ++- core/inflator.js | 2455 +------------------------------------ core/inflator.mod.js | 40 - core/input/devices.js | 26 +- core/input/keysym.js | 728 +++++------ core/input/keysymdef.js | 7 +- core/input/util.js | 726 +++++------ core/input/xtscancodes.js | 302 ++--- core/rfb.js | 498 ++++---- core/util.js | 774 ++++++------ core/websock.js | 53 +- docs/notes | 4 +- inflator/Makefile | 19 + inflator/build.js | 8 + inflator/inflator.js | 52 + karma.conf.js | 33 +- package.json | 1 + po/po2js | 6 +- tests/run_from_console.js | 2 + tests/test-main.js | 5 + tests/test.base64.js | 13 +- tests/test.display.js | 15 +- tests/test.helper.js | 14 +- tests/test.keyboard.js | 13 +- tests/test.rfb.js | 15 +- tests/test.util.js | 32 +- tests/test.websock.js | 11 +- utils/parse.js | 9 +- vnc.html | 12 +- vnc_auto.html | 300 +++-- 41 files changed, 2634 insertions(+), 5031 deletions(-) create mode 100644 app/novnc.js create mode 100644 app/require.js delete mode 100644 core/inflator.mod.js create mode 100644 inflator/Makefile create mode 100644 inflator/build.js create mode 100644 inflator/inflator.js create mode 100644 tests/test-main.js diff --git a/.gitignore b/.gitignore index da1b8c22..3550a5b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ *.pyc *.o +inflator/inflator-merged.js +inflator/pako tests/data_*.js utils/rebind.so utils/websockify diff --git a/app/locale/de.js b/app/locale/de.js index 6819c486..1ed5d2c4 100644 --- a/app/locale/de.js +++ b/app/locale/de.js @@ -5,7 +5,10 @@ * DO NOT EDIT! */ -Language = { +"use strict"; + +define(function() { +return { "Connecting...": "Verbunden...", "Connected (encrypted) to ": "Verbunden mit (verschlüsselt) ", "Connected (unencrypted) to ": "Verbunden mit (unverschlüsselt) ", @@ -16,3 +19,4 @@ Language = { "Forcing clipping mode since scrollbars aren't supported by IE in fullscreen": "'Clipping-Modus' aktiviert, Scrollbalken in 'IE-Vollbildmodus' werden nicht unterstützt", "Disconnect timeout": "Timeout beim trennen", }; +}); diff --git a/app/locale/el.js b/app/locale/el.js index 3ce6c389..8eac95c2 100644 --- a/app/locale/el.js +++ b/app/locale/el.js @@ -5,7 +5,10 @@ * DO NOT EDIT! */ -Language = { +"use strict"; + +define(function() { +return { "Connecting...": "Συνδέεται...", "Connected (encrypted) to ": "Συνδέθηκε (κρυπτογραφημένα) με το ", "Connected (unencrypted) to ": "Συνδέθηκε (μη κρυπτογραφημένα) με το ", @@ -72,3 +75,4 @@ Language = { "Send Password": "Αποστολή Κωδικού Πρόσβασης", "Canvas not supported.": "Δεν υποστηρίζεται το στοιχείο Canvas", }; +}); diff --git a/app/locale/nl.js b/app/locale/nl.js index cacab302..cd63d4b1 100644 --- a/app/locale/nl.js +++ b/app/locale/nl.js @@ -5,7 +5,10 @@ * DO NOT EDIT! */ -Language = { +"use strict"; + +define(function() { +return { "Connecting...": "Verbinden...", "Connected (encrypted) to ": "Verbonden (versleuteld) met ", "Connected (unencrypted) to ": "Verbonden (onversleuteld) met ", @@ -16,3 +19,4 @@ Language = { "Forcing clipping mode since scrollbars aren't supported by IE in fullscreen": "''Clipping mode' ingeschakeld, omdat schuifbalken in volledige-scherm-modus in IE niet worden ondersteund", "Disconnect timeout": "Timeout tijdens verbreken van verbinding", }; +}); diff --git a/app/locale/sv.js b/app/locale/sv.js index b7f4c1fb..6c70b68b 100644 --- a/app/locale/sv.js +++ b/app/locale/sv.js @@ -5,7 +5,10 @@ * DO NOT EDIT! */ -Language = { +"use strict"; + +define(function() { +return { "Connecting...": "Ansluter...", "Connected (encrypted) to ": "Ansluten (krypterat) till ", "Connected (unencrypted) to ": "Ansluten (okrypterat) till ", @@ -75,3 +78,4 @@ Language = { "Send Password": "Skicka Lösenord", "Canvas not supported.": "Canvas stöds ej", }; +}); diff --git a/app/novnc.js b/app/novnc.js new file mode 100644 index 00000000..601ada4d --- /dev/null +++ b/app/novnc.js @@ -0,0 +1,22 @@ +/* + * noVNC: HTML5 VNC client + * Copyright (C) 2017 Pierre Ossman for Cendio AB + * Licensed under MPL 2.0 (see LICENSE.txt) + * + * See README.md for usage and integration instructions. + */ + +/* jslint white: false, browser: true */ + +"use strict"; + +requirejs.config({ + baseUrl: '', +}); + +requirejs(['app/ui', 'core/util'], +function(ui, util) { + // Set up translations, then start the UI + var LINGUAS = ["de", "el", "nl", "sv"]; + util.Localisation.setup(LINGUAS, "app/locale", ui.load); +}); diff --git a/app/require.js b/app/require.js new file mode 100644 index 00000000..3eaa2a72 --- /dev/null +++ b/app/require.js @@ -0,0 +1,5 @@ +/** vim: et:ts=4:sw=4:sts=4 + * @license RequireJS 2.3.2 Copyright jQuery Foundation and other contributors. + * Released under MIT license, https://github.com/requirejs/requirejs/blob/master/LICENSE + */ +var requirejs,require,define;!function(global,setTimeout){function commentReplace(e,t){return t||""}function isFunction(e){return"[object Function]"===ostring.call(e)}function isArray(e){return"[object Array]"===ostring.call(e)}function each(e,t){if(e){var i;for(i=0;i-1&&(!e[i]||!t(e[i],i,e));i-=1);}}function hasProp(e,t){return hasOwn.call(e,t)}function getOwn(e,t){return hasProp(e,t)&&e[t]}function eachProp(e,t){var i;for(i in e)if(hasProp(e,i)&&t(e[i],i))break}function mixin(e,t,i,r){return t&&eachProp(t,function(t,n){!i&&hasProp(e,n)||(!r||"object"!=typeof t||!t||isArray(t)||isFunction(t)||t instanceof RegExp?e[n]=t:(e[n]||(e[n]={}),mixin(e[n],t,i,r)))}),e}function bind(e,t){return function(){return t.apply(e,arguments)}}function scripts(){return document.getElementsByTagName("script")}function defaultOnError(e){throw e}function getGlobal(e){if(!e)return e;var t=global;return each(e.split("."),function(e){t=t[e]}),t}function makeError(e,t,i,r){var n=new Error(t+"\nhttp://requirejs.org/docs/errors.html#"+e);return n.requireType=e,n.requireModules=r,i&&(n.originalError=i),n}function newContext(e){function t(e){var t,i;for(t=0;t0&&(e.splice(t-1,2),t-=2)}}function i(e,i,r){var n,o,a,s,u,c,d,p,f,l,h,m,g=i&&i.split("/"),v=y.map,x=v&&v["*"];if(e&&(e=e.split("/"),d=e.length-1,y.nodeIdCompat&&jsSuffixRegExp.test(e[d])&&(e[d]=e[d].replace(jsSuffixRegExp,"")),"."===e[0].charAt(0)&&g&&(m=g.slice(0,g.length-1),e=m.concat(e)),t(e),e=e.join("/")),r&&v&&(g||x)){a=e.split("/");e:for(s=a.length;s>0;s-=1){if(c=a.slice(0,s).join("/"),g)for(u=g.length;u>0;u-=1)if(o=getOwn(v,g.slice(0,u).join("/")),o&&(o=getOwn(o,c))){p=o,f=s;break e}!l&&x&&getOwn(x,c)&&(l=getOwn(x,c),h=s)}!p&&l&&(p=l,f=h),p&&(a.splice(0,f,p),e=a.join("/"))}return n=getOwn(y.pkgs,e),n?n:e}function r(e){isBrowser&&each(scripts(),function(t){if(t.getAttribute("data-requiremodule")===e&&t.getAttribute("data-requirecontext")===q.contextName)return t.parentNode.removeChild(t),!0})}function n(e){var t=getOwn(y.paths,e);if(t&&isArray(t)&&t.length>1)return t.shift(),q.require.undef(e),q.makeRequire(null,{skipMap:!0})([e]),!0}function o(e){var t,i=e?e.indexOf("!"):-1;return i>-1&&(t=e.substring(0,i),e=e.substring(i+1,e.length)),[t,e]}function a(e,t,r,n){var a,s,u,c,d=null,p=t?t.name:null,f=e,l=!0,h="";return e||(l=!1,e="_@r"+(T+=1)),c=o(e),d=c[0],e=c[1],d&&(d=i(d,p,n),s=getOwn(j,d)),e&&(d?h=s&&s.normalize?s.normalize(e,function(e){return i(e,p,n)}):e.indexOf("!")===-1?i(e,p,n):e:(h=i(e,p,n),c=o(h),d=c[0],h=c[1],r=!0,a=q.nameToUrl(h))),u=!d||s||r?"":"_unnormalized"+(A+=1),{prefix:d,name:h,parentMap:t,unnormalized:!!u,url:a,originalName:f,isDefine:l,id:(d?d+"!"+h:h)+u}}function s(e){var t=e.id,i=getOwn(S,t);return i||(i=S[t]=new q.Module(e)),i}function u(e,t,i){var r=e.id,n=getOwn(S,r);!hasProp(j,r)||n&&!n.defineEmitComplete?(n=s(e),n.error&&"error"===t?i(n.error):n.on(t,i)):"defined"===t&&i(j[r])}function c(e,t){var i=e.requireModules,r=!1;t?t(e):(each(i,function(t){var i=getOwn(S,t);i&&(i.error=e,i.events.error&&(r=!0,i.emit("error",e)))}),r||req.onError(e))}function d(){globalDefQueue.length&&(each(globalDefQueue,function(e){var t=e[0];"string"==typeof t&&(q.defQueueMap[t]=!0),O.push(e)}),globalDefQueue=[])}function p(e){delete S[e],delete k[e]}function f(e,t,i){var r=e.map.id;e.error?e.emit("error",e.error):(t[r]=!0,each(e.depMaps,function(r,n){var o=r.id,a=getOwn(S,o);!a||e.depMatched[n]||i[o]||(getOwn(t,o)?(e.defineDep(n,j[o]),e.check()):f(a,t,i))}),i[r]=!0)}function l(){var e,t,i=1e3*y.waitSeconds,o=i&&q.startTime+i<(new Date).getTime(),a=[],s=[],u=!1,d=!0;if(!x){if(x=!0,eachProp(k,function(e){var i=e.map,c=i.id;if(e.enabled&&(i.isDefine||s.push(e),!e.error))if(!e.inited&&o)n(c)?(t=!0,u=!0):(a.push(c),r(c));else if(!e.inited&&e.fetched&&i.isDefine&&(u=!0,!i.prefix))return d=!1}),o&&a.length)return e=makeError("timeout","Load timeout for modules: "+a,null,a),e.contextName=q.contextName,c(e);d&&each(s,function(e){f(e,{},{})}),o&&!t||!u||!isBrowser&&!isWebWorker||w||(w=setTimeout(function(){w=0,l()},50)),x=!1}}function h(e){hasProp(j,e[0])||s(a(e[0],null,!0)).init(e[1],e[2])}function m(e,t,i,r){e.detachEvent&&!isOpera?r&&e.detachEvent(r,t):e.removeEventListener(i,t,!1)}function g(e){var t=e.currentTarget||e.srcElement;return m(t,q.onScriptLoad,"load","onreadystatechange"),m(t,q.onScriptError,"error"),{node:t,id:t&&t.getAttribute("data-requiremodule")}}function v(){var e;for(d();O.length;){if(e=O.shift(),null===e[0])return c(makeError("mismatch","Mismatched anonymous define() module: "+e[e.length-1]));h(e)}q.defQueueMap={}}var x,b,q,E,w,y={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},S={},k={},M={},O=[],j={},P={},R={},T=1,A=1;return E={require:function(e){return e.require?e.require:e.require=q.makeRequire(e.map)},exports:function(e){if(e.usingExports=!0,e.map.isDefine)return e.exports?j[e.map.id]=e.exports:e.exports=j[e.map.id]={}},module:function(e){return e.module?e.module:e.module={id:e.map.id,uri:e.map.url,config:function(){return getOwn(y.config,e.map.id)||{}},exports:e.exports||(e.exports={})}}},b=function(e){this.events=getOwn(M,e.id)||{},this.map=e,this.shim=getOwn(y.shim,e.id),this.depExports=[],this.depMaps=[],this.depMatched=[],this.pluginMaps={},this.depCount=0},b.prototype={init:function(e,t,i,r){r=r||{},this.inited||(this.factory=t,i?this.on("error",i):this.events.error&&(i=bind(this,function(e){this.emit("error",e)})),this.depMaps=e&&e.slice(0),this.errback=i,this.inited=!0,this.ignore=r.ignore,r.enabled||this.enabled?this.enable():this.check())},defineDep:function(e,t){this.depMatched[e]||(this.depMatched[e]=!0,this.depCount-=1,this.depExports[e]=t)},fetch:function(){if(!this.fetched){this.fetched=!0,q.startTime=(new Date).getTime();var e=this.map;return this.shim?void q.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],bind(this,function(){return e.prefix?this.callPlugin():this.load()})):e.prefix?this.callPlugin():this.load()}},load:function(){var e=this.map.url;P[e]||(P[e]=!0,q.load(this.map.id,e))},check:function(){if(this.enabled&&!this.enabling){var e,t,i=this.map.id,r=this.depExports,n=this.exports,o=this.factory;if(this.inited){if(this.error)this.emit("error",this.error);else if(!this.defining){if(this.defining=!0,this.depCount<1&&!this.defined){if(isFunction(o)){if(this.events.error&&this.map.isDefine||req.onError!==defaultOnError)try{n=q.execCb(i,o,r,n)}catch(t){e=t}else n=q.execCb(i,o,r,n);if(this.map.isDefine&&void 0===n&&(t=this.module,t?n=t.exports:this.usingExports&&(n=this.exports)),e)return e.requireMap=this.map,e.requireModules=this.map.isDefine?[this.map.id]:null,e.requireType=this.map.isDefine?"define":"require",c(this.error=e)}else n=o;if(this.exports=n,this.map.isDefine&&!this.ignore&&(j[i]=n,req.onResourceLoad)){var a=[];each(this.depMaps,function(e){a.push(e.normalizedMap||e)}),req.onResourceLoad(q,this.map,a)}p(i),this.defined=!0}this.defining=!1,this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else hasProp(q.defQueueMap,i)||this.fetch()}},callPlugin:function(){var e=this.map,t=e.id,r=a(e.prefix);this.depMaps.push(r),u(r,"defined",bind(this,function(r){var n,o,d,f=getOwn(R,this.map.id),l=this.map.name,h=this.map.parentMap?this.map.parentMap.name:null,m=q.makeRequire(e.parentMap,{enableBuildCallback:!0});return this.map.unnormalized?(r.normalize&&(l=r.normalize(l,function(e){return i(e,h,!0)})||""),o=a(e.prefix+"!"+l,this.map.parentMap),u(o,"defined",bind(this,function(e){this.map.normalizedMap=o,this.init([],function(){return e},null,{enabled:!0,ignore:!0})})),d=getOwn(S,o.id),void(d&&(this.depMaps.push(o),this.events.error&&d.on("error",bind(this,function(e){this.emit("error",e)})),d.enable()))):f?(this.map.url=q.nameToUrl(f),void this.load()):(n=bind(this,function(e){this.init([],function(){return e},null,{enabled:!0})}),n.error=bind(this,function(e){this.inited=!0,this.error=e,e.requireModules=[t],eachProp(S,function(e){0===e.map.id.indexOf(t+"_unnormalized")&&p(e.map.id)}),c(e)}),n.fromText=bind(this,function(i,r){var o=e.name,u=a(o),d=useInteractive;r&&(i=r),d&&(useInteractive=!1),s(u),hasProp(y.config,t)&&(y.config[o]=y.config[t]);try{req.exec(i)}catch(e){return c(makeError("fromtexteval","fromText eval for "+t+" failed: "+e,e,[t]))}d&&(useInteractive=!0),this.depMaps.push(u),q.completeLoad(o),m([o],n)}),void r.load(e.name,m,n,y))})),q.enable(r,this),this.pluginMaps[r.id]=r},enable:function(){k[this.map.id]=this,this.enabled=!0,this.enabling=!0,each(this.depMaps,bind(this,function(e,t){var i,r,n;if("string"==typeof e){if(e=a(e,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap),this.depMaps[t]=e,n=getOwn(E,e.id))return void(this.depExports[t]=n(this));this.depCount+=1,u(e,"defined",bind(this,function(e){this.undefed||(this.defineDep(t,e),this.check())})),this.errback?u(e,"error",bind(this,this.errback)):this.events.error&&u(e,"error",bind(this,function(e){this.emit("error",e)}))}i=e.id,r=S[i],hasProp(E,i)||!r||r.enabled||q.enable(e,this)})),eachProp(this.pluginMaps,bind(this,function(e){var t=getOwn(S,e.id);t&&!t.enabled&&q.enable(e,this)})),this.enabling=!1,this.check()},on:function(e,t){var i=this.events[e];i||(i=this.events[e]=[]),i.push(t)},emit:function(e,t){each(this.events[e],function(e){e(t)}),"error"===e&&delete this.events[e]}},q={config:y,contextName:e,registry:S,defined:j,urlFetched:P,defQueue:O,defQueueMap:{},Module:b,makeModuleMap:a,nextTick:req.nextTick,onError:c,configure:function(e){if(e.baseUrl&&"/"!==e.baseUrl.charAt(e.baseUrl.length-1)&&(e.baseUrl+="/"),"string"==typeof e.urlArgs){var t=e.urlArgs;e.urlArgs=function(e,i){return(i.indexOf("?")===-1?"?":"&")+t}}var i=y.shim,r={paths:!0,bundles:!0,config:!0,map:!0};eachProp(e,function(e,t){r[t]?(y[t]||(y[t]={}),mixin(y[t],e,!0,!0)):y[t]=e}),e.bundles&&eachProp(e.bundles,function(e,t){each(e,function(e){e!==t&&(R[e]=t)})}),e.shim&&(eachProp(e.shim,function(e,t){isArray(e)&&(e={deps:e}),!e.exports&&!e.init||e.exportsFn||(e.exportsFn=q.makeShimExports(e)),i[t]=e}),y.shim=i),e.packages&&each(e.packages,function(e){var t,i;e="string"==typeof e?{name:e}:e,i=e.name,t=e.location,t&&(y.paths[i]=e.location),y.pkgs[i]=e.name+"/"+(e.main||"main").replace(currDirRegExp,"").replace(jsSuffixRegExp,"")}),eachProp(S,function(e,t){e.inited||e.map.unnormalized||(e.map=a(t,null,!0))}),(e.deps||e.callback)&&q.require(e.deps||[],e.callback)},makeShimExports:function(e){function t(){var t;return e.init&&(t=e.init.apply(global,arguments)),t||e.exports&&getGlobal(e.exports)}return t},makeRequire:function(t,n){function o(i,r,u){var d,p,f;return n.enableBuildCallback&&r&&isFunction(r)&&(r.__requireJsBuild=!0),"string"==typeof i?isFunction(r)?c(makeError("requireargs","Invalid require call"),u):t&&hasProp(E,i)?E[i](S[t.id]):req.get?req.get(q,i,t,o):(p=a(i,t,!1,!0),d=p.id,hasProp(j,d)?j[d]:c(makeError("notloaded",'Module name "'+d+'" has not been loaded yet for context: '+e+(t?"":". Use require([])")))):(v(),q.nextTick(function(){v(),f=s(a(null,t)),f.skipMap=n.skipMap,f.init(i,r,u,{enabled:!0}),l()}),o)}return n=n||{},mixin(o,{isBrowser:isBrowser,toUrl:function(e){var r,n=e.lastIndexOf("."),o=e.split("/")[0],a="."===o||".."===o;return n!==-1&&(!a||n>1)&&(r=e.substring(n,e.length),e=e.substring(0,n)),q.nameToUrl(i(e,t&&t.id,!0),r,!0)},defined:function(e){return hasProp(j,a(e,t,!1,!0).id)},specified:function(e){return e=a(e,t,!1,!0).id,hasProp(j,e)||hasProp(S,e)}}),t||(o.undef=function(e){d();var i=a(e,t,!0),n=getOwn(S,e);n.undefed=!0,r(e),delete j[e],delete P[i.url],delete M[e],eachReverse(O,function(t,i){t[0]===e&&O.splice(i,1)}),delete q.defQueueMap[e],n&&(n.events.defined&&(M[e]=n.events),p(e))}),o},enable:function(e){var t=getOwn(S,e.id);t&&s(e).enable()},completeLoad:function(e){var t,i,r,o=getOwn(y.shim,e)||{},a=o.exports;for(d();O.length;){if(i=O.shift(),null===i[0]){if(i[0]=e,t)break;t=!0}else i[0]===e&&(t=!0);h(i)}if(q.defQueueMap={},r=getOwn(S,e),!t&&!hasProp(j,e)&&r&&!r.inited){if(!(!y.enforceDefine||a&&getGlobal(a)))return n(e)?void 0:c(makeError("nodefine","No define call for "+e,null,[e]));h([e,o.deps||[],o.exportsFn])}l()},nameToUrl:function(e,t,i){var r,n,o,a,s,u,c,d=getOwn(y.pkgs,e);if(d&&(e=d),c=getOwn(R,e))return q.nameToUrl(c,t,i);if(req.jsExtRegExp.test(e))s=e+(t||"");else{for(r=y.paths,n=e.split("/"),o=n.length;o>0;o-=1)if(a=n.slice(0,o).join("/"),u=getOwn(r,a)){isArray(u)&&(u=u[0]),n.splice(0,o,u);break}s=n.join("/"),s+=t||(/^data\:|^blob\:|\?/.test(s)||i?"":".js"),s=("/"===s.charAt(0)||s.match(/^[\w\+\.\-]+:/)?"":y.baseUrl)+s}return y.urlArgs&&!/^blob\:/.test(s)?s+y.urlArgs(e,s):s},load:function(e,t){req.load(q,e,t)},execCb:function(e,t,i,r){return t.apply(r,i)},onScriptLoad:function(e){if("load"===e.type||readyRegExp.test((e.currentTarget||e.srcElement).readyState)){interactiveScript=null;var t=g(e);q.completeLoad(t.id)}},onScriptError:function(e){var t=g(e);if(!n(t.id)){var i=[];return eachProp(S,function(e,r){0!==r.indexOf("_@r")&&each(e.depMaps,function(e){if(e.id===t.id)return i.push(r),!0})}),c(makeError("scripterror",'Script error for "'+t.id+(i.length?'", needed by: '+i.join(", "):'"'),e,[t.id]))}}},q.require=q.makeRequire(),q}function getInteractiveScript(){return interactiveScript&&"interactive"===interactiveScript.readyState?interactiveScript:(eachReverse(scripts(),function(e){if("interactive"===e.readyState)return interactiveScript=e}),interactiveScript)}var req,s,head,baseElement,dataMain,src,interactiveScript,currentlyAddingScript,mainScript,subPath,version="2.3.2",commentRegExp=/\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm,cjsRequireRegExp=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,jsSuffixRegExp=/\.js$/,currDirRegExp=/^\.\//,op=Object.prototype,ostring=op.toString,hasOwn=op.hasOwnProperty,isBrowser=!("undefined"==typeof window||"undefined"==typeof navigator||!window.document),isWebWorker=!isBrowser&&"undefined"!=typeof importScripts,readyRegExp=isBrowser&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,defContextName="_",isOpera="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),contexts={},cfg={},globalDefQueue=[],useInteractive=!1;if("undefined"==typeof define){if("undefined"!=typeof requirejs){if(isFunction(requirejs))return;cfg=requirejs,requirejs=void 0}"undefined"==typeof require||isFunction(require)||(cfg=require,require=void 0),req=requirejs=function(e,t,i,r){var n,o,a=defContextName;return isArray(e)||"string"==typeof e||(o=e,isArray(t)?(e=t,t=i,i=r):e=[]),o&&o.context&&(a=o.context),n=getOwn(contexts,a),n||(n=contexts[a]=req.s.newContext(a)),o&&n.configure(o),n.require(e,t,i)},req.config=function(e){return req(e)},req.nextTick="undefined"!=typeof setTimeout?function(e){setTimeout(e,4)}:function(e){e()},require||(require=req),req.version=version,req.jsExtRegExp=/^\/|:|\?|\.js$/,req.isBrowser=isBrowser,s=req.s={contexts:contexts,newContext:newContext},req({}),each(["toUrl","undef","defined","specified"],function(e){req[e]=function(){var t=contexts[defContextName];return t.require[e].apply(t,arguments)}}),isBrowser&&(head=s.head=document.getElementsByTagName("head")[0],baseElement=document.getElementsByTagName("base")[0],baseElement&&(head=s.head=baseElement.parentNode)),req.onError=defaultOnError,req.createNode=function(e,t,i){var r=e.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");return r.type=e.scriptType||"text/javascript",r.charset="utf-8",r.async=!0,r},req.load=function(e,t,i){var r,n=e&&e.config||{};if(isBrowser)return r=req.createNode(n,t,i),r.setAttribute("data-requirecontext",e.contextName),r.setAttribute("data-requiremodule",t),!r.attachEvent||r.attachEvent.toString&&r.attachEvent.toString().indexOf("[native code")<0||isOpera?(r.addEventListener("load",e.onScriptLoad,!1),r.addEventListener("error",e.onScriptError,!1)):(useInteractive=!0,r.attachEvent("onreadystatechange",e.onScriptLoad)),r.src=i,n.onNodeCreated&&n.onNodeCreated(r,n,t,i),currentlyAddingScript=r,baseElement?head.insertBefore(r,baseElement):head.appendChild(r),currentlyAddingScript=null,r;if(isWebWorker)try{setTimeout(function(){},0),importScripts(i),e.completeLoad(t)}catch(r){e.onError(makeError("importscripts","importScripts failed for "+t+" at "+i,r,[t]))}},isBrowser&&!cfg.skipDataMain&&eachReverse(scripts(),function(e){if(head||(head=e.parentNode),dataMain=e.getAttribute("data-main"))return mainScript=dataMain,cfg.baseUrl||mainScript.indexOf("!")!==-1||(src=mainScript.split("/"),mainScript=src.pop(),subPath=src.length?src.join("/")+"/":"./",cfg.baseUrl=subPath),mainScript=mainScript.replace(jsSuffixRegExp,""),req.jsExtRegExp.test(mainScript)&&(mainScript=dataMain),cfg.deps=cfg.deps?cfg.deps.concat(mainScript):[mainScript],!0}),define=function(e,t,i){var r,n;"string"!=typeof e&&(i=t,t=e,e=null),isArray(t)||(i=t,t=null),!t&&isFunction(i)&&(t=[],i.length&&(i.toString().replace(commentRegExp,commentReplace).replace(cjsRequireRegExp,function(e,i){t.push(i)}),t=(1===i.length?["require"]:["require","exports","module"]).concat(t))),useInteractive&&(r=currentlyAddingScript||getInteractiveScript(),r&&(e||(e=r.getAttribute("data-requiremodule")),n=contexts[r.getAttribute("data-requirecontext")])),n?(n.defQueue.push([e,t,i]),n.defQueueMap[e]=!0):globalDefQueue.push([e,t,i])},define.amd={jQuery:!0},req.exec=function(text){return eval(text)},req(cfg)}}(this,"undefined"==typeof setTimeout?void 0:setTimeout); \ No newline at end of file diff --git a/app/ui.js b/app/ui.js index 7dbbac9d..1d323418 100644 --- a/app/ui.js +++ b/app/ui.js @@ -2,29 +2,19 @@ * noVNC: HTML5 VNC client * Copyright (C) 2012 Joel Martin * Copyright (C) 2016 Samuel Mannehed for Cendio AB - * Copyright (C) 2016 Pierre Ossman for Cendio AB + * Copyright (C) 2017 Pierre Ossman for Cendio AB * Licensed under MPL 2.0 (see LICENSE.txt) * * See README.md for usage and integration instructions. */ /* jslint white: false, browser: true */ -/* global window, document.getElementById, Util, WebUtil, RFB, Display */ - -/* [module] - * import Util from "../core/util"; - * import KeyTable from "../core/input/keysym"; - * import keysyms from "./keysymdef"; - * import RFB from "../core/rfb"; - * import Display from "../core/display"; - * import WebUtil from "./webutil"; - */ "use strict"; -var UI; - -(function () { +define(["app/webutil", "core/rfb", "core/util", + "core/input/keysym", "core/input/keysymdef"], +function (WebUtil, rfb, Util, KeyTable, keysyms) { // Fallback for all uncought errors window.addEventListener('error', function(event) { @@ -66,27 +56,9 @@ var UI; return false; }); - // Set up translations - var LINGUAS = ["de", "el", "nl", "sv"]; - Util.Localisation.setup(LINGUAS); - if (Util.Localisation.language !== "en") { - WebUtil.load_scripts( - {'app': ["locale/" + Util.Localisation.language + ".js"]}); - } - - /* [begin skip-as-module] */ - // Load supporting scripts - WebUtil.load_scripts( - {'core': ["base64.js", "websock.js", "des.js", "input/keysymdef.js", - "input/xtscancodes.js", "input/util.js", "input/devices.js", - "display.js", "inflator.js", "rfb.js", "input/keysym.js"]}); - - window.onscriptsload = function () { UI.load(); }; - /* [end skip-as-module] */ - var _ = Util.Localisation.get; - UI = { + var UI = { connected: false, desktopName: "", @@ -390,17 +362,17 @@ var UI; initRFB: function() { try { - UI.rfb = new RFB({'target': document.getElementById('noVNC_canvas'), - 'onNotification': UI.notification, - 'onUpdateState': UI.updateState, - 'onDisconnected': UI.disconnectFinished, - 'onPasswordRequired': UI.passwordRequired, - 'onXvpInit': UI.updateXvpButton, - 'onClipboard': UI.clipboardReceive, - 'onBell': UI.bell, - 'onFBUComplete': UI.initialResize, - 'onFBResize': UI.updateSessionSize, - 'onDesktopName': UI.updateDesktopName}); + UI.rfb = new rfb.RFB({'target': document.getElementById('noVNC_canvas'), + 'onNotification': UI.notification, + 'onUpdateState': UI.updateState, + 'onDisconnected': UI.disconnectFinished, + 'onPasswordRequired': UI.passwordRequired, + 'onXvpInit': UI.updateXvpButton, + 'onClipboard': UI.clipboardReceive, + 'onBell': UI.bell, + 'onFBUComplete': UI.initialResize, + 'onFBResize': UI.updateSessionSize, + 'onDesktopName': UI.updateDesktopName}); return true; } catch (exc) { var msg = "Unable to create RFB client -- " + exc; @@ -1679,7 +1651,5 @@ var UI; */ }; - /* [module] UI.load(); */ -})(); - -/* [module] export default UI; */ + return UI; +}); diff --git a/app/webutil.js b/app/webutil.js index 0bc7c627..71b41cd9 100644 --- a/app/webutil.js +++ b/app/webutil.js @@ -2,393 +2,316 @@ * noVNC: HTML5 VNC client * Copyright (C) 2012 Joel Martin * Copyright (C) 2013 NTT corp. + * Copyright (C) 2017 Pierre Ossman for Cendio AB * Licensed under MPL 2.0 (see LICENSE.txt) * * See README.md for usage and integration instructions. */ /*jslint bitwise: false, white: false, browser: true, devel: true */ -/*global Util, window, document */ - -/* [module] - * import Util from "../core/util"; - */ "use strict"; -// Globals defined here -var WebUtil = {}; +define(['core/util'], +function(Util) { + var WebUtil = {}; -/* - * ------------------------------------------------------ - * 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 { - var param = document.location.href.match(/logging=([A-Za-z0-9\._\-]*)/); - Util._log_level = (param || ['', Util._log_level])[1]; - } - Util.init_logging(); -}; - - -WebUtil.dirObj = function (obj, depth, parent) { - if (! depth) { depth = 2; } - if (! parent) { parent = ""; } - - // Print the properties of the passed-in object - var msg = ""; - for (var 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", " "); - var val = ""; - 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"; + // init log level reading the logging HTTP param + WebUtil.init_logging = function (level) { + if (typeof level === "undefined") { + var param = document.location.href.match(/logging=([A-Za-z0-9\._\-]*)/); + if (param !== undefined) + level = param; } - } - return msg; -}; + Util.init_logging(level); + }; -// 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; - } -}; -// Read a hash fragment variable -WebUtil.getHashVar = function (name, defVal) { - var re = new RegExp('.*[&#]' + name + '=([^&]*)'), - match = document.location.hash.match(re); - if (typeof defVal === 'undefined') { defVal = null; } - if (match) { - return decodeURIComponent(match[1]); - } else { - return defVal; - } -}; + WebUtil.dirObj = function (obj, depth, parent) { + if (! depth) { depth = 2; } + if (! parent) { parent = ""; } -// Read a variable from the fragment or the query string -// Fragment takes precedence -WebUtil.getConfigVar = function (name, defVal) { - var val = WebUtil.getHashVar(name); - if (val === null) { - val = WebUtil.getQueryVar(name, defVal); - } - return val; -}; + // Print the properties of the passed-in object + var msg = ""; + for (var 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", " "); + var val = ""; + 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; + }; -/* - * Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html - */ + // 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; + } + }; -// 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 = ""; - } + // Read a hash fragment variable + WebUtil.getHashVar = function (name, defVal) { + var re = new RegExp('.*[&#]' + name + '=([^&]*)'), + match = document.location.hash.match(re); + if (typeof defVal === 'undefined') { defVal = null; } + if (match) { + return decodeURIComponent(match[1]); + } else { + return defVal; + } + }; - var secure; - if (document.location.protocol === "https:") { - secure = "; secure"; - } else { - secure = ""; - } - document.cookie = name + "=" + value + expires + "; path=/" + secure; -}; + // Read a variable from the fragment or the query string + // Fragment takes precedence + WebUtil.getConfigVar = function (name, defVal) { + var val = WebUtil.getHashVar(name); + if (val === null) { + val = WebUtil.getQueryVar(name, defVal); + } + return val; + }; -WebUtil.readCookie = function (name, defaultValue) { - var nameEQ = name + "=", - ca = document.cookie.split(';'); + /* + * Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html + */ - for (var i = 0; i < ca.length; i += 1) { - var 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; -}; + // 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 = ""; + } -WebUtil.eraseCookie = function (name) { - WebUtil.createCookie(name, "", -1); -}; + var secure; + if (document.location.protocol === "https:") { + secure = "; secure"; + } else { + secure = ""; + } + document.cookie = name + "=" + value + expires + "; path=/" + secure; + }; -/* - * Setting handling. - */ + WebUtil.readCookie = function (name, defaultValue) { + var nameEQ = name + "=", + ca = document.cookie.split(';'); -WebUtil.initSettings = function (callback /*, ...callbackArgs */) { - 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); + for (var i = 0; i < ca.length; i += 1) { + var 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 /*, ...callbackArgs */) { + 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); } - }); - } 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); - } -}; - -WebUtil.injectParamIfMissing = function (path, param, value) { - // force pretend that we're dealing with a relative path - // (assume that we wanted an extra if we pass one in) - path = "/" + path; - - var elem = document.createElement('a'); - elem.href = path; - - var param_eq = encodeURIComponent(param) + "="; - var query; - if (elem.search) { - query = elem.search.slice(1).split('&'); - } else { - query = []; - } - - if (!query.some(function (v) { return v.startsWith(param_eq); })) { - query.push(param_eq + encodeURIComponent(value)); - elem.search = "?" + query.join("&"); - } - - // some browsers (e.g. IE11) may occasionally omit the leading slash - // in the elem.pathname string. Handle that case gracefully. - if (elem.pathname.charAt(0) == "/") { - return elem.pathname.slice(1) + elem.search + elem.hash; - } else { - return elem.pathname + elem.search + elem.hash; - } -}; - -// Emulate Element.setCapture() when not supported - -WebUtil._captureRecursion = false; -WebUtil._captureProxy = function (e) { - // Recursion protection as we'll see our own event - if (WebUtil._captureRecursion) return; - - // Clone the event as we cannot dispatch an already dispatched event - var newEv = new e.constructor(e.type, e); - - WebUtil._captureRecursion = true; - WebUtil._captureElem.dispatchEvent(newEv); - WebUtil._captureRecursion = false; - - // Implicitly release the capture on button release - if ((e.type === "mouseup") || (e.type === "touchend")) { - WebUtil.releaseCapture(); - } -}; - -WebUtil.setCapture = function (elem) { - if (elem.setCapture) { - - elem.setCapture(); - - // IE releases capture on 'click' events which might not trigger - elem.addEventListener('mouseup', WebUtil.releaseCapture); - elem.addEventListener('touchend', WebUtil.releaseCapture); - - } else { - // Safari on iOS 9 has a broken constructor for TouchEvent. - // We are fine in this case however, since Safari seems to - // have some sort of implicit setCapture magic anyway. - if (window.TouchEvent !== undefined) { - try { - new TouchEvent("touchstart"); - } catch (TypeError) { - return; - } - } - - var captureElem = document.getElementById("noVNC_mouse_capture_elem"); - - if (captureElem === null) { - captureElem = document.createElement("div"); - captureElem.id = "noVNC_mouse_capture_elem"; - captureElem.style.position = "fixed"; - captureElem.style.top = "0px"; - captureElem.style.left = "0px"; - captureElem.style.width = "100%"; - captureElem.style.height = "100%"; - captureElem.style.zIndex = 10000; - captureElem.style.display = "none"; - document.body.appendChild(captureElem); - - captureElem.addEventListener('mousemove', WebUtil._captureProxy); - captureElem.addEventListener('mouseup', WebUtil._captureProxy); - - captureElem.addEventListener('touchmove', WebUtil._captureProxy); - captureElem.addEventListener('touchend', WebUtil._captureProxy); - } - - WebUtil._captureElem = elem; - captureElem.style.display = null; - - // We listen to events on window in order to keep tracking if it - // happens to leave the viewport - window.addEventListener('mousemove', WebUtil._captureProxy); - window.addEventListener('mouseup', WebUtil._captureProxy); - - window.addEventListener('touchmove', WebUtil._captureProxy); - window.addEventListener('touchend', WebUtil._captureProxy); - } -}; - -WebUtil.releaseCapture = function () { - if (document.releaseCapture) { - - document.releaseCapture(); - - } else { - var captureElem = document.getElementById("noVNC_mouse_capture_elem"); - WebUtil._captureElem = null; - captureElem.style.display = "none"; - - window.removeEventListener('mousemove', WebUtil._captureProxy); - window.removeEventListener('mouseup', WebUtil._captureProxy); - - window.removeEventListener('touchmove', WebUtil._captureProxy); - window.removeEventListener('touchend', WebUtil._captureProxy); - } -}; - - -// Dynamically load scripts without using document.write() -// Reference: http://unixpapa.com/js/dyna.html -// -// Handles the case where load_scripts is invoked from a script that -// itself is loaded via load_scripts. Once all scripts are loaded the -// window.onscriptsloaded handler is called (if set). -WebUtil.get_include_uri = function (root_dir) { - return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI + root_dir + '/' : root_dir + '/'; -}; -WebUtil._loading_scripts = []; -WebUtil._pending_scripts = []; -WebUtil.load_scripts = function (files_by_dir) { - var head = document.getElementsByTagName('head')[0], script, - ls = WebUtil._loading_scripts, ps = WebUtil._pending_scripts; - - var loadFunc = function (e) { - while (ls.length > 0 && (ls[0].readyState === 'loaded' || - ls[0].readyState === 'complete')) { - // For IE, append the script to trigger execution - var s = ls.shift(); - //console.log("loaded script: " + s.src); - head.appendChild(s); - } - if (!this.readyState || - (Util.Engine.presto && this.readyState === 'loaded') || - this.readyState === 'complete') { - if (ps.indexOf(this) >= 0) { - this.onload = this.onreadystatechange = null; - //console.log("completed script: " + this.src); - ps.splice(ps.indexOf(this), 1); - - // Call window.onscriptsload after last script loads - if (ps.length === 0 && window.onscriptsload) { - window.onscriptsload(); - } - } } }; - var root_dirs = Object.keys(files_by_dir); - - for (var d = 0; d < root_dirs.length; d++) { - var root_dir = root_dirs[d]; - var files = files_by_dir[root_dir]; - - for (var f = 0; f < files.length; f++) { - script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = WebUtil.get_include_uri(root_dir) + files[f]; - //console.log("loading script: " + script.src); - script.onload = script.onreadystatechange = loadFunc; - // In-order script execution tricks - if (Util.Engine.trident) { - // For IE wait until readyState is 'loaded' before - // appending it which will trigger execution - // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order - ls.push(script); - } else { - // For webkit and firefox set async=false and append now - // https://developer.mozilla.org/en-US/docs/HTML/Element/script - script.async = false; - head.appendChild(script); + // 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); } - ps.push(script); + } else { + localStorage.setItem(name, value); } - } -}; + }; -/* [module] export default WebUtil; */ + 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); + } + }; + + WebUtil.injectParamIfMissing = function (path, param, value) { + // force pretend that we're dealing with a relative path + // (assume that we wanted an extra if we pass one in) + path = "/" + path; + + var elem = document.createElement('a'); + elem.href = path; + + var param_eq = encodeURIComponent(param) + "="; + var query; + if (elem.search) { + query = elem.search.slice(1).split('&'); + } else { + query = []; + } + + if (!query.some(function (v) { return v.startsWith(param_eq); })) { + query.push(param_eq + encodeURIComponent(value)); + elem.search = "?" + query.join("&"); + } + + // some browsers (e.g. IE11) may occasionally omit the leading slash + // in the elem.pathname string. Handle that case gracefully. + if (elem.pathname.charAt(0) == "/") { + return elem.pathname.slice(1) + elem.search + elem.hash; + } else { + return elem.pathname + elem.search + elem.hash; + } + }; + + // Emulate Element.setCapture() when not supported + + var _captureElem; + var _captureRecursion = false; + var _captureProxy = function (e) { + // Recursion protection as we'll see our own event + if (_captureRecursion) return; + + // Clone the event as we cannot dispatch an already dispatched event + var newEv = new e.constructor(e.type, e); + + _captureRecursion = true; + _captureElem.dispatchEvent(newEv); + _captureRecursion = false; + + // Implicitly release the capture on button release + if ((e.type === "mouseup") || (e.type === "touchend")) { + WebUtil.releaseCapture(); + } + }; + + WebUtil.setCapture = function (elem) { + if (elem.setCapture) { + + elem.setCapture(); + + // IE releases capture on 'click' events which might not trigger + elem.addEventListener('mouseup', WebUtil.releaseCapture); + elem.addEventListener('touchend', WebUtil.releaseCapture); + + } else { + // Safari on iOS 9 has a broken constructor for TouchEvent. + // We are fine in this case however, since Safari seems to + // have some sort of implicit setCapture magic anyway. + if (window.TouchEvent !== undefined) { + try { + new TouchEvent("touchstart"); + } catch (TypeError) { + return; + } + } + + var captureElem = document.getElementById("noVNC_mouse_capture_elem"); + + if (captureElem === null) { + captureElem = document.createElement("div"); + captureElem.id = "noVNC_mouse_capture_elem"; + captureElem.style.position = "fixed"; + captureElem.style.top = "0px"; + captureElem.style.left = "0px"; + captureElem.style.width = "100%"; + captureElem.style.height = "100%"; + captureElem.style.zIndex = 10000; + captureElem.style.display = "none"; + document.body.appendChild(captureElem); + + captureElem.addEventListener('mousemove', _captureProxy); + captureElem.addEventListener('mouseup', _captureProxy); + + captureElem.addEventListener('touchmove', _captureProxy); + captureElem.addEventListener('touchend', _captureProxy); + } + + _captureElem = elem; + captureElem.style.display = null; + + // We listen to events on window in order to keep tracking if it + // happens to leave the viewport + window.addEventListener('mousemove', _captureProxy); + window.addEventListener('mouseup', _captureProxy); + + window.addEventListener('touchmove', _captureProxy); + window.addEventListener('touchend', _captureProxy); + } + }; + + WebUtil.releaseCapture = function () { + if (document.releaseCapture) { + + document.releaseCapture(); + + } else { + var captureElem = document.getElementById("noVNC_mouse_capture_elem"); + _captureElem = null; + captureElem.style.display = "none"; + + window.removeEventListener('mousemove', _captureProxy); + window.removeEventListener('mouseup', _captureProxy); + + window.removeEventListener('touchmove', _captureProxy); + window.removeEventListener('touchend', _captureProxy); + } + }; + + return WebUtil; +}); diff --git a/core/base64.js b/core/base64.js index 8f34cb54..fea070c6 100644 --- a/core/base64.js +++ b/core/base64.js @@ -5,113 +5,114 @@ // From: http://hg.mozilla.org/mozilla-central/raw-file/ec10630b1a54/js/src/devtools/jint/sunspider/string-base64.js /*jslint white: false */ -/*global console */ "use strict"; -var Base64 = { - /* Convert data (an array of integers) to a Base64 string. */ - toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''), - base64Pad : '=', +define(function () { + var Base64 = { + /* Convert data (an array of integers) to a Base64 string. */ + toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''), + base64Pad : '=', - encode: function (data) { - "use strict"; - var result = ''; - var toBase64Table = Base64.toBase64Table; - var length = data.length; - var lengthpad = (length % 3); - // Convert every three bytes to 4 ascii characters. + encode: function (data) { + "use strict"; + var result = ''; + var toBase64Table = Base64.toBase64Table; + var length = data.length; + var lengthpad = (length % 3); + // Convert every three bytes to 4 ascii characters. - for (var i = 0; i < (length - 2); i += 3) { - result += toBase64Table[data[i] >> 2]; - result += toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)]; - result += toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)]; - result += toBase64Table[data[i + 2] & 0x3f]; - } - - // Convert the remaining 1 or 2 bytes, pad out to 4 characters. - var j = 0; - if (lengthpad === 2) { - j = length - lengthpad; - result += toBase64Table[data[j] >> 2]; - result += toBase64Table[((data[j] & 0x03) << 4) + (data[j + 1] >> 4)]; - result += toBase64Table[(data[j + 1] & 0x0f) << 2]; - result += toBase64Table[64]; - } else if (lengthpad === 1) { - j = length - lengthpad; - result += toBase64Table[data[j] >> 2]; - result += toBase64Table[(data[j] & 0x03) << 4]; - result += toBase64Table[64]; - result += toBase64Table[64]; - } - - return result; - }, - - /* Convert Base64 data to a string */ - /* jshint -W013 */ - toBinaryTable : [ - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, - 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, - 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, - -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, - 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 - ], - /* jshint +W013 */ - - decode: function (data, offset) { - "use strict"; - offset = typeof(offset) !== 'undefined' ? offset : 0; - var toBinaryTable = Base64.toBinaryTable; - var base64Pad = Base64.base64Pad; - var result, result_length; - var leftbits = 0; // number of bits decoded, but yet to be appended - var leftdata = 0; // bits decoded, but yet to be appended - var data_length = data.indexOf('=') - offset; - - if (data_length < 0) { data_length = data.length - offset; } - - /* Every four characters is 3 resulting numbers */ - result_length = (data_length >> 2) * 3 + Math.floor((data_length % 4) / 1.5); - result = new Array(result_length); - - // Convert one by one. - for (var idx = 0, i = offset; i < data.length; i++) { - var c = toBinaryTable[data.charCodeAt(i) & 0x7f]; - var padding = (data.charAt(i) === base64Pad); - // Skip illegal characters and whitespace - if (c === -1) { - console.error("Illegal character code " + data.charCodeAt(i) + " at position " + i); - continue; + for (var i = 0; i < (length - 2); i += 3) { + result += toBase64Table[data[i] >> 2]; + result += toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)]; + result += toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)]; + result += toBase64Table[data[i + 2] & 0x3f]; } - // Collect data into leftdata, update bitcount - leftdata = (leftdata << 6) | c; - leftbits += 6; + // Convert the remaining 1 or 2 bytes, pad out to 4 characters. + var j = 0; + if (lengthpad === 2) { + j = length - lengthpad; + result += toBase64Table[data[j] >> 2]; + result += toBase64Table[((data[j] & 0x03) << 4) + (data[j + 1] >> 4)]; + result += toBase64Table[(data[j + 1] & 0x0f) << 2]; + result += toBase64Table[64]; + } else if (lengthpad === 1) { + j = length - lengthpad; + result += toBase64Table[data[j] >> 2]; + result += toBase64Table[(data[j] & 0x03) << 4]; + result += toBase64Table[64]; + result += toBase64Table[64]; + } - // If we have 8 or more bits, append 8 bits to the result - if (leftbits >= 8) { - leftbits -= 8; - // Append if not padding. - if (!padding) { - result[idx++] = (leftdata >> leftbits) & 0xff; + return result; + }, + + /* Convert Base64 data to a string */ + /* jshint -W013 */ + toBinaryTable : [ + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 + ], + /* jshint +W013 */ + + decode: function (data, offset) { + "use strict"; + offset = typeof(offset) !== 'undefined' ? offset : 0; + var toBinaryTable = Base64.toBinaryTable; + var base64Pad = Base64.base64Pad; + var result, result_length; + var leftbits = 0; // number of bits decoded, but yet to be appended + var leftdata = 0; // bits decoded, but yet to be appended + var data_length = data.indexOf('=') - offset; + + if (data_length < 0) { data_length = data.length - offset; } + + /* Every four characters is 3 resulting numbers */ + result_length = (data_length >> 2) * 3 + Math.floor((data_length % 4) / 1.5); + result = new Array(result_length); + + // Convert one by one. + for (var idx = 0, i = offset; i < data.length; i++) { + var c = toBinaryTable[data.charCodeAt(i) & 0x7f]; + var padding = (data.charAt(i) === base64Pad); + // Skip illegal characters and whitespace + if (c === -1) { + console.error("Illegal character code " + data.charCodeAt(i) + " at position " + i); + continue; + } + + // Collect data into leftdata, update bitcount + leftdata = (leftdata << 6) | c; + leftbits += 6; + + // If we have 8 or more bits, append 8 bits to the result + if (leftbits >= 8) { + leftbits -= 8; + // Append if not padding. + if (!padding) { + result[idx++] = (leftdata >> leftbits) & 0xff; + } + leftdata &= (1 << leftbits) - 1; } - leftdata &= (1 << leftbits) - 1; } + + // If there are any bits left, the base64 string was corrupted + if (leftbits) { + err = new Error('Corrupted base64 string'); + err.name = 'Base64-Error'; + throw err; + } + + return result; } + }; - // If there are any bits left, the base64 string was corrupted - if (leftbits) { - err = new Error('Corrupted base64 string'); - err.name = 'Base64-Error'; - throw err; - } - - return result; - } -}; /* End of Base64 namespace */ - -/* [module] export default Base64; */ + return Base64; +}); diff --git a/core/des.js b/core/des.js index cc5e6b44..f56cc75c 100644 --- a/core/des.js +++ b/core/des.js @@ -79,199 +79,202 @@ "use strict"; -/* [module] export default */ function DES(passwd) { +define(function () { + function DES(passwd) { + // Tables, permutations, S-boxes, etc. + // jshint -W013 + var PC2 = [13,16,10,23, 0, 4, 2,27,14, 5,20, 9,22,18,11, 3, + 25, 7,15, 6,26,19,12, 1,40,51,30,36,46,54,29,39, + 50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31 ], + totrot = [ 1, 2, 4, 6, 8,10,12,14,15,17,19,21,23,25,27,28], + z = 0x0, a,b,c,d,e,f, SP1,SP2,SP3,SP4,SP5,SP6,SP7,SP8, + keys = []; - // Tables, permutations, S-boxes, etc. - // jshint -W013 - var PC2 = [13,16,10,23, 0, 4, 2,27,14, 5,20, 9,22,18,11, 3, - 25, 7,15, 6,26,19,12, 1,40,51,30,36,46,54,29,39, - 50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31 ], - totrot = [ 1, 2, 4, 6, 8,10,12,14,15,17,19,21,23,25,27,28], - z = 0x0, a,b,c,d,e,f, SP1,SP2,SP3,SP4,SP5,SP6,SP7,SP8, - keys = []; + // jshint -W015 + a=1<<16; b=1<<24; c=a|b; d=1<<2; e=1<<10; f=d|e; + SP1 = [c|e,z|z,a|z,c|f,c|d,a|f,z|d,a|z,z|e,c|e,c|f,z|e,b|f,c|d,b|z,z|d, + z|f,b|e,b|e,a|e,a|e,c|z,c|z,b|f,a|d,b|d,b|d,a|d,z|z,z|f,a|f,b|z, + a|z,c|f,z|d,c|z,c|e,b|z,b|z,z|e,c|d,a|z,a|e,b|d,z|e,z|d,b|f,a|f, + c|f,a|d,c|z,b|f,b|d,z|f,a|f,c|e,z|f,b|e,b|e,z|z,a|d,a|e,z|z,c|d]; + a=1<<20; b=1<<31; c=a|b; d=1<<5; e=1<<15; f=d|e; + SP2 = [c|f,b|e,z|e,a|f,a|z,z|d,c|d,b|f,b|d,c|f,c|e,b|z,b|e,a|z,z|d,c|d, + a|e,a|d,b|f,z|z,b|z,z|e,a|f,c|z,a|d,b|d,z|z,a|e,z|f,c|e,c|z,z|f, + z|z,a|f,c|d,a|z,b|f,c|z,c|e,z|e,c|z,b|e,z|d,c|f,a|f,z|d,z|e,b|z, + z|f,c|e,a|z,b|d,a|d,b|f,b|d,a|d,a|e,z|z,b|e,z|f,b|z,c|d,c|f,a|e]; + a=1<<17; b=1<<27; c=a|b; d=1<<3; e=1<<9; f=d|e; + SP3 = [z|f,c|e,z|z,c|d,b|e,z|z,a|f,b|e,a|d,b|d,b|d,a|z,c|f,a|d,c|z,z|f, + b|z,z|d,c|e,z|e,a|e,c|z,c|d,a|f,b|f,a|e,a|z,b|f,z|d,c|f,z|e,b|z, + c|e,b|z,a|d,z|f,a|z,c|e,b|e,z|z,z|e,a|d,c|f,b|e,b|d,z|e,z|z,c|d, + b|f,a|z,b|z,c|f,z|d,a|f,a|e,b|d,c|z,b|f,z|f,c|z,a|f,z|d,c|d,a|e]; + a=1<<13; b=1<<23; c=a|b; d=1<<0; e=1<<7; f=d|e; + SP4 = [c|d,a|f,a|f,z|e,c|e,b|f,b|d,a|d,z|z,c|z,c|z,c|f,z|f,z|z,b|e,b|d, + z|d,a|z,b|z,c|d,z|e,b|z,a|d,a|e,b|f,z|d,a|e,b|e,a|z,c|e,c|f,z|f, + b|e,b|d,c|z,c|f,z|f,z|z,z|z,c|z,a|e,b|e,b|f,z|d,c|d,a|f,a|f,z|e, + c|f,z|f,z|d,a|z,b|d,a|d,c|e,b|f,a|d,a|e,b|z,c|d,z|e,b|z,a|z,c|e]; + a=1<<25; b=1<<30; c=a|b; d=1<<8; e=1<<19; f=d|e; + SP5 = [z|d,a|f,a|e,c|d,z|e,z|d,b|z,a|e,b|f,z|e,a|d,b|f,c|d,c|e,z|f,b|z, + a|z,b|e,b|e,z|z,b|d,c|f,c|f,a|d,c|e,b|d,z|z,c|z,a|f,a|z,c|z,z|f, + z|e,c|d,z|d,a|z,b|z,a|e,c|d,b|f,a|d,b|z,c|e,a|f,b|f,z|d,a|z,c|e, + c|f,z|f,c|z,c|f,a|e,z|z,b|e,c|z,z|f,a|d,b|d,z|e,z|z,b|e,a|f,b|d]; + a=1<<22; b=1<<29; c=a|b; d=1<<4; e=1<<14; f=d|e; + SP6 = [b|d,c|z,z|e,c|f,c|z,z|d,c|f,a|z,b|e,a|f,a|z,b|d,a|d,b|e,b|z,z|f, + z|z,a|d,b|f,z|e,a|e,b|f,z|d,c|d,c|d,z|z,a|f,c|e,z|f,a|e,c|e,b|z, + b|e,z|d,c|d,a|e,c|f,a|z,z|f,b|d,a|z,b|e,b|z,z|f,b|d,c|f,a|e,c|z, + a|f,c|e,z|z,c|d,z|d,z|e,c|z,a|f,z|e,a|d,b|f,z|z,c|e,b|z,a|d,b|f]; + a=1<<21; b=1<<26; c=a|b; d=1<<1; e=1<<11; f=d|e; + SP7 = [a|z,c|d,b|f,z|z,z|e,b|f,a|f,c|e,c|f,a|z,z|z,b|d,z|d,b|z,c|d,z|f, + b|e,a|f,a|d,b|e,b|d,c|z,c|e,a|d,c|z,z|e,z|f,c|f,a|e,z|d,b|z,a|e, + b|z,a|e,a|z,b|f,b|f,c|d,c|d,z|d,a|d,b|z,b|e,a|z,c|e,z|f,a|f,c|e, + z|f,b|d,c|f,c|z,a|e,z|z,z|d,c|f,z|z,a|f,c|z,z|e,b|d,b|e,z|e,a|d]; + a=1<<18; b=1<<28; c=a|b; d=1<<6; e=1<<12; f=d|e; + SP8 = [b|f,z|e,a|z,c|f,b|z,b|f,z|d,b|z,a|d,c|z,c|f,a|e,c|e,a|f,z|e,z|d, + c|z,b|d,b|e,z|f,a|e,a|d,c|d,c|e,z|f,z|z,z|z,c|d,b|d,b|e,a|f,a|z, + a|f,a|z,c|e,z|e,z|d,c|d,z|e,a|f,b|e,z|d,b|d,c|z,c|d,b|z,a|z,b|f, + z|z,c|f,a|d,b|d,c|z,b|e,b|f,z|z,c|f,a|e,a|e,z|f,z|f,a|d,b|z,c|e]; + // jshint +W013,+W015 - // jshint -W015 - a=1<<16; b=1<<24; c=a|b; d=1<<2; e=1<<10; f=d|e; - SP1 = [c|e,z|z,a|z,c|f,c|d,a|f,z|d,a|z,z|e,c|e,c|f,z|e,b|f,c|d,b|z,z|d, - z|f,b|e,b|e,a|e,a|e,c|z,c|z,b|f,a|d,b|d,b|d,a|d,z|z,z|f,a|f,b|z, - a|z,c|f,z|d,c|z,c|e,b|z,b|z,z|e,c|d,a|z,a|e,b|d,z|e,z|d,b|f,a|f, - c|f,a|d,c|z,b|f,b|d,z|f,a|f,c|e,z|f,b|e,b|e,z|z,a|d,a|e,z|z,c|d]; - a=1<<20; b=1<<31; c=a|b; d=1<<5; e=1<<15; f=d|e; - SP2 = [c|f,b|e,z|e,a|f,a|z,z|d,c|d,b|f,b|d,c|f,c|e,b|z,b|e,a|z,z|d,c|d, - a|e,a|d,b|f,z|z,b|z,z|e,a|f,c|z,a|d,b|d,z|z,a|e,z|f,c|e,c|z,z|f, - z|z,a|f,c|d,a|z,b|f,c|z,c|e,z|e,c|z,b|e,z|d,c|f,a|f,z|d,z|e,b|z, - z|f,c|e,a|z,b|d,a|d,b|f,b|d,a|d,a|e,z|z,b|e,z|f,b|z,c|d,c|f,a|e]; - a=1<<17; b=1<<27; c=a|b; d=1<<3; e=1<<9; f=d|e; - SP3 = [z|f,c|e,z|z,c|d,b|e,z|z,a|f,b|e,a|d,b|d,b|d,a|z,c|f,a|d,c|z,z|f, - b|z,z|d,c|e,z|e,a|e,c|z,c|d,a|f,b|f,a|e,a|z,b|f,z|d,c|f,z|e,b|z, - c|e,b|z,a|d,z|f,a|z,c|e,b|e,z|z,z|e,a|d,c|f,b|e,b|d,z|e,z|z,c|d, - b|f,a|z,b|z,c|f,z|d,a|f,a|e,b|d,c|z,b|f,z|f,c|z,a|f,z|d,c|d,a|e]; - a=1<<13; b=1<<23; c=a|b; d=1<<0; e=1<<7; f=d|e; - SP4 = [c|d,a|f,a|f,z|e,c|e,b|f,b|d,a|d,z|z,c|z,c|z,c|f,z|f,z|z,b|e,b|d, - z|d,a|z,b|z,c|d,z|e,b|z,a|d,a|e,b|f,z|d,a|e,b|e,a|z,c|e,c|f,z|f, - b|e,b|d,c|z,c|f,z|f,z|z,z|z,c|z,a|e,b|e,b|f,z|d,c|d,a|f,a|f,z|e, - c|f,z|f,z|d,a|z,b|d,a|d,c|e,b|f,a|d,a|e,b|z,c|d,z|e,b|z,a|z,c|e]; - a=1<<25; b=1<<30; c=a|b; d=1<<8; e=1<<19; f=d|e; - SP5 = [z|d,a|f,a|e,c|d,z|e,z|d,b|z,a|e,b|f,z|e,a|d,b|f,c|d,c|e,z|f,b|z, - a|z,b|e,b|e,z|z,b|d,c|f,c|f,a|d,c|e,b|d,z|z,c|z,a|f,a|z,c|z,z|f, - z|e,c|d,z|d,a|z,b|z,a|e,c|d,b|f,a|d,b|z,c|e,a|f,b|f,z|d,a|z,c|e, - c|f,z|f,c|z,c|f,a|e,z|z,b|e,c|z,z|f,a|d,b|d,z|e,z|z,b|e,a|f,b|d]; - a=1<<22; b=1<<29; c=a|b; d=1<<4; e=1<<14; f=d|e; - SP6 = [b|d,c|z,z|e,c|f,c|z,z|d,c|f,a|z,b|e,a|f,a|z,b|d,a|d,b|e,b|z,z|f, - z|z,a|d,b|f,z|e,a|e,b|f,z|d,c|d,c|d,z|z,a|f,c|e,z|f,a|e,c|e,b|z, - b|e,z|d,c|d,a|e,c|f,a|z,z|f,b|d,a|z,b|e,b|z,z|f,b|d,c|f,a|e,c|z, - a|f,c|e,z|z,c|d,z|d,z|e,c|z,a|f,z|e,a|d,b|f,z|z,c|e,b|z,a|d,b|f]; - a=1<<21; b=1<<26; c=a|b; d=1<<1; e=1<<11; f=d|e; - SP7 = [a|z,c|d,b|f,z|z,z|e,b|f,a|f,c|e,c|f,a|z,z|z,b|d,z|d,b|z,c|d,z|f, - b|e,a|f,a|d,b|e,b|d,c|z,c|e,a|d,c|z,z|e,z|f,c|f,a|e,z|d,b|z,a|e, - b|z,a|e,a|z,b|f,b|f,c|d,c|d,z|d,a|d,b|z,b|e,a|z,c|e,z|f,a|f,c|e, - z|f,b|d,c|f,c|z,a|e,z|z,z|d,c|f,z|z,a|f,c|z,z|e,b|d,b|e,z|e,a|d]; - a=1<<18; b=1<<28; c=a|b; d=1<<6; e=1<<12; f=d|e; - SP8 = [b|f,z|e,a|z,c|f,b|z,b|f,z|d,b|z,a|d,c|z,c|f,a|e,c|e,a|f,z|e,z|d, - c|z,b|d,b|e,z|f,a|e,a|d,c|d,c|e,z|f,z|z,z|z,c|d,b|d,b|e,a|f,a|z, - a|f,a|z,c|e,z|e,z|d,c|d,z|e,a|f,b|e,z|d,b|d,c|z,c|d,b|z,a|z,b|f, - z|z,c|f,a|d,b|d,c|z,b|e,b|f,z|z,c|f,a|e,a|e,z|f,z|f,a|d,b|z,c|e]; - // jshint +W013,+W015 + // Set the key. + function setKeys(keyBlock) { + var i, j, l, m, n, o, pc1m = [], pcr = [], kn = [], + raw0, raw1, rawi, KnLi; - // Set the key. - function setKeys(keyBlock) { - var i, j, l, m, n, o, pc1m = [], pcr = [], kn = [], - raw0, raw1, rawi, KnLi; + for (j = 0, l = 56; j < 56; ++j, l -= 8) { + l += l < -5 ? 65 : l < -3 ? 31 : l < -1 ? 63 : l === 27 ? 35 : 0; // PC1 + m = l & 0x7; + pc1m[j] = ((keyBlock[l >>> 3] & (1<>> 3] & (1<>> 10; + keys[KnLi] |= (raw1 & 0x00000fc0) >>> 6; + ++KnLi; + keys[KnLi] = (raw0 & 0x0003f000) << 12; + keys[KnLi] |= (raw0 & 0x0000003f) << 16; + keys[KnLi] |= (raw1 & 0x0003f000) >>> 4; + keys[KnLi] |= (raw1 & 0x0000003f); + ++KnLi; } } - // cookey - for (i = 0, rawi = 0, KnLi = 0; i < 16; ++i) { - raw0 = kn[rawi++]; - raw1 = kn[rawi++]; - keys[KnLi] = (raw0 & 0x00fc0000) << 6; - keys[KnLi] |= (raw0 & 0x00000fc0) << 10; - keys[KnLi] |= (raw1 & 0x00fc0000) >>> 10; - keys[KnLi] |= (raw1 & 0x00000fc0) >>> 6; - ++KnLi; - keys[KnLi] = (raw0 & 0x0003f000) << 12; - keys[KnLi] |= (raw0 & 0x0000003f) << 16; - keys[KnLi] |= (raw1 & 0x0003f000) >>> 4; - keys[KnLi] |= (raw1 & 0x0000003f); - ++KnLi; - } - } + // Encrypt 8 bytes of text + function enc8(text) { + var i = 0, b = text.slice(), fval, keysi = 0, + l, r, x; // left, right, accumulator - // Encrypt 8 bytes of text - function enc8(text) { - var i = 0, b = text.slice(), fval, keysi = 0, - l, r, x; // left, right, accumulator + // Squash 8 bytes to 2 ints + l = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++]; + r = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++]; - // Squash 8 bytes to 2 ints - l = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++]; - r = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++]; + x = ((l >>> 4) ^ r) & 0x0f0f0f0f; + r ^= x; + l ^= (x << 4); + x = ((l >>> 16) ^ r) & 0x0000ffff; + r ^= x; + l ^= (x << 16); + x = ((r >>> 2) ^ l) & 0x33333333; + l ^= x; + r ^= (x << 2); + x = ((r >>> 8) ^ l) & 0x00ff00ff; + l ^= x; + r ^= (x << 8); + r = (r << 1) | ((r >>> 31) & 1); + x = (l ^ r) & 0xaaaaaaaa; + l ^= x; + r ^= x; + l = (l << 1) | ((l >>> 31) & 1); - x = ((l >>> 4) ^ r) & 0x0f0f0f0f; - r ^= x; - l ^= (x << 4); - x = ((l >>> 16) ^ r) & 0x0000ffff; - r ^= x; - l ^= (x << 16); - x = ((r >>> 2) ^ l) & 0x33333333; - l ^= x; - r ^= (x << 2); - x = ((r >>> 8) ^ l) & 0x00ff00ff; - l ^= x; - r ^= (x << 8); - r = (r << 1) | ((r >>> 31) & 1); - x = (l ^ r) & 0xaaaaaaaa; - l ^= x; - r ^= x; - l = (l << 1) | ((l >>> 31) & 1); + for (i = 0; i < 8; ++i) { + x = (r << 28) | (r >>> 4); + x ^= keys[keysi++]; + fval = SP7[x & 0x3f]; + fval |= SP5[(x >>> 8) & 0x3f]; + fval |= SP3[(x >>> 16) & 0x3f]; + fval |= SP1[(x >>> 24) & 0x3f]; + x = r ^ keys[keysi++]; + fval |= SP8[x & 0x3f]; + fval |= SP6[(x >>> 8) & 0x3f]; + fval |= SP4[(x >>> 16) & 0x3f]; + fval |= SP2[(x >>> 24) & 0x3f]; + l ^= fval; + x = (l << 28) | (l >>> 4); + x ^= keys[keysi++]; + fval = SP7[x & 0x3f]; + fval |= SP5[(x >>> 8) & 0x3f]; + fval |= SP3[(x >>> 16) & 0x3f]; + fval |= SP1[(x >>> 24) & 0x3f]; + x = l ^ keys[keysi++]; + fval |= SP8[x & 0x0000003f]; + fval |= SP6[(x >>> 8) & 0x3f]; + fval |= SP4[(x >>> 16) & 0x3f]; + fval |= SP2[(x >>> 24) & 0x3f]; + r ^= fval; + } - for (i = 0; i < 8; ++i) { - x = (r << 28) | (r >>> 4); - x ^= keys[keysi++]; - fval = SP7[x & 0x3f]; - fval |= SP5[(x >>> 8) & 0x3f]; - fval |= SP3[(x >>> 16) & 0x3f]; - fval |= SP1[(x >>> 24) & 0x3f]; - x = r ^ keys[keysi++]; - fval |= SP8[x & 0x3f]; - fval |= SP6[(x >>> 8) & 0x3f]; - fval |= SP4[(x >>> 16) & 0x3f]; - fval |= SP2[(x >>> 24) & 0x3f]; - l ^= fval; - x = (l << 28) | (l >>> 4); - x ^= keys[keysi++]; - fval = SP7[x & 0x3f]; - fval |= SP5[(x >>> 8) & 0x3f]; - fval |= SP3[(x >>> 16) & 0x3f]; - fval |= SP1[(x >>> 24) & 0x3f]; - x = l ^ keys[keysi++]; - fval |= SP8[x & 0x0000003f]; - fval |= SP6[(x >>> 8) & 0x3f]; - fval |= SP4[(x >>> 16) & 0x3f]; - fval |= SP2[(x >>> 24) & 0x3f]; - r ^= fval; + r = (r << 31) | (r >>> 1); + x = (l ^ r) & 0xaaaaaaaa; + l ^= x; + r ^= x; + l = (l << 31) | (l >>> 1); + x = ((l >>> 8) ^ r) & 0x00ff00ff; + r ^= x; + l ^= (x << 8); + x = ((l >>> 2) ^ r) & 0x33333333; + r ^= x; + l ^= (x << 2); + x = ((r >>> 16) ^ l) & 0x0000ffff; + l ^= x; + r ^= (x << 16); + x = ((r >>> 4) ^ l) & 0x0f0f0f0f; + l ^= x; + r ^= (x << 4); + + // Spread ints to bytes + x = [r, l]; + for (i = 0; i < 8; i++) { + b[i] = (x[i>>>2] >>> (8 * (3 - (i % 4)))) % 256; + if (b[i] < 0) { b[i] += 256; } // unsigned + } + return b; } - r = (r << 31) | (r >>> 1); - x = (l ^ r) & 0xaaaaaaaa; - l ^= x; - r ^= x; - l = (l << 31) | (l >>> 1); - x = ((l >>> 8) ^ r) & 0x00ff00ff; - r ^= x; - l ^= (x << 8); - x = ((l >>> 2) ^ r) & 0x33333333; - r ^= x; - l ^= (x << 2); - x = ((r >>> 16) ^ l) & 0x0000ffff; - l ^= x; - r ^= (x << 16); - x = ((r >>> 4) ^ l) & 0x0f0f0f0f; - l ^= x; - r ^= (x << 4); - - // Spread ints to bytes - x = [r, l]; - for (i = 0; i < 8; i++) { - b[i] = (x[i>>>2] >>> (8 * (3 - (i % 4)))) % 256; - if (b[i] < 0) { b[i] += 256; } // unsigned + // Encrypt 16 bytes of text using passwd as key + function encrypt(t) { + return enc8(t.slice(0, 8)).concat(enc8(t.slice(8, 16))); } - return b; - } - // Encrypt 16 bytes of text using passwd as key - function encrypt(t) { - return enc8(t.slice(0, 8)).concat(enc8(t.slice(8, 16))); - } + setKeys(passwd); // Setup keys + return {'encrypt': encrypt}; // Public interface - setKeys(passwd); // Setup keys - return {'encrypt': encrypt}; // Public interface + }; // function DES -}; // function DES + return DES; +}); diff --git a/core/display.js b/core/display.js index 6f60b37a..14ff5d30 100644 --- a/core/display.js +++ b/core/display.js @@ -2,106 +2,18 @@ * noVNC: HTML5 VNC client * Copyright (C) 2012 Joel Martin * Copyright (C) 2015 Samuel Mannehed for Cendio AB + * Copyright (C) 2017 Pierre Ossman for Cendio AB * Licensed under MPL 2.0 (see LICENSE.txt) * * See README.md for usage and integration instructions. */ /*jslint browser: true, white: false */ -/*global Util, Base64, changeCursor */ - -/* [module] - * import Util from "./util"; - * import Base64 from "./base64"; - */ "use strict"; -/* [module] export default */ function Display(defaults) { - this._drawCtx = null; - this._c_forceCanvas = false; - - this._renderQ = []; // queue drawing actions for in-oder rendering - this._flushing = false; - - // the full frame buffer (logical canvas) size - this._fb_width = 0; - this._fb_height = 0; - - this._prevDrawStyle = ""; - this._tile = null; - this._tile16x16 = null; - this._tile_x = 0; - this._tile_y = 0; - - Util.set_defaults(this, defaults, { - 'true_color': true, - 'colourMap': [], - 'scale': 1.0, - 'viewport': false, - 'render_mode': '', - "onFlush": function () {}, - }); - - Util.Debug(">> Display.constructor"); - - // The visible canvas - if (!this._target) { - throw new Error("Target must be set"); - } - - if (typeof this._target === 'string') { - throw new Error('target must be a DOM element'); - } - - if (!this._target.getContext) { - throw new Error("no getContext method"); - } - - this._targetCtx = this._target.getContext('2d'); - - // the visible canvas viewport (i.e. what actually gets seen) - this._viewportLoc = { 'x': 0, 'y': 0, 'w': this._target.width, 'h': this._target.height }; - - // The hidden canvas, where we do the actual rendering - this._backbuffer = document.createElement('canvas'); - this._drawCtx = this._backbuffer.getContext('2d'); - - this._damageBounds = { left:0, top:0, - right: this._backbuffer.width, - bottom: this._backbuffer.height }; - - Util.Debug("User Agent: " + navigator.userAgent); - if (Util.Engine.gecko) { Util.Debug("Browser: gecko " + Util.Engine.gecko); } - if (Util.Engine.webkit) { Util.Debug("Browser: webkit " + Util.Engine.webkit); } - if (Util.Engine.trident) { Util.Debug("Browser: trident " + Util.Engine.trident); } - if (Util.Engine.presto) { Util.Debug("Browser: presto " + Util.Engine.presto); } - - this.clear(); - - // Check canvas features - if ('createImageData' in this._drawCtx) { - this._render_mode = 'canvas rendering'; - } else { - throw new Error("Canvas does not support createImageData"); - } - - if (this._prefer_js === null) { - Util.Info("Prefering javascript operations"); - this._prefer_js = true; - } - - // Determine browser support for setting the cursor via data URI scheme - if (this._cursor_uri || this._cursor_uri === null || - this._cursor_uri === undefined) { - this._cursor_uri = Util.browserSupportsCursorURIs(); - } - - Util.Debug("<< Display.constructor"); -}; - -(function () { - +define(["core/util", "core/base64"], +function (Util, Base64) { var SUPPORTS_IMAGEDATA_CONSTRUCTOR = false; try { new ImageData(new Uint8ClampedArray(4), 1, 1); @@ -110,6 +22,88 @@ // ignore failure } + function Display(defaults) { + this._drawCtx = null; + this._c_forceCanvas = false; + + this._renderQ = []; // queue drawing actions for in-oder rendering + this._flushing = false; + + // the full frame buffer (logical canvas) size + this._fb_width = 0; + this._fb_height = 0; + + this._prevDrawStyle = ""; + this._tile = null; + this._tile16x16 = null; + this._tile_x = 0; + this._tile_y = 0; + + Util.set_defaults(this, defaults, { + 'true_color': true, + 'colourMap': [], + 'scale': 1.0, + 'viewport': false, + 'render_mode': '', + "onFlush": function () {}, + }); + + Util.Debug(">> Display.constructor"); + + // The visible canvas + if (!this._target) { + throw new Error("Target must be set"); + } + + if (typeof this._target === 'string') { + throw new Error('target must be a DOM element'); + } + + if (!this._target.getContext) { + throw new Error("no getContext method"); + } + + this._targetCtx = this._target.getContext('2d'); + + // the visible canvas viewport (i.e. what actually gets seen) + this._viewportLoc = { 'x': 0, 'y': 0, 'w': this._target.width, 'h': this._target.height }; + + // The hidden canvas, where we do the actual rendering + this._backbuffer = document.createElement('canvas'); + this._drawCtx = this._backbuffer.getContext('2d'); + + this._damageBounds = { left:0, top:0, + right: this._backbuffer.width, + bottom: this._backbuffer.height }; + + Util.Debug("User Agent: " + navigator.userAgent); + if (Util.Engine.gecko) { Util.Debug("Browser: gecko " + Util.Engine.gecko); } + if (Util.Engine.webkit) { Util.Debug("Browser: webkit " + Util.Engine.webkit); } + if (Util.Engine.trident) { Util.Debug("Browser: trident " + Util.Engine.trident); } + if (Util.Engine.presto) { Util.Debug("Browser: presto " + Util.Engine.presto); } + + this.clear(); + + // Check canvas features + if ('createImageData' in this._drawCtx) { + this._render_mode = 'canvas rendering'; + } else { + throw new Error("Canvas does not support createImageData"); + } + + if (this._prefer_js === null) { + Util.Info("Prefering javascript operations"); + this._prefer_js = true; + } + + // Determine browser support for setting the cursor via data URI scheme + if (this._cursor_uri || this._cursor_uri === null || + this._cursor_uri === undefined) { + this._cursor_uri = Util.browserSupportsCursorURIs(); + } + + Util.Debug("<< Display.constructor"); + }; Display.prototype = { // Public methods @@ -876,4 +870,6 @@ var url = 'data:image/x-icon;base64,' + Base64.encode(cur); target.style.cursor = 'url(' + url + ')' + hotx + ' ' + hoty + ', default'; }; -})(); + + return { Display: Display }; +}); diff --git a/core/inflator.js b/core/inflator.js index 973836d7..309a3325 100644 --- a/core/inflator.js +++ b/core/inflator.js @@ -1,2453 +1,8 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Inflator = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o this.chunkSize) { - this.chunkSize = expected; - this.strm.output = new Uint8Array(this.chunkSize); - } - - this.strm.avail_out = this.chunkSize; - - zlib.inflate(this.strm, flush); - - return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out); - }, - - reset: function () { - zlib.inflateReset(this.strm); - } -}; - -module.exports = { Inflate: Inflate }; - -},{"pako/lib/zlib/inflate.js":6,"pako/lib/zlib/zstream.js":8}],2:[function(require,module,exports){ -'use strict'; - - -var TYPED_OK = (typeof Uint8Array !== 'undefined') && - (typeof Uint16Array !== 'undefined') && - (typeof Int32Array !== 'undefined'); - - -exports.assign = function (obj /*from1, from2, from3, ...*/) { - var sources = Array.prototype.slice.call(arguments, 1); - while (sources.length) { - var source = sources.shift(); - if (!source) { continue; } - - if (typeof source !== 'object') { - throw new TypeError(source + 'must be non-object'); - } - - for (var p in source) { - if (source.hasOwnProperty(p)) { - obj[p] = source[p]; - } - } - } - - return obj; -}; - - -// reduce buffer size, avoiding mem copy -exports.shrinkBuf = function (buf, size) { - if (buf.length === size) { return buf; } - if (buf.subarray) { return buf.subarray(0, size); } - buf.length = size; - return buf; -}; - - -var fnTyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - if (src.subarray && dest.subarray) { - dest.set(src.subarray(src_offs, src_offs + len), dest_offs); - return; - } - // Fallback to ordinary array - for (var i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - var i, l, len, pos, chunk, result; - - // calculate data length - len = 0; - for (i = 0, l = chunks.length; i < l; i++) { - len += chunks[i].length; - } - - // join chunks - result = new Uint8Array(len); - pos = 0; - for (i = 0, l = chunks.length; i < l; i++) { - chunk = chunks[i]; - result.set(chunk, pos); - pos += chunk.length; - } - - return result; - } -}; - -var fnUntyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - for (var i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - return [].concat.apply([], chunks); - } -}; - - -// Enable/Disable typed arrays use, for testing -// -exports.setTyped = function (on) { - if (on) { - exports.Buf8 = Uint8Array; - exports.Buf16 = Uint16Array; - exports.Buf32 = Int32Array; - exports.assign(exports, fnTyped); - } else { - exports.Buf8 = Array; - exports.Buf16 = Array; - exports.Buf32 = Array; - exports.assign(exports, fnUntyped); - } -}; - -exports.setTyped(TYPED_OK); - -},{}],3:[function(require,module,exports){ -'use strict'; - -// Note: adler32 takes 12% for level 0 and 2% for level 6. -// It doesn't worth to make additional optimizationa as in original. -// Small size is preferable. - -function adler32(adler, buf, len, pos) { - var s1 = (adler & 0xffff) |0, - s2 = ((adler >>> 16) & 0xffff) |0, - n = 0; - - while (len !== 0) { - // Set limit ~ twice less than 5552, to keep - // s2 in 31-bits, because we force signed ints. - // in other case %= will fail. - n = len > 2000 ? 2000 : len; - len -= n; - - do { - s1 = (s1 + buf[pos++]) |0; - s2 = (s2 + s1) |0; - } while (--n); - - s1 %= 65521; - s2 %= 65521; - } - - return (s1 | (s2 << 16)) |0; -} - - -module.exports = adler32; - -},{}],4:[function(require,module,exports){ -'use strict'; - -// Note: we can't get significant speed boost here. -// So write code to minimize size - no pregenerated tables -// and array tools dependencies. - - -// Use ordinary array, since untyped makes no boost here -function makeTable() { - var c, table = []; - - for (var n = 0; n < 256; n++) { - c = n; - for (var k = 0; k < 8; k++) { - c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); - } - table[n] = c; - } - - return table; -} - -// Create table on load. Just 255 signed longs. Not a problem. -var crcTable = makeTable(); - - -function crc32(crc, buf, len, pos) { - var t = crcTable, - end = pos + len; - - crc ^= -1; - - for (var i = pos; i < end; i++) { - crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; - } - - return (crc ^ (-1)); // >>> 0; -} - - -module.exports = crc32; - -},{}],5:[function(require,module,exports){ -'use strict'; - -// See state defs from inflate.js -var BAD = 30; /* got a data error -- remain here until reset */ -var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ - /* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state.mode === LEN - strm.avail_in >= 6 - strm.avail_out >= 258 - start >= strm.avail_out - state.bits < 8 - - On return, state.mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm.avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm.avail_out >= 258 for each loop to avoid checking for - output space. + * noVNC: HTML5 VNC client + * Copyright (C) 2012 Joel Martin + * Copyright (C) 2017 Pierre Ossman for Cendio AB + * Licensed under MPL 2.0 or any later version (see LICENSE.txt) */ -module.exports = function inflate_fast(strm, start) { - var state; - var _in; /* local strm.input */ - var last; /* have enough input while in < last */ - var _out; /* local strm.output */ - var beg; /* inflate()'s initial strm.output */ - var end; /* while out < end, enough space available */ -//#ifdef INFLATE_STRICT - var dmax; /* maximum distance from zlib header */ -//#endif - var wsize; /* window size or zero if not using window */ - var whave; /* valid bytes in the window */ - var wnext; /* window write index */ - // Use `s_window` instead `window`, avoid conflict with instrumentation tools - var s_window; /* allocated sliding window, if wsize != 0 */ - var hold; /* local strm.hold */ - var bits; /* local strm.bits */ - var lcode; /* local strm.lencode */ - var dcode; /* local strm.distcode */ - var lmask; /* mask for first level of length codes */ - var dmask; /* mask for first level of distance codes */ - var here; /* retrieved table entry */ - var op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - var len; /* match length, unused bytes */ - var dist; /* match distance */ - var from; /* where to copy match from */ - var from_source; - - var input, output; // JS specific, because we have no pointers - - /* copy state to local variables */ - state = strm.state; - //here = state.here; - _in = strm.next_in; - input = strm.input; - last = _in + (strm.avail_in - 5); - _out = strm.next_out; - output = strm.output; - beg = _out - (start - strm.avail_out); - end = _out + (strm.avail_out - 257); -//#ifdef INFLATE_STRICT - dmax = state.dmax; -//#endif - wsize = state.wsize; - whave = state.whave; - wnext = state.wnext; - s_window = state.window; - hold = state.hold; - bits = state.bits; - lcode = state.lencode; - dcode = state.distcode; - lmask = (1 << state.lenbits) - 1; - dmask = (1 << state.distbits) - 1; - - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - top: - do { - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - - here = lcode[hold & lmask]; - - dolen: - for (;;) { // Goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; - if (op === 0) { /* literal */ - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - output[_out++] = here & 0xffff/*here.val*/; - } - else if (op & 16) { /* length base */ - len = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - len += hold & ((1 << op) - 1); - hold >>>= op; - bits -= op; - } - //Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - here = dcode[hold & dmask]; - - dodist: - for (;;) { // goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; - - if (op & 16) { /* distance base */ - dist = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - } - dist += hold & ((1 << op) - 1); -//#ifdef INFLATE_STRICT - if (dist > dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } -//#endif - hold >>>= op; - bits -= op; - //Tracevv((stderr, "inflate: distance %u\n", dist)); - op = _out - beg; /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } - -// (!) This block is disabled in zlib defailts, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// if (len <= op - whave) { -// do { -// output[_out++] = 0; -// } while (--len); -// continue top; -// } -// len -= op - whave; -// do { -// output[_out++] = 0; -// } while (--op > whave); -// if (op === 0) { -// from = _out - dist; -// do { -// output[_out++] = output[from++]; -// } while (--len); -// continue top; -// } -//#endif - } - from = 0; // window index - from_source = s_window; - if (wnext === 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = 0; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - } - else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - while (len > 2) { - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - len -= 3; - } - if (len) { - output[_out++] = from_source[from++]; - if (len > 1) { - output[_out++] = from_source[from++]; - } - } - } - else { - from = _out - dist; /* copy direct from output */ - do { /* minimum length is three */ - output[_out++] = output[from++]; - output[_out++] = output[from++]; - output[_out++] = output[from++]; - len -= 3; - } while (len > 2); - if (len) { - output[_out++] = output[from++]; - if (len > 1) { - output[_out++] = output[from++]; - } - } - } - } - else if ((op & 64) === 0) { /* 2nd level distance code */ - here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dodist; - } - else { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } - else if ((op & 64) === 0) { /* 2nd level length code */ - here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dolen; - } - else if (op & 32) { /* end-of-block */ - //Tracevv((stderr, "inflate: end of block\n")); - state.mode = TYPE; - break top; - } - else { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } while (_in < last && _out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - _in -= len; - bits -= len << 3; - hold &= (1 << bits) - 1; - - /* update state and return */ - strm.next_in = _in; - strm.next_out = _out; - strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); - strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); - state.hold = hold; - state.bits = bits; - return; -}; - -},{}],6:[function(require,module,exports){ -'use strict'; - - -var utils = require('../utils/common'); -var adler32 = require('./adler32'); -var crc32 = require('./crc32'); -var inflate_fast = require('./inffast'); -var inflate_table = require('./inftrees'); - -var CODES = 0; -var LENS = 1; -var DISTS = 2; - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - - -/* Allowed flush values; see deflate() and inflate() below for details */ -//var Z_NO_FLUSH = 0; -//var Z_PARTIAL_FLUSH = 1; -//var Z_SYNC_FLUSH = 2; -//var Z_FULL_FLUSH = 3; -var Z_FINISH = 4; -var Z_BLOCK = 5; -var Z_TREES = 6; - - -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ -var Z_OK = 0; -var Z_STREAM_END = 1; -var Z_NEED_DICT = 2; -//var Z_ERRNO = -1; -var Z_STREAM_ERROR = -2; -var Z_DATA_ERROR = -3; -var Z_MEM_ERROR = -4; -var Z_BUF_ERROR = -5; -//var Z_VERSION_ERROR = -6; - -/* The deflate compression method */ -var Z_DEFLATED = 8; - - -/* STATES ====================================================================*/ -/* ===========================================================================*/ - - -var HEAD = 1; /* i: waiting for magic header */ -var FLAGS = 2; /* i: waiting for method and flags (gzip) */ -var TIME = 3; /* i: waiting for modification time (gzip) */ -var OS = 4; /* i: waiting for extra flags and operating system (gzip) */ -var EXLEN = 5; /* i: waiting for extra length (gzip) */ -var EXTRA = 6; /* i: waiting for extra bytes (gzip) */ -var NAME = 7; /* i: waiting for end of file name (gzip) */ -var COMMENT = 8; /* i: waiting for end of comment (gzip) */ -var HCRC = 9; /* i: waiting for header crc (gzip) */ -var DICTID = 10; /* i: waiting for dictionary check value */ -var DICT = 11; /* waiting for inflateSetDictionary() call */ -var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ -var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ -var STORED = 14; /* i: waiting for stored size (length and complement) */ -var COPY_ = 15; /* i/o: same as COPY below, but only first time in */ -var COPY = 16; /* i/o: waiting for input or output to copy stored block */ -var TABLE = 17; /* i: waiting for dynamic block table lengths */ -var LENLENS = 18; /* i: waiting for code length code lengths */ -var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ -var LEN_ = 20; /* i: same as LEN below, but only first time in */ -var LEN = 21; /* i: waiting for length/lit/eob code */ -var LENEXT = 22; /* i: waiting for length extra bits */ -var DIST = 23; /* i: waiting for distance code */ -var DISTEXT = 24; /* i: waiting for distance extra bits */ -var MATCH = 25; /* o: waiting for output space to copy string */ -var LIT = 26; /* o: waiting for output space to write literal */ -var CHECK = 27; /* i: waiting for 32-bit check value */ -var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ -var DONE = 29; /* finished check, done -- remain here until reset */ -var BAD = 30; /* got a data error -- remain here until reset */ -var MEM = 31; /* got an inflate() memory error -- remain here until reset */ -var SYNC = 32; /* looking for synchronization bytes to restart inflate() */ - -/* ===========================================================================*/ - - - -var ENOUGH_LENS = 852; -var ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - -var MAX_WBITS = 15; -/* 32K LZ77 window */ -var DEF_WBITS = MAX_WBITS; - - -function zswap32(q) { - return (((q >>> 24) & 0xff) + - ((q >>> 8) & 0xff00) + - ((q & 0xff00) << 8) + - ((q & 0xff) << 24)); -} - - -function InflateState() { - this.mode = 0; /* current inflate mode */ - this.last = false; /* true if processing last block */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.havedict = false; /* true if dictionary provided */ - this.flags = 0; /* gzip header method and flags (0 if zlib) */ - this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ - this.check = 0; /* protected copy of check value */ - this.total = 0; /* protected copy of output count */ - // TODO: may be {} - this.head = null; /* where to save gzip header information */ - - /* sliding window */ - this.wbits = 0; /* log base 2 of requested window size */ - this.wsize = 0; /* window size or zero if not using window */ - this.whave = 0; /* valid bytes in the window */ - this.wnext = 0; /* window write index */ - this.window = null; /* allocated sliding window, if needed */ - - /* bit accumulator */ - this.hold = 0; /* input bit accumulator */ - this.bits = 0; /* number of bits in "in" */ - - /* for string and stored block copying */ - this.length = 0; /* literal or length of data to copy */ - this.offset = 0; /* distance back to copy string from */ - - /* for table and code decoding */ - this.extra = 0; /* extra bits needed */ - - /* fixed and dynamic code tables */ - this.lencode = null; /* starting table for length/literal codes */ - this.distcode = null; /* starting table for distance codes */ - this.lenbits = 0; /* index bits for lencode */ - this.distbits = 0; /* index bits for distcode */ - - /* dynamic table building */ - this.ncode = 0; /* number of code length code lengths */ - this.nlen = 0; /* number of length code lengths */ - this.ndist = 0; /* number of distance code lengths */ - this.have = 0; /* number of code lengths in lens[] */ - this.next = null; /* next available space in codes[] */ - - this.lens = new utils.Buf16(320); /* temporary storage for code lengths */ - this.work = new utils.Buf16(288); /* work area for code table building */ - - /* - because we don't have pointers in js, we use lencode and distcode directly - as buffers so we don't need codes - */ - //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ - this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ - this.distdyn = null; /* dynamic table for distance codes (JS specific) */ - this.sane = 0; /* if false, allow invalid distance too far */ - this.back = 0; /* bits back of last unprocessed length/lit */ - this.was = 0; /* initial length of match */ -} - -function inflateResetKeep(strm) { - var state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - strm.total_in = strm.total_out = state.total = 0; - strm.msg = ''; /*Z_NULL*/ - if (state.wrap) { /* to support ill-conceived Java test suite */ - strm.adler = state.wrap & 1; - } - state.mode = HEAD; - state.last = 0; - state.havedict = 0; - state.dmax = 32768; - state.head = null/*Z_NULL*/; - state.hold = 0; - state.bits = 0; - //state.lencode = state.distcode = state.next = state.codes; - state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS); - state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS); - - state.sane = 1; - state.back = -1; - //Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -function inflateReset(strm) { - var state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - state.wsize = 0; - state.whave = 0; - state.wnext = 0; - return inflateResetKeep(strm); - -} - -function inflateReset2(strm, windowBits) { - var wrap; - var state; - - /* get the state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; - if (windowBits < 48) { - windowBits &= 15; - } - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) { - return Z_STREAM_ERROR; - } - if (state.window !== null && state.wbits !== windowBits) { - state.window = null; - } - - /* update state and reset the rest of it */ - state.wrap = wrap; - state.wbits = windowBits; - return inflateReset(strm); -} - -function inflateInit2(strm, windowBits) { - var ret; - var state; - - if (!strm) { return Z_STREAM_ERROR; } - //strm.msg = Z_NULL; /* in case we return an error */ - - state = new InflateState(); - - //if (state === Z_NULL) return Z_MEM_ERROR; - //Tracev((stderr, "inflate: allocated\n")); - strm.state = state; - state.window = null/*Z_NULL*/; - ret = inflateReset2(strm, windowBits); - if (ret !== Z_OK) { - strm.state = null/*Z_NULL*/; - } - return ret; -} - -function inflateInit(strm) { - return inflateInit2(strm, DEF_WBITS); -} - - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -var virgin = true; - -var lenfix, distfix; // We have no pointers in JS, so keep tables separate - -function fixedtables(state) { - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - var sym; - - lenfix = new utils.Buf32(512); - distfix = new utils.Buf32(32); - - /* literal/length table */ - sym = 0; - while (sym < 144) { state.lens[sym++] = 8; } - while (sym < 256) { state.lens[sym++] = 9; } - while (sym < 280) { state.lens[sym++] = 7; } - while (sym < 288) { state.lens[sym++] = 8; } - - inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); - - /* distance table */ - sym = 0; - while (sym < 32) { state.lens[sym++] = 5; } - - inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); - - /* do this just once */ - virgin = false; - } - - state.lencode = lenfix; - state.lenbits = 9; - state.distcode = distfix; - state.distbits = 5; -} - - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -function updatewindow(strm, src, end, copy) { - var dist; - var state = strm.state; - - /* if it hasn't been done already, allocate space for the window */ - if (state.window === null) { - state.wsize = 1 << state.wbits; - state.wnext = 0; - state.whave = 0; - - state.window = new utils.Buf8(state.wsize); - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state.wsize) { - utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0); - state.wnext = 0; - state.whave = state.wsize; - } - else { - dist = state.wsize - state.wnext; - if (dist > copy) { - dist = copy; - } - //zmemcpy(state->window + state->wnext, end - copy, dist); - utils.arraySet(state.window, src, end - copy, dist, state.wnext); - copy -= dist; - if (copy) { - //zmemcpy(state->window, end - copy, copy); - utils.arraySet(state.window, src, end - copy, copy, 0); - state.wnext = copy; - state.whave = state.wsize; - } - else { - state.wnext += dist; - if (state.wnext === state.wsize) { state.wnext = 0; } - if (state.whave < state.wsize) { state.whave += dist; } - } - } - return 0; -} - -function inflate(strm, flush) { - var state; - var input, output; // input/output buffers - var next; /* next input INDEX */ - var put; /* next output INDEX */ - var have, left; /* available input and output */ - var hold; /* bit buffer */ - var bits; /* bits in bit buffer */ - var _in, _out; /* save starting available input and output */ - var copy; /* number of stored or match bytes to copy */ - var from; /* where to copy match bytes from */ - var from_source; - var here = 0; /* current decoding table entry */ - var here_bits, here_op, here_val; // paked "here" denormalized (JS specific) - //var last; /* parent table entry */ - var last_bits, last_op, last_val; // paked "last" denormalized (JS specific) - var len; /* length to copy for repeats, bits to drop */ - var ret; /* return code */ - var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */ - var opts; - - var n; // temporary var for NEED_BITS - - var order = /* permutation of code lengths */ - [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; - - - if (!strm || !strm.state || !strm.output || - (!strm.input && strm.avail_in !== 0)) { - return Z_STREAM_ERROR; - } - - state = strm.state; - if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ - - - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - _in = have; - _out = left; - ret = Z_OK; - - inf_leave: // goto emulation - for (;;) { - switch (state.mode) { - case HEAD: - if (state.wrap === 0) { - state.mode = TYPEDO; - break; - } - //=== NEEDBITS(16); - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ - state.check = 0/*crc32(0L, Z_NULL, 0)*/; - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = FLAGS; - break; - } - state.flags = 0; /* expect zlib header */ - if (state.head) { - state.head.done = false; - } - if (!(state.wrap & 1) || /* check if zlib header allowed */ - (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { - strm.msg = 'incorrect header check'; - state.mode = BAD; - break; - } - if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - len = (hold & 0x0f)/*BITS(4)*/ + 8; - if (state.wbits === 0) { - state.wbits = len; - } - else if (len > state.wbits) { - strm.msg = 'invalid window size'; - state.mode = BAD; - break; - } - state.dmax = 1 << len; - //Tracev((stderr, "inflate: zlib header ok\n")); - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = hold & 0x200 ? DICTID : TYPE; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - break; - case FLAGS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.flags = hold; - if ((state.flags & 0xff) !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - if (state.flags & 0xe000) { - strm.msg = 'unknown header flags set'; - state.mode = BAD; - break; - } - if (state.head) { - state.head.text = ((hold >> 8) & 1); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = TIME; - /* falls through */ - case TIME: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.time = hold; - } - if (state.flags & 0x0200) { - //=== CRC4(state.check, hold) - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - hbuf[2] = (hold >>> 16) & 0xff; - hbuf[3] = (hold >>> 24) & 0xff; - state.check = crc32(state.check, hbuf, 4, 0); - //=== - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = OS; - /* falls through */ - case OS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.xflags = (hold & 0xff); - state.head.os = (hold >> 8); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = EXLEN; - /* falls through */ - case EXLEN: - if (state.flags & 0x0400) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length = hold; - if (state.head) { - state.head.extra_len = hold; - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - else if (state.head) { - state.head.extra = null/*Z_NULL*/; - } - state.mode = EXTRA; - /* falls through */ - case EXTRA: - if (state.flags & 0x0400) { - copy = state.length; - if (copy > have) { copy = have; } - if (copy) { - if (state.head) { - len = state.head.extra_len - state.length; - if (!state.head.extra) { - // Use untyped array for more conveniend processing later - state.head.extra = new Array(state.head.extra_len); - } - utils.arraySet( - state.head.extra, - input, - next, - // extra field is limited to 65536 bytes - // - no need for additional size check - copy, - /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ - len - ); - //zmemcpy(state.head.extra + len, next, - // len + copy > state.head.extra_max ? - // state.head.extra_max - len : copy); - } - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - state.length -= copy; - } - if (state.length) { break inf_leave; } - } - state.length = 0; - state.mode = NAME; - /* falls through */ - case NAME: - if (state.flags & 0x0800) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - // TODO: 2 or 1 bytes? - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.name_max*/)) { - state.head.name += String.fromCharCode(len); - } - } while (len && copy < have); - - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.name = null; - } - state.length = 0; - state.mode = COMMENT; - /* falls through */ - case COMMENT: - if (state.flags & 0x1000) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.comm_max*/)) { - state.head.comment += String.fromCharCode(len); - } - } while (len && copy < have); - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.comment = null; - } - state.mode = HCRC; - /* falls through */ - case HCRC: - if (state.flags & 0x0200) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.check & 0xffff)) { - strm.msg = 'header crc mismatch'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - if (state.head) { - state.head.hcrc = ((state.flags >> 9) & 1); - state.head.done = true; - } - strm.adler = state.check = 0; - state.mode = TYPE; - break; - case DICTID: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - strm.adler = state.check = zswap32(hold); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = DICT; - /* falls through */ - case DICT: - if (state.havedict === 0) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - return Z_NEED_DICT; - } - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = TYPE; - /* falls through */ - case TYPE: - if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } - /* falls through */ - case TYPEDO: - if (state.last) { - //--- BYTEBITS() ---// - hold >>>= bits & 7; - bits -= bits & 7; - //---// - state.mode = CHECK; - break; - } - //=== NEEDBITS(3); */ - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.last = (hold & 0x01)/*BITS(1)*/; - //--- DROPBITS(1) ---// - hold >>>= 1; - bits -= 1; - //---// - - switch ((hold & 0x03)/*BITS(2)*/) { - case 0: /* stored block */ - //Tracev((stderr, "inflate: stored block%s\n", - // state.last ? " (last)" : "")); - state.mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - //Tracev((stderr, "inflate: fixed codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = LEN_; /* decode codes */ - if (flush === Z_TREES) { - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break inf_leave; - } - break; - case 2: /* dynamic block */ - //Tracev((stderr, "inflate: dynamic codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = TABLE; - break; - case 3: - strm.msg = 'invalid block type'; - state.mode = BAD; - } - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break; - case STORED: - //--- BYTEBITS() ---// /* go to byte boundary */ - hold >>>= bits & 7; - bits -= bits & 7; - //---// - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { - strm.msg = 'invalid stored block lengths'; - state.mode = BAD; - break; - } - state.length = hold & 0xffff; - //Tracev((stderr, "inflate: stored length %u\n", - // state.length)); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = COPY_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case COPY_: - state.mode = COPY; - /* falls through */ - case COPY: - copy = state.length; - if (copy) { - if (copy > have) { copy = have; } - if (copy > left) { copy = left; } - if (copy === 0) { break inf_leave; } - //--- zmemcpy(put, next, copy); --- - utils.arraySet(output, input, next, copy, put); - //---// - have -= copy; - next += copy; - left -= copy; - put += copy; - state.length -= copy; - break; - } - //Tracev((stderr, "inflate: stored end\n")); - state.mode = TYPE; - break; - case TABLE: - //=== NEEDBITS(14); */ - while (bits < 14) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// -//#ifndef PKZIP_BUG_WORKAROUND - if (state.nlen > 286 || state.ndist > 30) { - strm.msg = 'too many length or distance symbols'; - state.mode = BAD; - break; - } -//#endif - //Tracev((stderr, "inflate: table sizes ok\n")); - state.have = 0; - state.mode = LENLENS; - /* falls through */ - case LENLENS: - while (state.have < state.ncode) { - //=== NEEDBITS(3); - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - while (state.have < 19) { - state.lens[order[state.have++]] = 0; - } - // We have separate tables & no pointers. 2 commented lines below not needed. - //state.next = state.codes; - //state.lencode = state.next; - // Switch to use dynamic table - state.lencode = state.lendyn; - state.lenbits = 7; - - opts = { bits: state.lenbits }; - ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); - state.lenbits = opts.bits; - - if (ret) { - strm.msg = 'invalid code lengths set'; - state.mode = BAD; - break; - } - //Tracev((stderr, "inflate: code lengths ok\n")); - state.have = 0; - state.mode = CODELENS; - /* falls through */ - case CODELENS: - while (state.have < state.nlen + state.ndist) { - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_val < 16) { - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.lens[state.have++] = here_val; - } - else { - if (here_val === 16) { - //=== NEEDBITS(here.bits + 2); - n = here_bits + 2; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - if (state.have === 0) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - len = state.lens[state.have - 1]; - copy = 3 + (hold & 0x03);//BITS(2); - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - } - else if (here_val === 17) { - //=== NEEDBITS(here.bits + 3); - n = here_bits + 3; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 3 + (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - else { - //=== NEEDBITS(here.bits + 7); - n = here_bits + 7; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 11 + (hold & 0x7f);//BITS(7); - //--- DROPBITS(7) ---// - hold >>>= 7; - bits -= 7; - //---// - } - if (state.have + copy > state.nlen + state.ndist) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - while (copy--) { - state.lens[state.have++] = len; - } - } - } - - /* handle error breaks in while */ - if (state.mode === BAD) { break; } - - /* check for end-of-block code (better have one) */ - if (state.lens[256] === 0) { - strm.msg = 'invalid code -- missing end-of-block'; - state.mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state.lenbits = 9; - - opts = { bits: state.lenbits }; - ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.lenbits = opts.bits; - // state.lencode = state.next; - - if (ret) { - strm.msg = 'invalid literal/lengths set'; - state.mode = BAD; - break; - } - - state.distbits = 6; - //state.distcode.copy(state.codes); - // Switch to use dynamic table - state.distcode = state.distdyn; - opts = { bits: state.distbits }; - ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.distbits = opts.bits; - // state.distcode = state.next; - - if (ret) { - strm.msg = 'invalid distances set'; - state.mode = BAD; - break; - } - //Tracev((stderr, 'inflate: codes ok\n')); - state.mode = LEN_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case LEN_: - state.mode = LEN; - /* falls through */ - case LEN: - if (have >= 6 && left >= 258) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - inflate_fast(strm, _out); - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - if (state.mode === TYPE) { - state.back = -1; - } - break; - } - state.back = 0; - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if (here_bits <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_op && (here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.lencode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - state.length = here_val; - if (here_op === 0) { - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - state.mode = LIT; - break; - } - if (here_op & 32) { - //Tracevv((stderr, "inflate: end of block\n")); - state.back = -1; - state.mode = TYPE; - break; - } - if (here_op & 64) { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break; - } - state.extra = here_op & 15; - state.mode = LENEXT; - /* falls through */ - case LENEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //Tracevv((stderr, "inflate: length %u\n", state.length)); - state.was = state.length; - state.mode = DIST; - /* falls through */ - case DIST: - for (;;) { - here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if ((here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.distcode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - if (here_op & 64) { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break; - } - state.offset = here_val; - state.extra = (here_op) & 15; - state.mode = DISTEXT; - /* falls through */ - case DISTEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } -//#ifdef INFLATE_STRICT - if (state.offset > state.dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -//#endif - //Tracevv((stderr, "inflate: distance %u\n", state.offset)); - state.mode = MATCH; - /* falls through */ - case MATCH: - if (left === 0) { break inf_leave; } - copy = _out - left; - if (state.offset > copy) { /* copy from window */ - copy = state.offset - copy; - if (copy > state.whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -// (!) This block is disabled in zlib defailts, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// Trace((stderr, "inflate.c too far\n")); -// copy -= state.whave; -// if (copy > state.length) { copy = state.length; } -// if (copy > left) { copy = left; } -// left -= copy; -// state.length -= copy; -// do { -// output[put++] = 0; -// } while (--copy); -// if (state.length === 0) { state.mode = LEN; } -// break; -//#endif - } - if (copy > state.wnext) { - copy -= state.wnext; - from = state.wsize - copy; - } - else { - from = state.wnext - copy; - } - if (copy > state.length) { copy = state.length; } - from_source = state.window; - } - else { /* copy from output */ - from_source = output; - from = put - state.offset; - copy = state.length; - } - if (copy > left) { copy = left; } - left -= copy; - state.length -= copy; - do { - output[put++] = from_source[from++]; - } while (--copy); - if (state.length === 0) { state.mode = LEN; } - break; - case LIT: - if (left === 0) { break inf_leave; } - output[put++] = state.length; - left--; - state.mode = LEN; - break; - case CHECK: - if (state.wrap) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - // Use '|' insdead of '+' to make sure that result is signed - hold |= input[next++] << bits; - bits += 8; - } - //===// - _out -= left; - strm.total_out += _out; - state.total += _out; - if (_out) { - strm.adler = state.check = - /*UPDATE(state.check, put - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); - - } - _out = left; - // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too - if ((state.flags ? hold : zswap32(hold)) !== state.check) { - strm.msg = 'incorrect data check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: check matches trailer\n")); - } - state.mode = LENGTH; - /* falls through */ - case LENGTH: - if (state.wrap && state.flags) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.total & 0xffffffff)) { - strm.msg = 'incorrect length check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: length matches trailer\n")); - } - state.mode = DONE; - /* falls through */ - case DONE: - ret = Z_STREAM_END; - break inf_leave; - case BAD: - ret = Z_DATA_ERROR; - break inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - /* falls through */ - default: - return Z_STREAM_ERROR; - } - } - - // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - - if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && - (state.mode < CHECK || flush !== Z_FINISH))) { - if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { - state.mode = MEM; - return Z_MEM_ERROR; - } - } - _in -= strm.avail_in; - _out -= strm.avail_out; - strm.total_in += _in; - strm.total_out += _out; - state.total += _out; - if (state.wrap && _out) { - strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); - } - strm.data_type = state.bits + (state.last ? 64 : 0) + - (state.mode === TYPE ? 128 : 0) + - (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); - if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { - ret = Z_BUF_ERROR; - } - return ret; -} - -function inflateEnd(strm) { - - if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { - return Z_STREAM_ERROR; - } - - var state = strm.state; - if (state.window) { - state.window = null; - } - strm.state = null; - return Z_OK; -} - -function inflateGetHeader(strm, head) { - var state; - - /* check state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } - - /* save header structure */ - state.head = head; - head.done = false; - return Z_OK; -} - -function inflateSetDictionary(strm, dictionary) { - var dictLength = dictionary.length; - - var state; - var dictid; - var ret; - - /* check state */ - if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } - state = strm.state; - - if (state.wrap !== 0 && state.mode !== DICT) { - return Z_STREAM_ERROR; - } - - /* check for correct dictionary identifier */ - if (state.mode === DICT) { - dictid = 1; /* adler32(0, null, 0)*/ - /* dictid = adler32(dictid, dictionary, dictLength); */ - dictid = adler32(dictid, dictionary, dictLength, 0); - if (dictid !== state.check) { - return Z_DATA_ERROR; - } - } - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary, dictLength, dictLength); - if (ret) { - state.mode = MEM; - return Z_MEM_ERROR; - } - state.havedict = 1; - // Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -exports.inflateReset = inflateReset; -exports.inflateReset2 = inflateReset2; -exports.inflateResetKeep = inflateResetKeep; -exports.inflateInit = inflateInit; -exports.inflateInit2 = inflateInit2; -exports.inflate = inflate; -exports.inflateEnd = inflateEnd; -exports.inflateGetHeader = inflateGetHeader; -exports.inflateSetDictionary = inflateSetDictionary; -exports.inflateInfo = 'pako inflate (from Nodeca project)'; - -/* Not implemented -exports.inflateCopy = inflateCopy; -exports.inflateGetDictionary = inflateGetDictionary; -exports.inflateMark = inflateMark; -exports.inflatePrime = inflatePrime; -exports.inflateSync = inflateSync; -exports.inflateSyncPoint = inflateSyncPoint; -exports.inflateUndermine = inflateUndermine; -*/ - -},{"../utils/common":2,"./adler32":3,"./crc32":4,"./inffast":5,"./inftrees":7}],7:[function(require,module,exports){ -'use strict'; - - -var utils = require('../utils/common'); - -var MAXBITS = 15; -var ENOUGH_LENS = 852; -var ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - -var CODES = 0; -var LENS = 1; -var DISTS = 2; - -var lbase = [ /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 -]; - -var lext = [ /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 -]; - -var dbase = [ /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0 -]; - -var dext = [ /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64 -]; - -module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) -{ - var bits = opts.bits; - //here = opts.here; /* table entry for duplication */ - - var len = 0; /* a code's length in bits */ - var sym = 0; /* index of code symbols */ - var min = 0, max = 0; /* minimum and maximum code lengths */ - var root = 0; /* number of index bits for root table */ - var curr = 0; /* number of index bits for current table */ - var drop = 0; /* code bits to drop for sub-table */ - var left = 0; /* number of prefix codes available */ - var used = 0; /* code entries in table used */ - var huff = 0; /* Huffman code */ - var incr; /* for incrementing code, index */ - var fill; /* index for replicating entries */ - var low; /* low bits for current root entry */ - var mask; /* mask for low root bits */ - var next; /* next available space in table */ - var base = null; /* base value table to use */ - var base_index = 0; -// var shoextra; /* extra bits table to use */ - var end; /* use base and extra for symbol > end */ - var count = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ - var offs = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ - var extra = null; - var extra_index = 0; - - var here_bits, here_op, here_val; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) { - count[len] = 0; - } - for (sym = 0; sym < codes; sym++) { - count[lens[lens_index + sym]]++; - } - - /* bound code lengths, force root to be within code lengths */ - root = bits; - for (max = MAXBITS; max >= 1; max--) { - if (count[max] !== 0) { break; } - } - if (root > max) { - root = max; - } - if (max === 0) { /* no symbols to code at all */ - //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ - //table.bits[opts.table_index] = 1; //here.bits = (var char)1; - //table.val[opts.table_index++] = 0; //here.val = (var short)0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; - - - //table.op[opts.table_index] = 64; - //table.bits[opts.table_index] = 1; - //table.val[opts.table_index++] = 0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; - - opts.bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) { - if (count[min] !== 0) { break; } - } - if (root < min) { - root = min; - } - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) { - return -1; - } /* over-subscribed */ - } - if (left > 0 && (type === CODES || max !== 1)) { - return -1; /* incomplete set */ - } - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) { - offs[len + 1] = offs[len] + count[len]; - } - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) { - if (lens[lens_index + sym] !== 0) { - work[offs[lens[lens_index + sym]]++] = sym; - } - } - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - // poor man optimization - use if-else instead of switch, - // to avoid deopts in old v8 - if (type === CODES) { - base = extra = work; /* dummy value--not used */ - end = 19; - - } else if (type === LENS) { - base = lbase; - base_index -= 257; - extra = lext; - extra_index -= 257; - end = 256; - - } else { /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize opts for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = table_index; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = -1; /* trigger new sub-table when len > root */ - used = 1 << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; - } - - var i = 0; - /* process all codes and make table entries */ - for (;;) { - i++; - /* create table entry */ - here_bits = len - drop; - if (work[sym] < end) { - here_op = 0; - here_val = work[sym]; - } - else if (work[sym] > end) { - here_op = extra[extra_index + work[sym]]; - here_val = base[base_index + work[sym]]; - } - else { - here_op = 32 + 64; /* end of block */ - here_val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1 << (len - drop); - fill = 1 << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; - } while (fill !== 0); - - /* backwards increment the len-bit code huff */ - incr = 1 << (len - 1); - while (huff & incr) { - incr >>= 1; - } - if (incr !== 0) { - huff &= incr - 1; - huff += incr; - } else { - huff = 0; - } - - /* go to next symbol, update count, len */ - sym++; - if (--count[len] === 0) { - if (len === max) { break; } - len = lens[lens_index + work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) !== low) { - /* if first time, transition to sub-tables */ - if (drop === 0) { - drop = root; - } - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = 1 << curr; - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) { break; } - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1 << curr; - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; - } - - /* point entry in root table to sub-table */ - low = huff & mask; - /*table.op[low] = curr; - table.bits[low] = root; - table.val[low] = next - opts.table_index;*/ - table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff !== 0) { - //table.op[next + huff] = 64; /* invalid code marker */ - //table.bits[next + huff] = len - drop; - //table.val[next + huff] = 0; - table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; - } - - /* set return parameters */ - //opts.table_index += used; - opts.bits = root; - return 0; -}; - -},{"../utils/common":2}],8:[function(require,module,exports){ -'use strict'; - - -function ZStream() { - /* next input byte */ - this.input = null; // JS specific, because we have no pointers - this.next_in = 0; - /* number of bytes available at input */ - this.avail_in = 0; - /* total number of input bytes read so far */ - this.total_in = 0; - /* next output byte should be put there */ - this.output = null; // JS specific, because we have no pointers - this.next_out = 0; - /* remaining free space at output */ - this.avail_out = 0; - /* total number of bytes output so far */ - this.total_out = 0; - /* last error message, NULL if no error */ - this.msg = ''/*Z_NULL*/; - /* not visible by applications */ - this.state = null; - /* best guess about the data type: binary or text */ - this.data_type = 2/*Z_UNKNOWN*/; - /* adler32 value of the uncompressed data */ - this.adler = 0; -} - -module.exports = ZStream; - -},{}]},{},[1])(1) -}); \ No newline at end of file +define("pako/lib/utils/common",["require","exports","module"],function(e,t,n){var r=typeof Uint8Array!="undefined"&&typeof Uint16Array!="undefined"&&typeof Int32Array!="undefined";t.assign=function(e){var t=Array.prototype.slice.call(arguments,1);while(t.length){var n=t.shift();if(!n)continue;if(typeof n!="object")throw new TypeError(n+"must be non-object");for(var r in n)n.hasOwnProperty(r)&&(e[r]=n[r])}return e},t.shrinkBuf=function(e,t){return e.length===t?e:e.subarray?e.subarray(0,t):(e.length=t,e)};var i={arraySet:function(e,t,n,r,i){if(t.subarray&&e.subarray){e.set(t.subarray(n,n+r),i);return}for(var s=0;s>>16&65535|0,o=0;while(n!==0){o=n>2e3?2e3:n,n-=o;do i=i+t[r++]|0,s=s+i|0;while(--o);i%=65521,s%=65521}return i|s<<16|0}n.exports=r}),define("pako/lib/zlib/crc32",["require","exports","module"],function(e,t,n){function r(){var e,t=[];for(var n=0;n<256;n++){e=n;for(var r=0;r<8;r++)e=e&1?3988292384^e>>>1:e>>>1;t[n]=e}return t}function s(e,t,n,r){var s=i,o=r+n;e^=-1;for(var u=r;u>>8^s[(e^t[u])&255];return e^-1}var i=r();n.exports=s}),define("pako/lib/zlib/inffast",["require","exports","module"],function(e,t,n){var r=30,i=12;n.exports=function(t,n){var s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L,A;s=t.state,o=t.next_in,L=t.input,u=o+(t.avail_in-5),a=t.next_out,A=t.output,f=a-(n-t.avail_out),l=a+(t.avail_out-257),c=s.dmax,h=s.wsize,p=s.whave,d=s.wnext,v=s.window,m=s.hold,g=s.bits,y=s.lencode,b=s.distcode,w=(1<>>24,m>>>=x,g-=x,x=S>>>16&255;if(x===0)A[a++]=S&65535;else{if(!(x&16)){if((x&64)===0){S=y[(S&65535)+(m&(1<>>=x,g-=x),g<15&&(m+=L[o++]<>>24,m>>>=x,g-=x,x=S>>>16&255;if(!(x&16)){if((x&64)===0){S=b[(S&65535)+(m&(1<c){t.msg="invalid distance too far back",s.mode=r;break e}m>>>=x,g-=x,x=a-f;if(N>x){x=N-x;if(x>p&&s.sane){t.msg="invalid distance too far back",s.mode=r;break e}C=0,k=v;if(d===0){C+=h-x;if(x2)A[a++]=k[C++],A[a++]=k[C++],A[a++]=k[C++],T-=3;T&&(A[a++]=k[C++],T>1&&(A[a++]=k[C++]))}else{C=a-N;do A[a++]=A[C++],A[a++]=A[C++],A[a++]=A[C++],T-=3;while(T>2);T&&(A[a++]=A[C++],T>1&&(A[a++]=A[C++]))}break}}break}}while(o>3,o-=T,g-=T<<3,m&=(1<=1;T--)if(I[T]!==0)break;N>T&&(N=T);if(T===0)return m[g++]=20971520,m[g++]=20971520,b.bits=1,0;for(x=1;x0&&(t===u||T!==1))return-1;q[1]=0;for(E=1;Es||t===f&&A>o)return 1;for(;;){z=E-k,y[S]F?(W=R[U+y[S]],X=B[j+y[S]]):(W=96,X=0),M=1<>k)+_]=z<<24|W<<16|X|0;while(_!==0);M=1<>=1;M!==0?(O&=M-1,O+=M):O=0,S++;if(--I[E]===0){if(E===T)break;E=n[d+y[S]]}if(E>N&&(O&P)!==D){k===0&&(k=N),H+=x,C=E-k,L=1<s||t===f&&A>o)return 1;D=O&P,m[D]=N<<24|C<<16|H-g|0}}return O!==0&&(m[H+O]=E-k<<24|64<<16|0),b.bits=N,0}}),define("pako/lib/zlib/inflate.js",["require","exports","module","../utils/common","./adler32","./crc32","./inffast","./inftrees"],function(e,t,n){function it(e){return(e>>>24&255)+(e>>>8&65280)+((e&65280)<<8)+((e&255)<<24)}function st(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function ot(e){var t;return!e||!e.state?g:(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=t.wrap&1),t.mode=S,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new r.Buf32(et),t.distcode=t.distdyn=new r.Buf32(tt),t.sane=1,t.back=-1,d)}function ut(e){var t;return!e||!e.state?g:(t=e.state,t.wsize=0,t.whave=0,t.wnext=0,ot(e))}function at(e,t){var n,r;return!e||!e.state?g:(r=e.state,t<0?(n=0,t=-t):(n=(t>>4)+1,t<48&&(t&=15)),t&&(t<8||t>15)?g:(r.window!==null&&r.wbits!==t&&(r.window=null),r.wrap=n,r.wbits=t,ut(e)))}function ft(e,t){var n,r;return e?(r=new st,e.state=r,r.window=null,n=at(e,t),n!==d&&(e.state=null),n):g}function lt(e){return ft(e,rt)}function dt(e){if(ct){var t;ht=new r.Buf32(512),pt=new r.Buf32(32),t=0;while(t<144)e.lens[t++]=8;while(t<256)e.lens[t++]=9;while(t<280)e.lens[t++]=7;while(t<288)e.lens[t++]=8;u(f,e.lens,0,288,ht,0,e.work,{bits:9}),t=0;while(t<32)e.lens[t++]=5;u(l,e.lens,0,32,pt,0,e.work,{bits:5}),ct=!1}e.lencode=ht,e.lenbits=9,e.distcode=pt,e.distbits=5}function vt(e,t,n,i){var s,o=e.state;return o.window===null&&(o.wsize=1<=o.wsize?(r.arraySet(o.window,t,n-o.wsize,o.wsize,0),o.wnext=0,o.whave=o.wsize):(s=o.wsize-o.wnext,s>i&&(s=i),r.arraySet(o.window,t,n-i,s,o.wnext),i-=s,i?(r.arraySet(o.window,t,n-i,i,0),o.wnext=i,o.whave=o.wsize):(o.wnext+=s,o.wnext===o.wsize&&(o.wnext=0),o.whave>>8&255,n.check=s(n.check,Nt,2,0),ut=0,at=0,n.mode=x;break}n.flags=0,n.head&&(n.head.done=!1);if(!(n.wrap&1)||(((ut&255)<<8)+(ut>>8))%31){e.msg="incorrect header check",n.mode=G;break}if((ut&15)!==E){e.msg="unknown compression method",n.mode=G;break}ut>>>=4,at-=4,xt=(ut&15)+8;if(n.wbits===0)n.wbits=xt;else if(xt>n.wbits){e.msg="invalid window size",n.mode=G;break}n.dmax=1<>8&1),n.flags&512&&(Nt[0]=ut&255,Nt[1]=ut>>>8&255,n.check=s(n.check,Nt,2,0)),ut=0,at=0,n.mode=T;case T:while(at<32){if(st===0)break e;st--,ut+=et[nt++]<>>8&255,Nt[2]=ut>>>16&255,Nt[3]=ut>>>24&255,n.check=s(n.check,Nt,4,0)),ut=0,at=0,n.mode=N;case N:while(at<16){if(st===0)break e;st--,ut+=et[nt++]<>8),n.flags&512&&(Nt[0]=ut&255,Nt[1]=ut>>>8&255,n.check=s(n.check,Nt,2,0)),ut=0,at=0,n.mode=C;case C:if(n.flags&1024){while(at<16){if(st===0)break e;st--,ut+=et[nt++]<>>8&255,n.check=s(n.check,Nt,2,0)),ut=0,at=0}else n.head&&(n.head.extra=null);n.mode=k;case k:if(n.flags&1024){ct=n.length,ct>st&&(ct=st),ct&&(n.head&&(xt=n.head.extra_len-n.length,n.head.extra||(n.head.extra=new Array(n.head.extra_len)),r.arraySet(n.head.extra,et,nt,ct,xt)),n.flags&512&&(n.check=s(n.check,et,ct,nt)),st-=ct,nt+=ct,n.length-=ct);if(n.length)break e}n.length=0,n.mode=L;case L:if(n.flags&2048){if(st===0)break e;ct=0;do xt=et[nt+ct++],n.head&&xt&&n.length<65536&&(n.head.name+=String.fromCharCode(xt));while(xt&&ct>9&1,n.head.done=!0),e.adler=n.check=0,n.mode=D;break;case M:while(at<32){if(st===0)break e;st--,ut+=et[nt++]<>>=at&7,at-=at&7,n.mode=J;break}while(at<3){if(st===0)break e;st--,ut+=et[nt++]<>>=1,at-=1;switch(ut&3){case 0:n.mode=H;break;case 1:dt(n),n.mode=R;if(t===p){ut>>>=2,at-=2;break e}break;case 2:n.mode=F;break;case 3:e.msg="invalid block type",n.mode=G}ut>>>=2,at-=2;break;case H:ut>>>=at&7,at-=at&7;while(at<32){if(st===0)break e;st--,ut+=et[nt++]<>>16^65535)){e.msg="invalid stored block lengths",n.mode=G;break}n.length=ut&65535,ut=0,at=0,n.mode=B;if(t===p)break e;case B:n.mode=j;case j:ct=n.length;if(ct){ct>st&&(ct=st),ct>ot&&(ct=ot);if(ct===0)break e;r.arraySet(tt,et,nt,ct,rt),st-=ct,nt+=ct,ot-=ct,rt+=ct,n.length-=ct;break}n.mode=D;break;case F:while(at<14){if(st===0)break e;st--,ut+=et[nt++]<>>=5,at-=5,n.ndist=(ut&31)+1,ut>>>=5,at-=5,n.ncode=(ut&15)+4,ut>>>=4,at-=4;if(n.nlen>286||n.ndist>30){e.msg="too many length or distance symbols",n.mode=G;break}n.have=0,n.mode=I;case I:while(n.have>>=3,at-=3}while(n.have<19)n.lens[Lt[n.have++]]=0;n.lencode=n.lendyn,n.lenbits=7,Ct={bits:n.lenbits},Tt=u(a,n.lens,0,19,n.lencode,0,n.work,Ct),n.lenbits=Ct.bits;if(Tt){e.msg="invalid code lengths set",n.mode=G;break}n.have=0,n.mode=q;case q:while(n.have>>24,yt=mt>>>16&255,bt=mt&65535;if(gt<=at)break;if(st===0)break e;st--,ut+=et[nt++]<>>=gt,at-=gt,n.lens[n.have++]=bt;else{if(bt===16){kt=gt+2;while(at>>=gt,at-=gt;if(n.have===0){e.msg="invalid bit length repeat",n.mode=G;break}xt=n.lens[n.have-1],ct=3+(ut&3),ut>>>=2,at-=2}else if(bt===17){kt=gt+3;while(at>>=gt,at-=gt,xt=0,ct=3+(ut&7),ut>>>=3,at-=3}else{kt=gt+7;while(at>>=gt,at-=gt,xt=0,ct=11+(ut&127),ut>>>=7,at-=7}if(n.have+ct>n.nlen+n.ndist){e.msg="invalid bit length repeat",n.mode=G;break}while(ct--)n.lens[n.have++]=xt}}if(n.mode===G)break;if(n.lens[256]===0){e.msg="invalid code -- missing end-of-block",n.mode=G;break}n.lenbits=9,Ct={bits:n.lenbits},Tt=u(f,n.lens,0,n.nlen,n.lencode,0,n.work,Ct),n.lenbits=Ct.bits;if(Tt){e.msg="invalid literal/lengths set",n.mode=G;break}n.distbits=6,n.distcode=n.distdyn,Ct={bits:n.distbits},Tt=u(l,n.lens,n.nlen,n.ndist,n.distcode,0,n.work,Ct),n.distbits=Ct.bits;if(Tt){e.msg="invalid distances set",n.mode=G;break}n.mode=R;if(t===p)break e;case R:n.mode=U;case U:if(st>=6&&ot>=258){e.next_out=rt,e.avail_out=ot,e.next_in=nt,e.avail_in=st,n.hold=ut,n.bits=at,o(e,lt),rt=e.next_out,tt=e.output,ot=e.avail_out,nt=e.next_in,et=e.input,st=e.avail_in,ut=n.hold,at=n.bits,n.mode===D&&(n.back=-1);break}n.back=0;for(;;){mt=n.lencode[ut&(1<>>24,yt=mt>>>16&255,bt=mt&65535;if(gt<=at)break;if(st===0)break e;st--,ut+=et[nt++]<>wt)],gt=mt>>>24,yt=mt>>>16&255,bt=mt&65535;if(wt+gt<=at)break;if(st===0)break e;st--,ut+=et[nt++]<>>=wt,at-=wt,n.back+=wt}ut>>>=gt,at-=gt,n.back+=gt,n.length=bt;if(yt===0){n.mode=$;break}if(yt&32){n.back=-1,n.mode=D;break}if(yt&64){e.msg="invalid literal/length code",n.mode=G;break}n.extra=yt&15,n.mode=z;case z:if(n.extra){kt=n.extra;while(at>>=n.extra,at-=n.extra,n.back+=n.extra}n.was=n.length,n.mode=W;case W:for(;;){mt=n.distcode[ut&(1<>>24,yt=mt>>>16&255,bt=mt&65535;if(gt<=at)break;if(st===0)break e;st--,ut+=et[nt++]<>wt)],gt=mt>>>24,yt=mt>>>16&255,bt=mt&65535;if(wt+gt<=at)break;if(st===0)break e;st--,ut+=et[nt++]<>>=wt,at-=wt,n.back+=wt}ut>>>=gt,at-=gt,n.back+=gt;if(yt&64){e.msg="invalid distance code",n.mode=G;break}n.offset=bt,n.extra=yt&15,n.mode=X;case X:if(n.extra){kt=n.extra;while(at>>=n.extra,at-=n.extra,n.back+=n.extra}if(n.offset>n.dmax){e.msg="invalid distance too far back",n.mode=G;break}n.mode=V;case V:if(ot===0)break e;ct=lt-ot;if(n.offset>ct){ct=n.offset-ct;if(ct>n.whave&&n.sane){e.msg="invalid distance too far back",n.mode=G;break}ct>n.wnext?(ct-=n.wnext,ht=n.wsize-ct):ht=n.wnext-ct,ct>n.length&&(ct=n.length),pt=n.window}else pt=tt,ht=rt-n.offset,ct=n.length;ct>ot&&(ct=ot),ot-=ct,n.length-=ct;do tt[rt++]=pt[ht++];while(--ct);n.length===0&&(n.mode=U);break;case $:if(ot===0)break e;tt[rt++]=n.length,ot--,n.mode=U;break;case J:if(n.wrap){while(at<32){if(st===0)break e;st--,ut|=et[nt++]<this.chunkSize&&(this.chunkSize=r,this.strm.output=new Uint8Array(this.chunkSize)),this.strm.avail_out=this.chunkSize,e.inflate(this.strm,n),new Uint8Array(this.strm.output.buffer,0,this.strm.next_out)},reset:function(){e.inflateReset(this.strm)}},{Inflate:n}}); \ No newline at end of file diff --git a/core/inflator.mod.js b/core/inflator.mod.js deleted file mode 100644 index 26e6441b..00000000 --- a/core/inflator.mod.js +++ /dev/null @@ -1,40 +0,0 @@ -var zlib = require('pako/lib/zlib/inflate.js'); -var ZStream = require('pako/lib/zlib/zstream.js'); - -function Inflate() { - this.strm = new ZStream(); - this.chunkSize = 1024 * 10 * 10; - this.strm.output = new Uint8Array(this.chunkSize); - this.windowBits = 5; - - zlib.inflateInit(this.strm, this.windowBits); -}; - -Inflate.prototype = { - inflate: function (data, flush, expected) { - this.strm.input = data; - this.strm.avail_in = this.strm.input.length; - this.strm.next_in = 0; - this.strm.next_out = 0; - - // resize our output buffer if it's too small - // (we could just use multiple chunks, but that would cause an extra - // allocation each time to flatten the chunks) - if (expected > this.chunkSize) { - this.chunkSize = expected; - this.strm.output = new Uint8Array(this.chunkSize); - } - - this.strm.avail_out = this.chunkSize; - - zlib.inflate(this.strm, flush); - - return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out); - }, - - reset: function () { - zlib.inflateReset(this.strm); - } -}; - -module.exports = { Inflate: Inflate }; diff --git a/core/input/devices.js b/core/input/devices.js index 47f75abe..ff344a40 100644 --- a/core/input/devices.js +++ b/core/input/devices.js @@ -2,28 +2,21 @@ * noVNC: HTML5 VNC client * Copyright (C) 2012 Joel Martin * Copyright (C) 2013 Samuel Mannehed for Cendio AB + * Copyright (C) 2017 Pierre Ossman for Cendio AB * Licensed under MPL 2.0 or any later version (see LICENSE.txt) */ /*jslint browser: true, white: false */ -/*global window, Util */ - -/* [module] - * import Util from "../util"; - * import KeyboardUtil from "./util"; - */ "use strict"; -/* [module] export */ var Keyboard; - -(function () { - +define(["core/util", "core/input/util"], +function (Util, KeyboardUtil) { // // Keyboard event handler // - Keyboard = function (defaults) { + function Keyboard(defaults) { this._keyDownList = []; // List of depressed keys // (even if they are happy) @@ -159,12 +152,8 @@ ['onKeyPress', 'rw', 'func'] // Handler for key press/release ]); -})(); -/* [module] export */ var Mouse; - -(function () { - Mouse = function (defaults) { + function Mouse(defaults) { this._mouseCaptured = false; this._doubleClickTimer = null; @@ -403,4 +392,7 @@ ['onMouseMove', 'rw', 'func'], // Handler for mouse movement ['touchButton', 'rw', 'int'] // Button mask (1, 2, 4) for touch devices (0 means ignore clicks) ]); -})(); + + return { Keyboard: Keyboard, + Mouse: Mouse }; +}); diff --git a/core/input/keysym.js b/core/input/keysym.js index a6b23fcc..d670c3c3 100644 --- a/core/input/keysym.js +++ b/core/input/keysym.js @@ -1,384 +1,386 @@ "use strict"; -var KeyTable = { - XK_VoidSymbol: 0xffffff, /* Void symbol */ +define(function () { + var KeyTable = { + XK_VoidSymbol: 0xffffff, /* Void symbol */ - XK_BackSpace: 0xff08, /* Back space, back char */ - XK_Tab: 0xff09, - XK_Linefeed: 0xff0a, /* Linefeed, LF */ - XK_Clear: 0xff0b, - XK_Return: 0xff0d, /* Return, enter */ - XK_Pause: 0xff13, /* Pause, hold */ - XK_Scroll_Lock: 0xff14, - XK_Sys_Req: 0xff15, - XK_Escape: 0xff1b, - XK_Delete: 0xffff, /* Delete, rubout */ + XK_BackSpace: 0xff08, /* Back space, back char */ + XK_Tab: 0xff09, + XK_Linefeed: 0xff0a, /* Linefeed, LF */ + XK_Clear: 0xff0b, + XK_Return: 0xff0d, /* Return, enter */ + XK_Pause: 0xff13, /* Pause, hold */ + XK_Scroll_Lock: 0xff14, + XK_Sys_Req: 0xff15, + XK_Escape: 0xff1b, + XK_Delete: 0xffff, /* Delete, rubout */ - /* Cursor control & motion */ + /* Cursor control & motion */ - XK_Home: 0xff50, - XK_Left: 0xff51, /* Move left, left arrow */ - XK_Up: 0xff52, /* Move up, up arrow */ - XK_Right: 0xff53, /* Move right, right arrow */ - XK_Down: 0xff54, /* Move down, down arrow */ - XK_Prior: 0xff55, /* Prior, previous */ - XK_Page_Up: 0xff55, - XK_Next: 0xff56, /* Next */ - XK_Page_Down: 0xff56, - XK_End: 0xff57, /* EOL */ - XK_Begin: 0xff58, /* BOL */ + XK_Home: 0xff50, + XK_Left: 0xff51, /* Move left, left arrow */ + XK_Up: 0xff52, /* Move up, up arrow */ + XK_Right: 0xff53, /* Move right, right arrow */ + XK_Down: 0xff54, /* Move down, down arrow */ + XK_Prior: 0xff55, /* Prior, previous */ + XK_Page_Up: 0xff55, + XK_Next: 0xff56, /* Next */ + XK_Page_Down: 0xff56, + XK_End: 0xff57, /* EOL */ + XK_Begin: 0xff58, /* BOL */ - /* Misc functions */ + /* Misc functions */ - XK_Select: 0xff60, /* Select, mark */ - XK_Print: 0xff61, - XK_Execute: 0xff62, /* Execute, run, do */ - XK_Insert: 0xff63, /* Insert, insert here */ - XK_Undo: 0xff65, - XK_Redo: 0xff66, /* Redo, again */ - XK_Menu: 0xff67, - XK_Find: 0xff68, /* Find, search */ - XK_Cancel: 0xff69, /* Cancel, stop, abort, exit */ - XK_Help: 0xff6a, /* Help */ - XK_Break: 0xff6b, - XK_Mode_switch: 0xff7e, /* Character set switch */ - XK_script_switch: 0xff7e, /* Alias for mode_switch */ - XK_Num_Lock: 0xff7f, + XK_Select: 0xff60, /* Select, mark */ + XK_Print: 0xff61, + XK_Execute: 0xff62, /* Execute, run, do */ + XK_Insert: 0xff63, /* Insert, insert here */ + XK_Undo: 0xff65, + XK_Redo: 0xff66, /* Redo, again */ + XK_Menu: 0xff67, + XK_Find: 0xff68, /* Find, search */ + XK_Cancel: 0xff69, /* Cancel, stop, abort, exit */ + XK_Help: 0xff6a, /* Help */ + XK_Break: 0xff6b, + XK_Mode_switch: 0xff7e, /* Character set switch */ + XK_script_switch: 0xff7e, /* Alias for mode_switch */ + XK_Num_Lock: 0xff7f, - /* Keypad functions, keypad numbers cleverly chosen to map to ASCII */ + /* Keypad functions, keypad numbers cleverly chosen to map to ASCII */ - XK_KP_Space: 0xff80, /* Space */ - XK_KP_Tab: 0xff89, - XK_KP_Enter: 0xff8d, /* Enter */ - XK_KP_F1: 0xff91, /* PF1, KP_A, ... */ - XK_KP_F2: 0xff92, - XK_KP_F3: 0xff93, - XK_KP_F4: 0xff94, - XK_KP_Home: 0xff95, - XK_KP_Left: 0xff96, - XK_KP_Up: 0xff97, - XK_KP_Right: 0xff98, - XK_KP_Down: 0xff99, - XK_KP_Prior: 0xff9a, - XK_KP_Page_Up: 0xff9a, - XK_KP_Next: 0xff9b, - XK_KP_Page_Down: 0xff9b, - XK_KP_End: 0xff9c, - XK_KP_Begin: 0xff9d, - XK_KP_Insert: 0xff9e, - XK_KP_Delete: 0xff9f, - XK_KP_Equal: 0xffbd, /* Equals */ - XK_KP_Multiply: 0xffaa, - XK_KP_Add: 0xffab, - XK_KP_Separator: 0xffac, /* Separator, often comma */ - XK_KP_Subtract: 0xffad, - XK_KP_Decimal: 0xffae, - XK_KP_Divide: 0xffaf, + XK_KP_Space: 0xff80, /* Space */ + XK_KP_Tab: 0xff89, + XK_KP_Enter: 0xff8d, /* Enter */ + XK_KP_F1: 0xff91, /* PF1, KP_A, ... */ + XK_KP_F2: 0xff92, + XK_KP_F3: 0xff93, + XK_KP_F4: 0xff94, + XK_KP_Home: 0xff95, + XK_KP_Left: 0xff96, + XK_KP_Up: 0xff97, + XK_KP_Right: 0xff98, + XK_KP_Down: 0xff99, + XK_KP_Prior: 0xff9a, + XK_KP_Page_Up: 0xff9a, + XK_KP_Next: 0xff9b, + XK_KP_Page_Down: 0xff9b, + XK_KP_End: 0xff9c, + XK_KP_Begin: 0xff9d, + XK_KP_Insert: 0xff9e, + XK_KP_Delete: 0xff9f, + XK_KP_Equal: 0xffbd, /* Equals */ + XK_KP_Multiply: 0xffaa, + XK_KP_Add: 0xffab, + XK_KP_Separator: 0xffac, /* Separator, often comma */ + XK_KP_Subtract: 0xffad, + XK_KP_Decimal: 0xffae, + XK_KP_Divide: 0xffaf, - XK_KP_0: 0xffb0, - XK_KP_1: 0xffb1, - XK_KP_2: 0xffb2, - XK_KP_3: 0xffb3, - XK_KP_4: 0xffb4, - XK_KP_5: 0xffb5, - XK_KP_6: 0xffb6, - XK_KP_7: 0xffb7, - XK_KP_8: 0xffb8, - XK_KP_9: 0xffb9, + XK_KP_0: 0xffb0, + XK_KP_1: 0xffb1, + XK_KP_2: 0xffb2, + XK_KP_3: 0xffb3, + XK_KP_4: 0xffb4, + XK_KP_5: 0xffb5, + XK_KP_6: 0xffb6, + XK_KP_7: 0xffb7, + XK_KP_8: 0xffb8, + XK_KP_9: 0xffb9, - /* - * Auxiliary functions; note the duplicate definitions for left and right - * function keys; Sun keyboards and a few other manufacturers have such - * function key groups on the left and/or right sides of the keyboard. - * We've not found a keyboard with more than 35 function keys total. - */ + /* + * Auxiliary functions; note the duplicate definitions for left and right + * function keys; Sun keyboards and a few other manufacturers have such + * function key groups on the left and/or right sides of the keyboard. + * We've not found a keyboard with more than 35 function keys total. + */ - XK_F1: 0xffbe, - XK_F2: 0xffbf, - XK_F3: 0xffc0, - XK_F4: 0xffc1, - XK_F5: 0xffc2, - XK_F6: 0xffc3, - XK_F7: 0xffc4, - XK_F8: 0xffc5, - XK_F9: 0xffc6, - XK_F10: 0xffc7, - XK_F11: 0xffc8, - XK_L1: 0xffc8, - XK_F12: 0xffc9, - XK_L2: 0xffc9, - XK_F13: 0xffca, - XK_L3: 0xffca, - XK_F14: 0xffcb, - XK_L4: 0xffcb, - XK_F15: 0xffcc, - XK_L5: 0xffcc, - XK_F16: 0xffcd, - XK_L6: 0xffcd, - XK_F17: 0xffce, - XK_L7: 0xffce, - XK_F18: 0xffcf, - XK_L8: 0xffcf, - XK_F19: 0xffd0, - XK_L9: 0xffd0, - XK_F20: 0xffd1, - XK_L10: 0xffd1, - XK_F21: 0xffd2, - XK_R1: 0xffd2, - XK_F22: 0xffd3, - XK_R2: 0xffd3, - XK_F23: 0xffd4, - XK_R3: 0xffd4, - XK_F24: 0xffd5, - XK_R4: 0xffd5, - XK_F25: 0xffd6, - XK_R5: 0xffd6, - XK_F26: 0xffd7, - XK_R6: 0xffd7, - XK_F27: 0xffd8, - XK_R7: 0xffd8, - XK_F28: 0xffd9, - XK_R8: 0xffd9, - XK_F29: 0xffda, - XK_R9: 0xffda, - XK_F30: 0xffdb, - XK_R10: 0xffdb, - XK_F31: 0xffdc, - XK_R11: 0xffdc, - XK_F32: 0xffdd, - XK_R12: 0xffdd, - XK_F33: 0xffde, - XK_R13: 0xffde, - XK_F34: 0xffdf, - XK_R14: 0xffdf, - XK_F35: 0xffe0, - XK_R15: 0xffe0, + XK_F1: 0xffbe, + XK_F2: 0xffbf, + XK_F3: 0xffc0, + XK_F4: 0xffc1, + XK_F5: 0xffc2, + XK_F6: 0xffc3, + XK_F7: 0xffc4, + XK_F8: 0xffc5, + XK_F9: 0xffc6, + XK_F10: 0xffc7, + XK_F11: 0xffc8, + XK_L1: 0xffc8, + XK_F12: 0xffc9, + XK_L2: 0xffc9, + XK_F13: 0xffca, + XK_L3: 0xffca, + XK_F14: 0xffcb, + XK_L4: 0xffcb, + XK_F15: 0xffcc, + XK_L5: 0xffcc, + XK_F16: 0xffcd, + XK_L6: 0xffcd, + XK_F17: 0xffce, + XK_L7: 0xffce, + XK_F18: 0xffcf, + XK_L8: 0xffcf, + XK_F19: 0xffd0, + XK_L9: 0xffd0, + XK_F20: 0xffd1, + XK_L10: 0xffd1, + XK_F21: 0xffd2, + XK_R1: 0xffd2, + XK_F22: 0xffd3, + XK_R2: 0xffd3, + XK_F23: 0xffd4, + XK_R3: 0xffd4, + XK_F24: 0xffd5, + XK_R4: 0xffd5, + XK_F25: 0xffd6, + XK_R5: 0xffd6, + XK_F26: 0xffd7, + XK_R6: 0xffd7, + XK_F27: 0xffd8, + XK_R7: 0xffd8, + XK_F28: 0xffd9, + XK_R8: 0xffd9, + XK_F29: 0xffda, + XK_R9: 0xffda, + XK_F30: 0xffdb, + XK_R10: 0xffdb, + XK_F31: 0xffdc, + XK_R11: 0xffdc, + XK_F32: 0xffdd, + XK_R12: 0xffdd, + XK_F33: 0xffde, + XK_R13: 0xffde, + XK_F34: 0xffdf, + XK_R14: 0xffdf, + XK_F35: 0xffe0, + XK_R15: 0xffe0, - /* Modifiers */ + /* Modifiers */ - XK_Shift_L: 0xffe1, /* Left shift */ - XK_Shift_R: 0xffe2, /* Right shift */ - XK_Control_L: 0xffe3, /* Left control */ - XK_Control_R: 0xffe4, /* Right control */ - XK_Caps_Lock: 0xffe5, /* Caps lock */ - XK_Shift_Lock: 0xffe6, /* Shift lock */ + XK_Shift_L: 0xffe1, /* Left shift */ + XK_Shift_R: 0xffe2, /* Right shift */ + XK_Control_L: 0xffe3, /* Left control */ + XK_Control_R: 0xffe4, /* Right control */ + XK_Caps_Lock: 0xffe5, /* Caps lock */ + XK_Shift_Lock: 0xffe6, /* Shift lock */ - XK_Meta_L: 0xffe7, /* Left meta */ - XK_Meta_R: 0xffe8, /* Right meta */ - XK_Alt_L: 0xffe9, /* Left alt */ - XK_Alt_R: 0xffea, /* Right alt */ - XK_Super_L: 0xffeb, /* Left super */ - XK_Super_R: 0xffec, /* Right super */ - XK_Hyper_L: 0xffed, /* Left hyper */ - XK_Hyper_R: 0xffee, /* Right hyper */ + XK_Meta_L: 0xffe7, /* Left meta */ + XK_Meta_R: 0xffe8, /* Right meta */ + XK_Alt_L: 0xffe9, /* Left alt */ + XK_Alt_R: 0xffea, /* Right alt */ + XK_Super_L: 0xffeb, /* Left super */ + XK_Super_R: 0xffec, /* Right super */ + XK_Hyper_L: 0xffed, /* Left hyper */ + XK_Hyper_R: 0xffee, /* Right hyper */ - XK_ISO_Level3_Shift: 0xfe03, /* AltGr */ + XK_ISO_Level3_Shift: 0xfe03, /* AltGr */ - /* - * Latin 1 - * (ISO/IEC 8859-1: Unicode U+0020..U+00FF) - * Byte 3: 0 - */ + /* + * Latin 1 + * (ISO/IEC 8859-1: Unicode U+0020..U+00FF) + * Byte 3: 0 + */ - XK_space: 0x0020, /* U+0020 SPACE */ - XK_exclam: 0x0021, /* U+0021 EXCLAMATION MARK */ - XK_quotedbl: 0x0022, /* U+0022 QUOTATION MARK */ - XK_numbersign: 0x0023, /* U+0023 NUMBER SIGN */ - XK_dollar: 0x0024, /* U+0024 DOLLAR SIGN */ - XK_percent: 0x0025, /* U+0025 PERCENT SIGN */ - XK_ampersand: 0x0026, /* U+0026 AMPERSAND */ - XK_apostrophe: 0x0027, /* U+0027 APOSTROPHE */ - XK_quoteright: 0x0027, /* deprecated */ - XK_parenleft: 0x0028, /* U+0028 LEFT PARENTHESIS */ - XK_parenright: 0x0029, /* U+0029 RIGHT PARENTHESIS */ - XK_asterisk: 0x002a, /* U+002A ASTERISK */ - XK_plus: 0x002b, /* U+002B PLUS SIGN */ - XK_comma: 0x002c, /* U+002C COMMA */ - XK_minus: 0x002d, /* U+002D HYPHEN-MINUS */ - XK_period: 0x002e, /* U+002E FULL STOP */ - XK_slash: 0x002f, /* U+002F SOLIDUS */ - XK_0: 0x0030, /* U+0030 DIGIT ZERO */ - XK_1: 0x0031, /* U+0031 DIGIT ONE */ - XK_2: 0x0032, /* U+0032 DIGIT TWO */ - XK_3: 0x0033, /* U+0033 DIGIT THREE */ - XK_4: 0x0034, /* U+0034 DIGIT FOUR */ - XK_5: 0x0035, /* U+0035 DIGIT FIVE */ - XK_6: 0x0036, /* U+0036 DIGIT SIX */ - XK_7: 0x0037, /* U+0037 DIGIT SEVEN */ - XK_8: 0x0038, /* U+0038 DIGIT EIGHT */ - XK_9: 0x0039, /* U+0039 DIGIT NINE */ - XK_colon: 0x003a, /* U+003A COLON */ - XK_semicolon: 0x003b, /* U+003B SEMICOLON */ - XK_less: 0x003c, /* U+003C LESS-THAN SIGN */ - XK_equal: 0x003d, /* U+003D EQUALS SIGN */ - XK_greater: 0x003e, /* U+003E GREATER-THAN SIGN */ - XK_question: 0x003f, /* U+003F QUESTION MARK */ - XK_at: 0x0040, /* U+0040 COMMERCIAL AT */ - XK_A: 0x0041, /* U+0041 LATIN CAPITAL LETTER A */ - XK_B: 0x0042, /* U+0042 LATIN CAPITAL LETTER B */ - XK_C: 0x0043, /* U+0043 LATIN CAPITAL LETTER C */ - XK_D: 0x0044, /* U+0044 LATIN CAPITAL LETTER D */ - XK_E: 0x0045, /* U+0045 LATIN CAPITAL LETTER E */ - XK_F: 0x0046, /* U+0046 LATIN CAPITAL LETTER F */ - XK_G: 0x0047, /* U+0047 LATIN CAPITAL LETTER G */ - XK_H: 0x0048, /* U+0048 LATIN CAPITAL LETTER H */ - XK_I: 0x0049, /* U+0049 LATIN CAPITAL LETTER I */ - XK_J: 0x004a, /* U+004A LATIN CAPITAL LETTER J */ - XK_K: 0x004b, /* U+004B LATIN CAPITAL LETTER K */ - XK_L: 0x004c, /* U+004C LATIN CAPITAL LETTER L */ - XK_M: 0x004d, /* U+004D LATIN CAPITAL LETTER M */ - XK_N: 0x004e, /* U+004E LATIN CAPITAL LETTER N */ - XK_O: 0x004f, /* U+004F LATIN CAPITAL LETTER O */ - XK_P: 0x0050, /* U+0050 LATIN CAPITAL LETTER P */ - XK_Q: 0x0051, /* U+0051 LATIN CAPITAL LETTER Q */ - XK_R: 0x0052, /* U+0052 LATIN CAPITAL LETTER R */ - XK_S: 0x0053, /* U+0053 LATIN CAPITAL LETTER S */ - XK_T: 0x0054, /* U+0054 LATIN CAPITAL LETTER T */ - XK_U: 0x0055, /* U+0055 LATIN CAPITAL LETTER U */ - XK_V: 0x0056, /* U+0056 LATIN CAPITAL LETTER V */ - XK_W: 0x0057, /* U+0057 LATIN CAPITAL LETTER W */ - XK_X: 0x0058, /* U+0058 LATIN CAPITAL LETTER X */ - XK_Y: 0x0059, /* U+0059 LATIN CAPITAL LETTER Y */ - XK_Z: 0x005a, /* U+005A LATIN CAPITAL LETTER Z */ - XK_bracketleft: 0x005b, /* U+005B LEFT SQUARE BRACKET */ - XK_backslash: 0x005c, /* U+005C REVERSE SOLIDUS */ - XK_bracketright: 0x005d, /* U+005D RIGHT SQUARE BRACKET */ - XK_asciicircum: 0x005e, /* U+005E CIRCUMFLEX ACCENT */ - XK_underscore: 0x005f, /* U+005F LOW LINE */ - XK_grave: 0x0060, /* U+0060 GRAVE ACCENT */ - XK_quoteleft: 0x0060, /* deprecated */ - XK_a: 0x0061, /* U+0061 LATIN SMALL LETTER A */ - XK_b: 0x0062, /* U+0062 LATIN SMALL LETTER B */ - XK_c: 0x0063, /* U+0063 LATIN SMALL LETTER C */ - XK_d: 0x0064, /* U+0064 LATIN SMALL LETTER D */ - XK_e: 0x0065, /* U+0065 LATIN SMALL LETTER E */ - XK_f: 0x0066, /* U+0066 LATIN SMALL LETTER F */ - XK_g: 0x0067, /* U+0067 LATIN SMALL LETTER G */ - XK_h: 0x0068, /* U+0068 LATIN SMALL LETTER H */ - XK_i: 0x0069, /* U+0069 LATIN SMALL LETTER I */ - XK_j: 0x006a, /* U+006A LATIN SMALL LETTER J */ - XK_k: 0x006b, /* U+006B LATIN SMALL LETTER K */ - XK_l: 0x006c, /* U+006C LATIN SMALL LETTER L */ - XK_m: 0x006d, /* U+006D LATIN SMALL LETTER M */ - XK_n: 0x006e, /* U+006E LATIN SMALL LETTER N */ - XK_o: 0x006f, /* U+006F LATIN SMALL LETTER O */ - XK_p: 0x0070, /* U+0070 LATIN SMALL LETTER P */ - XK_q: 0x0071, /* U+0071 LATIN SMALL LETTER Q */ - XK_r: 0x0072, /* U+0072 LATIN SMALL LETTER R */ - XK_s: 0x0073, /* U+0073 LATIN SMALL LETTER S */ - XK_t: 0x0074, /* U+0074 LATIN SMALL LETTER T */ - XK_u: 0x0075, /* U+0075 LATIN SMALL LETTER U */ - XK_v: 0x0076, /* U+0076 LATIN SMALL LETTER V */ - XK_w: 0x0077, /* U+0077 LATIN SMALL LETTER W */ - XK_x: 0x0078, /* U+0078 LATIN SMALL LETTER X */ - XK_y: 0x0079, /* U+0079 LATIN SMALL LETTER Y */ - XK_z: 0x007a, /* U+007A LATIN SMALL LETTER Z */ - XK_braceleft: 0x007b, /* U+007B LEFT CURLY BRACKET */ - XK_bar: 0x007c, /* U+007C VERTICAL LINE */ - XK_braceright: 0x007d, /* U+007D RIGHT CURLY BRACKET */ - XK_asciitilde: 0x007e, /* U+007E TILDE */ + XK_space: 0x0020, /* U+0020 SPACE */ + XK_exclam: 0x0021, /* U+0021 EXCLAMATION MARK */ + XK_quotedbl: 0x0022, /* U+0022 QUOTATION MARK */ + XK_numbersign: 0x0023, /* U+0023 NUMBER SIGN */ + XK_dollar: 0x0024, /* U+0024 DOLLAR SIGN */ + XK_percent: 0x0025, /* U+0025 PERCENT SIGN */ + XK_ampersand: 0x0026, /* U+0026 AMPERSAND */ + XK_apostrophe: 0x0027, /* U+0027 APOSTROPHE */ + XK_quoteright: 0x0027, /* deprecated */ + XK_parenleft: 0x0028, /* U+0028 LEFT PARENTHESIS */ + XK_parenright: 0x0029, /* U+0029 RIGHT PARENTHESIS */ + XK_asterisk: 0x002a, /* U+002A ASTERISK */ + XK_plus: 0x002b, /* U+002B PLUS SIGN */ + XK_comma: 0x002c, /* U+002C COMMA */ + XK_minus: 0x002d, /* U+002D HYPHEN-MINUS */ + XK_period: 0x002e, /* U+002E FULL STOP */ + XK_slash: 0x002f, /* U+002F SOLIDUS */ + XK_0: 0x0030, /* U+0030 DIGIT ZERO */ + XK_1: 0x0031, /* U+0031 DIGIT ONE */ + XK_2: 0x0032, /* U+0032 DIGIT TWO */ + XK_3: 0x0033, /* U+0033 DIGIT THREE */ + XK_4: 0x0034, /* U+0034 DIGIT FOUR */ + XK_5: 0x0035, /* U+0035 DIGIT FIVE */ + XK_6: 0x0036, /* U+0036 DIGIT SIX */ + XK_7: 0x0037, /* U+0037 DIGIT SEVEN */ + XK_8: 0x0038, /* U+0038 DIGIT EIGHT */ + XK_9: 0x0039, /* U+0039 DIGIT NINE */ + XK_colon: 0x003a, /* U+003A COLON */ + XK_semicolon: 0x003b, /* U+003B SEMICOLON */ + XK_less: 0x003c, /* U+003C LESS-THAN SIGN */ + XK_equal: 0x003d, /* U+003D EQUALS SIGN */ + XK_greater: 0x003e, /* U+003E GREATER-THAN SIGN */ + XK_question: 0x003f, /* U+003F QUESTION MARK */ + XK_at: 0x0040, /* U+0040 COMMERCIAL AT */ + XK_A: 0x0041, /* U+0041 LATIN CAPITAL LETTER A */ + XK_B: 0x0042, /* U+0042 LATIN CAPITAL LETTER B */ + XK_C: 0x0043, /* U+0043 LATIN CAPITAL LETTER C */ + XK_D: 0x0044, /* U+0044 LATIN CAPITAL LETTER D */ + XK_E: 0x0045, /* U+0045 LATIN CAPITAL LETTER E */ + XK_F: 0x0046, /* U+0046 LATIN CAPITAL LETTER F */ + XK_G: 0x0047, /* U+0047 LATIN CAPITAL LETTER G */ + XK_H: 0x0048, /* U+0048 LATIN CAPITAL LETTER H */ + XK_I: 0x0049, /* U+0049 LATIN CAPITAL LETTER I */ + XK_J: 0x004a, /* U+004A LATIN CAPITAL LETTER J */ + XK_K: 0x004b, /* U+004B LATIN CAPITAL LETTER K */ + XK_L: 0x004c, /* U+004C LATIN CAPITAL LETTER L */ + XK_M: 0x004d, /* U+004D LATIN CAPITAL LETTER M */ + XK_N: 0x004e, /* U+004E LATIN CAPITAL LETTER N */ + XK_O: 0x004f, /* U+004F LATIN CAPITAL LETTER O */ + XK_P: 0x0050, /* U+0050 LATIN CAPITAL LETTER P */ + XK_Q: 0x0051, /* U+0051 LATIN CAPITAL LETTER Q */ + XK_R: 0x0052, /* U+0052 LATIN CAPITAL LETTER R */ + XK_S: 0x0053, /* U+0053 LATIN CAPITAL LETTER S */ + XK_T: 0x0054, /* U+0054 LATIN CAPITAL LETTER T */ + XK_U: 0x0055, /* U+0055 LATIN CAPITAL LETTER U */ + XK_V: 0x0056, /* U+0056 LATIN CAPITAL LETTER V */ + XK_W: 0x0057, /* U+0057 LATIN CAPITAL LETTER W */ + XK_X: 0x0058, /* U+0058 LATIN CAPITAL LETTER X */ + XK_Y: 0x0059, /* U+0059 LATIN CAPITAL LETTER Y */ + XK_Z: 0x005a, /* U+005A LATIN CAPITAL LETTER Z */ + XK_bracketleft: 0x005b, /* U+005B LEFT SQUARE BRACKET */ + XK_backslash: 0x005c, /* U+005C REVERSE SOLIDUS */ + XK_bracketright: 0x005d, /* U+005D RIGHT SQUARE BRACKET */ + XK_asciicircum: 0x005e, /* U+005E CIRCUMFLEX ACCENT */ + XK_underscore: 0x005f, /* U+005F LOW LINE */ + XK_grave: 0x0060, /* U+0060 GRAVE ACCENT */ + XK_quoteleft: 0x0060, /* deprecated */ + XK_a: 0x0061, /* U+0061 LATIN SMALL LETTER A */ + XK_b: 0x0062, /* U+0062 LATIN SMALL LETTER B */ + XK_c: 0x0063, /* U+0063 LATIN SMALL LETTER C */ + XK_d: 0x0064, /* U+0064 LATIN SMALL LETTER D */ + XK_e: 0x0065, /* U+0065 LATIN SMALL LETTER E */ + XK_f: 0x0066, /* U+0066 LATIN SMALL LETTER F */ + XK_g: 0x0067, /* U+0067 LATIN SMALL LETTER G */ + XK_h: 0x0068, /* U+0068 LATIN SMALL LETTER H */ + XK_i: 0x0069, /* U+0069 LATIN SMALL LETTER I */ + XK_j: 0x006a, /* U+006A LATIN SMALL LETTER J */ + XK_k: 0x006b, /* U+006B LATIN SMALL LETTER K */ + XK_l: 0x006c, /* U+006C LATIN SMALL LETTER L */ + XK_m: 0x006d, /* U+006D LATIN SMALL LETTER M */ + XK_n: 0x006e, /* U+006E LATIN SMALL LETTER N */ + XK_o: 0x006f, /* U+006F LATIN SMALL LETTER O */ + XK_p: 0x0070, /* U+0070 LATIN SMALL LETTER P */ + XK_q: 0x0071, /* U+0071 LATIN SMALL LETTER Q */ + XK_r: 0x0072, /* U+0072 LATIN SMALL LETTER R */ + XK_s: 0x0073, /* U+0073 LATIN SMALL LETTER S */ + XK_t: 0x0074, /* U+0074 LATIN SMALL LETTER T */ + XK_u: 0x0075, /* U+0075 LATIN SMALL LETTER U */ + XK_v: 0x0076, /* U+0076 LATIN SMALL LETTER V */ + XK_w: 0x0077, /* U+0077 LATIN SMALL LETTER W */ + XK_x: 0x0078, /* U+0078 LATIN SMALL LETTER X */ + XK_y: 0x0079, /* U+0079 LATIN SMALL LETTER Y */ + XK_z: 0x007a, /* U+007A LATIN SMALL LETTER Z */ + XK_braceleft: 0x007b, /* U+007B LEFT CURLY BRACKET */ + XK_bar: 0x007c, /* U+007C VERTICAL LINE */ + XK_braceright: 0x007d, /* U+007D RIGHT CURLY BRACKET */ + XK_asciitilde: 0x007e, /* U+007E TILDE */ - XK_nobreakspace: 0x00a0, /* U+00A0 NO-BREAK SPACE */ - XK_exclamdown: 0x00a1, /* U+00A1 INVERTED EXCLAMATION MARK */ - XK_cent: 0x00a2, /* U+00A2 CENT SIGN */ - XK_sterling: 0x00a3, /* U+00A3 POUND SIGN */ - XK_currency: 0x00a4, /* U+00A4 CURRENCY SIGN */ - XK_yen: 0x00a5, /* U+00A5 YEN SIGN */ - XK_brokenbar: 0x00a6, /* U+00A6 BROKEN BAR */ - XK_section: 0x00a7, /* U+00A7 SECTION SIGN */ - XK_diaeresis: 0x00a8, /* U+00A8 DIAERESIS */ - XK_copyright: 0x00a9, /* U+00A9 COPYRIGHT SIGN */ - XK_ordfeminine: 0x00aa, /* U+00AA FEMININE ORDINAL INDICATOR */ - XK_guillemotleft: 0x00ab, /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */ - XK_notsign: 0x00ac, /* U+00AC NOT SIGN */ - XK_hyphen: 0x00ad, /* U+00AD SOFT HYPHEN */ - XK_registered: 0x00ae, /* U+00AE REGISTERED SIGN */ - XK_macron: 0x00af, /* U+00AF MACRON */ - XK_degree: 0x00b0, /* U+00B0 DEGREE SIGN */ - XK_plusminus: 0x00b1, /* U+00B1 PLUS-MINUS SIGN */ - XK_twosuperior: 0x00b2, /* U+00B2 SUPERSCRIPT TWO */ - XK_threesuperior: 0x00b3, /* U+00B3 SUPERSCRIPT THREE */ - XK_acute: 0x00b4, /* U+00B4 ACUTE ACCENT */ - XK_mu: 0x00b5, /* U+00B5 MICRO SIGN */ - XK_paragraph: 0x00b6, /* U+00B6 PILCROW SIGN */ - XK_periodcentered: 0x00b7, /* U+00B7 MIDDLE DOT */ - XK_cedilla: 0x00b8, /* U+00B8 CEDILLA */ - XK_onesuperior: 0x00b9, /* U+00B9 SUPERSCRIPT ONE */ - XK_masculine: 0x00ba, /* U+00BA MASCULINE ORDINAL INDICATOR */ - XK_guillemotright: 0x00bb, /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */ - XK_onequarter: 0x00bc, /* U+00BC VULGAR FRACTION ONE QUARTER */ - XK_onehalf: 0x00bd, /* U+00BD VULGAR FRACTION ONE HALF */ - XK_threequarters: 0x00be, /* U+00BE VULGAR FRACTION THREE QUARTERS */ - XK_questiondown: 0x00bf, /* U+00BF INVERTED QUESTION MARK */ - XK_Agrave: 0x00c0, /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */ - XK_Aacute: 0x00c1, /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */ - XK_Acircumflex: 0x00c2, /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ - XK_Atilde: 0x00c3, /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */ - XK_Adiaeresis: 0x00c4, /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */ - XK_Aring: 0x00c5, /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */ - XK_AE: 0x00c6, /* U+00C6 LATIN CAPITAL LETTER AE */ - XK_Ccedilla: 0x00c7, /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */ - XK_Egrave: 0x00c8, /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */ - XK_Eacute: 0x00c9, /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */ - XK_Ecircumflex: 0x00ca, /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ - XK_Ediaeresis: 0x00cb, /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */ - XK_Igrave: 0x00cc, /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */ - XK_Iacute: 0x00cd, /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */ - XK_Icircumflex: 0x00ce, /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ - XK_Idiaeresis: 0x00cf, /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */ - XK_ETH: 0x00d0, /* U+00D0 LATIN CAPITAL LETTER ETH */ - XK_Eth: 0x00d0, /* deprecated */ - XK_Ntilde: 0x00d1, /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */ - XK_Ograve: 0x00d2, /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */ - XK_Oacute: 0x00d3, /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */ - XK_Ocircumflex: 0x00d4, /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ - XK_Otilde: 0x00d5, /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */ - XK_Odiaeresis: 0x00d6, /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */ - XK_multiply: 0x00d7, /* U+00D7 MULTIPLICATION SIGN */ - XK_Oslash: 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ - XK_Ooblique: 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ - XK_Ugrave: 0x00d9, /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */ - XK_Uacute: 0x00da, /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */ - XK_Ucircumflex: 0x00db, /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ - XK_Udiaeresis: 0x00dc, /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */ - XK_Yacute: 0x00dd, /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */ - XK_THORN: 0x00de, /* U+00DE LATIN CAPITAL LETTER THORN */ - XK_Thorn: 0x00de, /* deprecated */ - XK_ssharp: 0x00df, /* U+00DF LATIN SMALL LETTER SHARP S */ - XK_agrave: 0x00e0, /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */ - XK_aacute: 0x00e1, /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */ - XK_acircumflex: 0x00e2, /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */ - XK_atilde: 0x00e3, /* U+00E3 LATIN SMALL LETTER A WITH TILDE */ - XK_adiaeresis: 0x00e4, /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */ - XK_aring: 0x00e5, /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */ - XK_ae: 0x00e6, /* U+00E6 LATIN SMALL LETTER AE */ - XK_ccedilla: 0x00e7, /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */ - XK_egrave: 0x00e8, /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */ - XK_eacute: 0x00e9, /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */ - XK_ecircumflex: 0x00ea, /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */ - XK_ediaeresis: 0x00eb, /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */ - XK_igrave: 0x00ec, /* U+00EC LATIN SMALL LETTER I WITH GRAVE */ - XK_iacute: 0x00ed, /* U+00ED LATIN SMALL LETTER I WITH ACUTE */ - XK_icircumflex: 0x00ee, /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */ - XK_idiaeresis: 0x00ef, /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */ - XK_eth: 0x00f0, /* U+00F0 LATIN SMALL LETTER ETH */ - XK_ntilde: 0x00f1, /* U+00F1 LATIN SMALL LETTER N WITH TILDE */ - XK_ograve: 0x00f2, /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */ - XK_oacute: 0x00f3, /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */ - XK_ocircumflex: 0x00f4, /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */ - XK_otilde: 0x00f5, /* U+00F5 LATIN SMALL LETTER O WITH TILDE */ - XK_odiaeresis: 0x00f6, /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */ - XK_division: 0x00f7, /* U+00F7 DIVISION SIGN */ - XK_oslash: 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ - XK_ooblique: 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ - XK_ugrave: 0x00f9, /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */ - XK_uacute: 0x00fa, /* U+00FA LATIN SMALL LETTER U WITH ACUTE */ - XK_ucircumflex: 0x00fb, /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */ - XK_udiaeresis: 0x00fc, /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */ - XK_yacute: 0x00fd, /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */ - XK_thorn: 0x00fe, /* U+00FE LATIN SMALL LETTER THORN */ - XK_ydiaeresis: 0x00ff, /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */ -}; + XK_nobreakspace: 0x00a0, /* U+00A0 NO-BREAK SPACE */ + XK_exclamdown: 0x00a1, /* U+00A1 INVERTED EXCLAMATION MARK */ + XK_cent: 0x00a2, /* U+00A2 CENT SIGN */ + XK_sterling: 0x00a3, /* U+00A3 POUND SIGN */ + XK_currency: 0x00a4, /* U+00A4 CURRENCY SIGN */ + XK_yen: 0x00a5, /* U+00A5 YEN SIGN */ + XK_brokenbar: 0x00a6, /* U+00A6 BROKEN BAR */ + XK_section: 0x00a7, /* U+00A7 SECTION SIGN */ + XK_diaeresis: 0x00a8, /* U+00A8 DIAERESIS */ + XK_copyright: 0x00a9, /* U+00A9 COPYRIGHT SIGN */ + XK_ordfeminine: 0x00aa, /* U+00AA FEMININE ORDINAL INDICATOR */ + XK_guillemotleft: 0x00ab, /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */ + XK_notsign: 0x00ac, /* U+00AC NOT SIGN */ + XK_hyphen: 0x00ad, /* U+00AD SOFT HYPHEN */ + XK_registered: 0x00ae, /* U+00AE REGISTERED SIGN */ + XK_macron: 0x00af, /* U+00AF MACRON */ + XK_degree: 0x00b0, /* U+00B0 DEGREE SIGN */ + XK_plusminus: 0x00b1, /* U+00B1 PLUS-MINUS SIGN */ + XK_twosuperior: 0x00b2, /* U+00B2 SUPERSCRIPT TWO */ + XK_threesuperior: 0x00b3, /* U+00B3 SUPERSCRIPT THREE */ + XK_acute: 0x00b4, /* U+00B4 ACUTE ACCENT */ + XK_mu: 0x00b5, /* U+00B5 MICRO SIGN */ + XK_paragraph: 0x00b6, /* U+00B6 PILCROW SIGN */ + XK_periodcentered: 0x00b7, /* U+00B7 MIDDLE DOT */ + XK_cedilla: 0x00b8, /* U+00B8 CEDILLA */ + XK_onesuperior: 0x00b9, /* U+00B9 SUPERSCRIPT ONE */ + XK_masculine: 0x00ba, /* U+00BA MASCULINE ORDINAL INDICATOR */ + XK_guillemotright: 0x00bb, /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */ + XK_onequarter: 0x00bc, /* U+00BC VULGAR FRACTION ONE QUARTER */ + XK_onehalf: 0x00bd, /* U+00BD VULGAR FRACTION ONE HALF */ + XK_threequarters: 0x00be, /* U+00BE VULGAR FRACTION THREE QUARTERS */ + XK_questiondown: 0x00bf, /* U+00BF INVERTED QUESTION MARK */ + XK_Agrave: 0x00c0, /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */ + XK_Aacute: 0x00c1, /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */ + XK_Acircumflex: 0x00c2, /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ + XK_Atilde: 0x00c3, /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */ + XK_Adiaeresis: 0x00c4, /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */ + XK_Aring: 0x00c5, /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */ + XK_AE: 0x00c6, /* U+00C6 LATIN CAPITAL LETTER AE */ + XK_Ccedilla: 0x00c7, /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */ + XK_Egrave: 0x00c8, /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */ + XK_Eacute: 0x00c9, /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */ + XK_Ecircumflex: 0x00ca, /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ + XK_Ediaeresis: 0x00cb, /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */ + XK_Igrave: 0x00cc, /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */ + XK_Iacute: 0x00cd, /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */ + XK_Icircumflex: 0x00ce, /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ + XK_Idiaeresis: 0x00cf, /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */ + XK_ETH: 0x00d0, /* U+00D0 LATIN CAPITAL LETTER ETH */ + XK_Eth: 0x00d0, /* deprecated */ + XK_Ntilde: 0x00d1, /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */ + XK_Ograve: 0x00d2, /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */ + XK_Oacute: 0x00d3, /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */ + XK_Ocircumflex: 0x00d4, /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ + XK_Otilde: 0x00d5, /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */ + XK_Odiaeresis: 0x00d6, /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */ + XK_multiply: 0x00d7, /* U+00D7 MULTIPLICATION SIGN */ + XK_Oslash: 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ + XK_Ooblique: 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ + XK_Ugrave: 0x00d9, /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */ + XK_Uacute: 0x00da, /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */ + XK_Ucircumflex: 0x00db, /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ + XK_Udiaeresis: 0x00dc, /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */ + XK_Yacute: 0x00dd, /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */ + XK_THORN: 0x00de, /* U+00DE LATIN CAPITAL LETTER THORN */ + XK_Thorn: 0x00de, /* deprecated */ + XK_ssharp: 0x00df, /* U+00DF LATIN SMALL LETTER SHARP S */ + XK_agrave: 0x00e0, /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */ + XK_aacute: 0x00e1, /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */ + XK_acircumflex: 0x00e2, /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */ + XK_atilde: 0x00e3, /* U+00E3 LATIN SMALL LETTER A WITH TILDE */ + XK_adiaeresis: 0x00e4, /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */ + XK_aring: 0x00e5, /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */ + XK_ae: 0x00e6, /* U+00E6 LATIN SMALL LETTER AE */ + XK_ccedilla: 0x00e7, /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */ + XK_egrave: 0x00e8, /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */ + XK_eacute: 0x00e9, /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */ + XK_ecircumflex: 0x00ea, /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */ + XK_ediaeresis: 0x00eb, /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */ + XK_igrave: 0x00ec, /* U+00EC LATIN SMALL LETTER I WITH GRAVE */ + XK_iacute: 0x00ed, /* U+00ED LATIN SMALL LETTER I WITH ACUTE */ + XK_icircumflex: 0x00ee, /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */ + XK_idiaeresis: 0x00ef, /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */ + XK_eth: 0x00f0, /* U+00F0 LATIN SMALL LETTER ETH */ + XK_ntilde: 0x00f1, /* U+00F1 LATIN SMALL LETTER N WITH TILDE */ + XK_ograve: 0x00f2, /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */ + XK_oacute: 0x00f3, /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */ + XK_ocircumflex: 0x00f4, /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */ + XK_otilde: 0x00f5, /* U+00F5 LATIN SMALL LETTER O WITH TILDE */ + XK_odiaeresis: 0x00f6, /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */ + XK_division: 0x00f7, /* U+00F7 DIVISION SIGN */ + XK_oslash: 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ + XK_ooblique: 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ + XK_ugrave: 0x00f9, /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */ + XK_uacute: 0x00fa, /* U+00FA LATIN SMALL LETTER U WITH ACUTE */ + XK_ucircumflex: 0x00fb, /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */ + XK_udiaeresis: 0x00fc, /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */ + XK_yacute: 0x00fd, /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */ + XK_thorn: 0x00fe, /* U+00FE LATIN SMALL LETTER THORN */ + XK_ydiaeresis: 0x00ff, /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */ + }; -/* [module] export default KeyTable; */ + return KeyTable; +}); diff --git a/core/input/keysymdef.js b/core/input/keysymdef.js index ba47e69b..31d72f68 100644 --- a/core/input/keysymdef.js +++ b/core/input/keysymdef.js @@ -5,11 +5,12 @@ "use strict"; -var keysyms = (function(){ +define(function () { var keynames = null; var codepoints = {"32":32,"33":33,"34":34,"35":35,"36":36,"37":37,"38":38,"39":39,"40":40,"41":41,"42":42,"43":43,"44":44,"45":45,"46":46,"47":47,"48":48,"49":49,"50":50,"51":51,"52":52,"53":53,"54":54,"55":55,"56":56,"57":57,"58":58,"59":59,"60":60,"61":61,"62":62,"63":63,"64":64,"65":65,"66":66,"67":67,"68":68,"69":69,"70":70,"71":71,"72":72,"73":73,"74":74,"75":75,"76":76,"77":77,"78":78,"79":79,"80":80,"81":81,"82":82,"83":83,"84":84,"85":85,"86":86,"87":87,"88":88,"89":89,"90":90,"91":91,"92":92,"93":93,"94":94,"95":95,"96":96,"97":97,"98":98,"99":99,"100":100,"101":101,"102":102,"103":103,"104":104,"105":105,"106":106,"107":107,"108":108,"109":109,"110":110,"111":111,"112":112,"113":113,"114":114,"115":115,"116":116,"117":117,"118":118,"119":119,"120":120,"121":121,"122":122,"123":123,"124":124,"125":125,"126":126,"160":160,"161":161,"162":162,"163":163,"164":164,"165":165,"166":166,"167":167,"168":168,"169":169,"170":170,"171":171,"172":172,"173":173,"174":174,"175":175,"176":176,"177":177,"178":178,"179":179,"180":180,"181":181,"182":182,"183":183,"184":184,"185":185,"186":186,"187":187,"188":188,"189":189,"190":190,"191":191,"192":192,"193":193,"194":194,"195":195,"196":196,"197":197,"198":198,"199":199,"200":200,"201":201,"202":202,"203":203,"204":204,"205":205,"206":206,"207":207,"208":208,"209":209,"210":210,"211":211,"212":212,"213":213,"214":214,"215":215,"216":216,"217":217,"218":218,"219":219,"220":220,"221":221,"222":222,"223":223,"224":224,"225":225,"226":226,"227":227,"228":228,"229":229,"230":230,"231":231,"232":232,"233":233,"234":234,"235":235,"236":236,"237":237,"238":238,"239":239,"240":240,"241":241,"242":242,"243":243,"244":244,"245":245,"246":246,"247":247,"248":248,"249":249,"250":250,"251":251,"252":252,"253":253,"254":254,"255":255,"256":960,"257":992,"258":451,"259":483,"260":417,"261":433,"262":454,"263":486,"264":710,"265":742,"266":709,"267":741,"268":456,"269":488,"270":463,"271":495,"272":464,"273":496,"274":938,"275":954,"278":972,"279":1004,"280":458,"281":490,"282":460,"283":492,"284":728,"285":760,"286":683,"287":699,"288":725,"289":757,"290":939,"291":955,"292":678,"293":694,"294":673,"295":689,"296":933,"297":949,"298":975,"299":1007,"300":16777516,"301":16777517,"302":967,"303":999,"304":681,"305":697,"308":684,"309":700,"310":979,"311":1011,"312":930,"313":453,"314":485,"315":934,"316":950,"317":421,"318":437,"321":419,"322":435,"323":465,"324":497,"325":977,"326":1009,"327":466,"328":498,"330":957,"331":959,"332":978,"333":1010,"336":469,"337":501,"338":5052,"339":5053,"340":448,"341":480,"342":931,"343":947,"344":472,"345":504,"346":422,"347":438,"348":734,"349":766,"350":426,"351":442,"352":425,"353":441,"354":478,"355":510,"356":427,"357":443,"358":940,"359":956,"360":989,"361":1021,"362":990,"363":1022,"364":733,"365":765,"366":473,"367":505,"368":475,"369":507,"370":985,"371":1017,"372":16777588,"373":16777589,"374":16777590,"375":16777591,"376":5054,"377":428,"378":444,"379":431,"380":447,"381":430,"382":446,"399":16777615,"402":2294,"415":16777631,"416":16777632,"417":16777633,"431":16777647,"432":16777648,"437":16777653,"438":16777654,"439":16777655,"466":16777681,"486":16777702,"487":16777703,"601":16777817,"629":16777845,"658":16777874,"711":439,"728":418,"729":511,"731":434,"733":445,"901":1966,"902":1953,"904":1954,"905":1955,"906":1956,"908":1959,"910":1960,"911":1963,"912":1974,"913":1985,"914":1986,"915":1987,"916":1988,"917":1989,"918":1990,"919":1991,"920":1992,"921":1993,"922":1994,"923":1995,"924":1996,"925":1997,"926":1998,"927":1999,"928":2000,"929":2001,"931":2002,"932":2004,"933":2005,"934":2006,"935":2007,"936":2008,"937":2009,"938":1957,"939":1961,"940":1969,"941":1970,"942":1971,"943":1972,"944":1978,"945":2017,"946":2018,"947":2019,"948":2020,"949":2021,"950":2022,"951":2023,"952":2024,"953":2025,"954":2026,"955":2027,"956":2028,"957":2029,"958":2030,"959":2031,"960":2032,"961":2033,"962":2035,"963":2034,"964":2036,"965":2037,"966":2038,"967":2039,"968":2040,"969":2041,"970":1973,"971":1977,"972":1975,"973":1976,"974":1979,"1025":1715,"1026":1713,"1027":1714,"1028":1716,"1029":1717,"1030":1718,"1031":1719,"1032":1720,"1033":1721,"1034":1722,"1035":1723,"1036":1724,"1038":1726,"1039":1727,"1040":1761,"1041":1762,"1042":1783,"1043":1767,"1044":1764,"1045":1765,"1046":1782,"1047":1786,"1048":1769,"1049":1770,"1050":1771,"1051":1772,"1052":1773,"1053":1774,"1054":1775,"1055":1776,"1056":1778,"1057":1779,"1058":1780,"1059":1781,"1060":1766,"1061":1768,"1062":1763,"1063":1790,"1064":1787,"1065":1789,"1066":1791,"1067":1785,"1068":1784,"1069":1788,"1070":1760,"1071":1777,"1072":1729,"1073":1730,"1074":1751,"1075":1735,"1076":1732,"1077":1733,"1078":1750,"1079":1754,"1080":1737,"1081":1738,"1082":1739,"1083":1740,"1084":1741,"1085":1742,"1086":1743,"1087":1744,"1088":1746,"1089":1747,"1090":1748,"1091":1749,"1092":1734,"1093":1736,"1094":1731,"1095":1758,"1096":1755,"1097":1757,"1098":1759,"1099":1753,"1100":1752,"1101":1756,"1102":1728,"1103":1745,"1105":1699,"1106":1697,"1107":1698,"1108":1700,"1109":1701,"1110":1702,"1111":1703,"1112":1704,"1113":1705,"1114":1706,"1115":1707,"1116":1708,"1118":1710,"1119":1711,"1168":1725,"1169":1709,"1170":16778386,"1171":16778387,"1174":16778390,"1175":16778391,"1178":16778394,"1179":16778395,"1180":16778396,"1181":16778397,"1186":16778402,"1187":16778403,"1198":16778414,"1199":16778415,"1200":16778416,"1201":16778417,"1202":16778418,"1203":16778419,"1206":16778422,"1207":16778423,"1208":16778424,"1209":16778425,"1210":16778426,"1211":16778427,"1240":16778456,"1241":16778457,"1250":16778466,"1251":16778467,"1256":16778472,"1257":16778473,"1262":16778478,"1263":16778479,"1329":16778545,"1330":16778546,"1331":16778547,"1332":16778548,"1333":16778549,"1334":16778550,"1335":16778551,"1336":16778552,"1337":16778553,"1338":16778554,"1339":16778555,"1340":16778556,"1341":16778557,"1342":16778558,"1343":16778559,"1344":16778560,"1345":16778561,"1346":16778562,"1347":16778563,"1348":16778564,"1349":16778565,"1350":16778566,"1351":16778567,"1352":16778568,"1353":16778569,"1354":16778570,"1355":16778571,"1356":16778572,"1357":16778573,"1358":16778574,"1359":16778575,"1360":16778576,"1361":16778577,"1362":16778578,"1363":16778579,"1364":16778580,"1365":16778581,"1366":16778582,"1370":16778586,"1371":16778587,"1372":16778588,"1373":16778589,"1374":16778590,"1377":16778593,"1378":16778594,"1379":16778595,"1380":16778596,"1381":16778597,"1382":16778598,"1383":16778599,"1384":16778600,"1385":16778601,"1386":16778602,"1387":16778603,"1388":16778604,"1389":16778605,"1390":16778606,"1391":16778607,"1392":16778608,"1393":16778609,"1394":16778610,"1395":16778611,"1396":16778612,"1397":16778613,"1398":16778614,"1399":16778615,"1400":16778616,"1401":16778617,"1402":16778618,"1403":16778619,"1404":16778620,"1405":16778621,"1406":16778622,"1407":16778623,"1408":16778624,"1409":16778625,"1410":16778626,"1411":16778627,"1412":16778628,"1413":16778629,"1414":16778630,"1415":16778631,"1417":16778633,"1418":16778634,"1488":3296,"1489":3297,"1490":3298,"1491":3299,"1492":3300,"1493":3301,"1494":3302,"1495":3303,"1496":3304,"1497":3305,"1498":3306,"1499":3307,"1500":3308,"1501":3309,"1502":3310,"1503":3311,"1504":3312,"1505":3313,"1506":3314,"1507":3315,"1508":3316,"1509":3317,"1510":3318,"1511":3319,"1512":3320,"1513":3321,"1514":3322,"1548":1452,"1563":1467,"1567":1471,"1569":1473,"1570":1474,"1571":1475,"1572":1476,"1573":1477,"1574":1478,"1575":1479,"1576":1480,"1577":1481,"1578":1482,"1579":1483,"1580":1484,"1581":1485,"1582":1486,"1583":1487,"1584":1488,"1585":1489,"1586":1490,"1587":1491,"1588":1492,"1589":1493,"1590":1494,"1591":1495,"1592":1496,"1593":1497,"1594":1498,"1600":1504,"1601":1505,"1602":1506,"1603":1507,"1604":1508,"1605":1509,"1606":1510,"1607":1511,"1608":1512,"1609":1513,"1610":1514,"1611":1515,"1612":1516,"1613":1517,"1614":1518,"1615":1519,"1616":1520,"1617":1521,"1618":1522,"1619":16778835,"1620":16778836,"1621":16778837,"1632":16778848,"1633":16778849,"1634":16778850,"1635":16778851,"1636":16778852,"1637":16778853,"1638":16778854,"1639":16778855,"1640":16778856,"1641":16778857,"1642":16778858,"1648":16778864,"1657":16778873,"1662":16778878,"1670":16778886,"1672":16778888,"1681":16778897,"1688":16778904,"1700":16778916,"1705":16778921,"1711":16778927,"1722":16778938,"1726":16778942,"1729":16778945,"1740":16778956,"1746":16778962,"1748":16778964,"1776":16778992,"1777":16778993,"1778":16778994,"1779":16778995,"1780":16778996,"1781":16778997,"1782":16778998,"1783":16778999,"1784":16779000,"1785":16779001,"3458":16780674,"3459":16780675,"3461":16780677,"3462":16780678,"3463":16780679,"3464":16780680,"3465":16780681,"3466":16780682,"3467":16780683,"3468":16780684,"3469":16780685,"3470":16780686,"3471":16780687,"3472":16780688,"3473":16780689,"3474":16780690,"3475":16780691,"3476":16780692,"3477":16780693,"3478":16780694,"3482":16780698,"3483":16780699,"3484":16780700,"3485":16780701,"3486":16780702,"3487":16780703,"3488":16780704,"3489":16780705,"3490":16780706,"3491":16780707,"3492":16780708,"3493":16780709,"3494":16780710,"3495":16780711,"3496":16780712,"3497":16780713,"3498":16780714,"3499":16780715,"3500":16780716,"3501":16780717,"3502":16780718,"3503":16780719,"3504":16780720,"3505":16780721,"3507":16780723,"3508":16780724,"3509":16780725,"3510":16780726,"3511":16780727,"3512":16780728,"3513":16780729,"3514":16780730,"3515":16780731,"3517":16780733,"3520":16780736,"3521":16780737,"3522":16780738,"3523":16780739,"3524":16780740,"3525":16780741,"3526":16780742,"3530":16780746,"3535":16780751,"3536":16780752,"3537":16780753,"3538":16780754,"3539":16780755,"3540":16780756,"3542":16780758,"3544":16780760,"3545":16780761,"3546":16780762,"3547":16780763,"3548":16780764,"3549":16780765,"3550":16780766,"3551":16780767,"3570":16780786,"3571":16780787,"3572":16780788,"3585":3489,"3586":3490,"3587":3491,"3588":3492,"3589":3493,"3590":3494,"3591":3495,"3592":3496,"3593":3497,"3594":3498,"3595":3499,"3596":3500,"3597":3501,"3598":3502,"3599":3503,"3600":3504,"3601":3505,"3602":3506,"3603":3507,"3604":3508,"3605":3509,"3606":3510,"3607":3511,"3608":3512,"3609":3513,"3610":3514,"3611":3515,"3612":3516,"3613":3517,"3614":3518,"3615":3519,"3616":3520,"3617":3521,"3618":3522,"3619":3523,"3620":3524,"3621":3525,"3622":3526,"3623":3527,"3624":3528,"3625":3529,"3626":3530,"3627":3531,"3628":3532,"3629":3533,"3630":3534,"3631":3535,"3632":3536,"3633":3537,"3634":3538,"3635":3539,"3636":3540,"3637":3541,"3638":3542,"3639":3543,"3640":3544,"3641":3545,"3642":3546,"3647":3551,"3648":3552,"3649":3553,"3650":3554,"3651":3555,"3652":3556,"3653":3557,"3654":3558,"3655":3559,"3656":3560,"3657":3561,"3658":3562,"3659":3563,"3660":3564,"3661":3565,"3664":3568,"3665":3569,"3666":3570,"3667":3571,"3668":3572,"3669":3573,"3670":3574,"3671":3575,"3672":3576,"3673":3577,"4304":16781520,"4305":16781521,"4306":16781522,"4307":16781523,"4308":16781524,"4309":16781525,"4310":16781526,"4311":16781527,"4312":16781528,"4313":16781529,"4314":16781530,"4315":16781531,"4316":16781532,"4317":16781533,"4318":16781534,"4319":16781535,"4320":16781536,"4321":16781537,"4322":16781538,"4323":16781539,"4324":16781540,"4325":16781541,"4326":16781542,"4327":16781543,"4328":16781544,"4329":16781545,"4330":16781546,"4331":16781547,"4332":16781548,"4333":16781549,"4334":16781550,"4335":16781551,"4336":16781552,"4337":16781553,"4338":16781554,"4339":16781555,"4340":16781556,"4341":16781557,"4342":16781558,"7682":16784898,"7683":16784899,"7690":16784906,"7691":16784907,"7710":16784926,"7711":16784927,"7734":16784950,"7735":16784951,"7744":16784960,"7745":16784961,"7766":16784982,"7767":16784983,"7776":16784992,"7777":16784993,"7786":16785002,"7787":16785003,"7808":16785024,"7809":16785025,"7810":16785026,"7811":16785027,"7812":16785028,"7813":16785029,"7818":16785034,"7819":16785035,"7840":16785056,"7841":16785057,"7842":16785058,"7843":16785059,"7844":16785060,"7845":16785061,"7846":16785062,"7847":16785063,"7848":16785064,"7849":16785065,"7850":16785066,"7851":16785067,"7852":16785068,"7853":16785069,"7854":16785070,"7855":16785071,"7856":16785072,"7857":16785073,"7858":16785074,"7859":16785075,"7860":16785076,"7861":16785077,"7862":16785078,"7863":16785079,"7864":16785080,"7865":16785081,"7866":16785082,"7867":16785083,"7868":16785084,"7869":16785085,"7870":16785086,"7871":16785087,"7872":16785088,"7873":16785089,"7874":16785090,"7875":16785091,"7876":16785092,"7877":16785093,"7878":16785094,"7879":16785095,"7880":16785096,"7881":16785097,"7882":16785098,"7883":16785099,"7884":16785100,"7885":16785101,"7886":16785102,"7887":16785103,"7888":16785104,"7889":16785105,"7890":16785106,"7891":16785107,"7892":16785108,"7893":16785109,"7894":16785110,"7895":16785111,"7896":16785112,"7897":16785113,"7898":16785114,"7899":16785115,"7900":16785116,"7901":16785117,"7902":16785118,"7903":16785119,"7904":16785120,"7905":16785121,"7906":16785122,"7907":16785123,"7908":16785124,"7909":16785125,"7910":16785126,"7911":16785127,"7912":16785128,"7913":16785129,"7914":16785130,"7915":16785131,"7916":16785132,"7917":16785133,"7918":16785134,"7919":16785135,"7920":16785136,"7921":16785137,"7922":16785138,"7923":16785139,"7924":16785140,"7925":16785141,"7926":16785142,"7927":16785143,"7928":16785144,"7929":16785145,"8194":2722,"8195":2721,"8196":2723,"8197":2724,"8199":2725,"8200":2726,"8201":2727,"8202":2728,"8210":2747,"8211":2730,"8212":2729,"8213":1967,"8215":3295,"8216":2768,"8217":2769,"8218":2813,"8220":2770,"8221":2771,"8222":2814,"8224":2801,"8225":2802,"8226":2790,"8229":2735,"8230":2734,"8240":2773,"8242":2774,"8243":2775,"8248":2812,"8254":1150,"8304":16785520,"8308":16785524,"8309":16785525,"8310":16785526,"8311":16785527,"8312":16785528,"8313":16785529,"8320":16785536,"8321":16785537,"8322":16785538,"8323":16785539,"8324":16785540,"8325":16785541,"8326":16785542,"8327":16785543,"8328":16785544,"8329":16785545,"8352":16785568,"8353":16785569,"8354":16785570,"8355":16785571,"8356":16785572,"8357":16785573,"8358":16785574,"8359":16785575,"8360":16785576,"8361":3839,"8362":16785578,"8363":16785579,"8364":8364,"8453":2744,"8470":1712,"8471":2811,"8478":2772,"8482":2761,"8531":2736,"8532":2737,"8533":2738,"8534":2739,"8535":2740,"8536":2741,"8537":2742,"8538":2743,"8539":2755,"8540":2756,"8541":2757,"8542":2758,"8592":2299,"8593":2300,"8594":2301,"8595":2302,"8658":2254,"8660":2253,"8706":2287,"8709":16785925,"8711":2245,"8712":16785928,"8713":16785929,"8715":16785931,"8728":3018,"8730":2262,"8731":16785947,"8732":16785948,"8733":2241,"8734":2242,"8743":2270,"8744":2271,"8745":2268,"8746":2269,"8747":2239,"8748":16785964,"8749":16785965,"8756":2240,"8757":16785973,"8764":2248,"8771":2249,"8773":16785992,"8775":16785991,"8800":2237,"8801":2255,"8802":16786018,"8803":16786019,"8804":2236,"8805":2238,"8834":2266,"8835":2267,"8866":3068,"8867":3036,"8868":3010,"8869":3022,"8968":3027,"8970":3012,"8981":2810,"8992":2212,"8993":2213,"9109":3020,"9115":2219,"9117":2220,"9118":2221,"9120":2222,"9121":2215,"9123":2216,"9124":2217,"9126":2218,"9128":2223,"9132":2224,"9143":2209,"9146":2543,"9147":2544,"9148":2546,"9149":2547,"9225":2530,"9226":2533,"9227":2537,"9228":2531,"9229":2532,"9251":2732,"9252":2536,"9472":2211,"9474":2214,"9484":2210,"9488":2539,"9492":2541,"9496":2538,"9500":2548,"9508":2549,"9516":2551,"9524":2550,"9532":2542,"9618":2529,"9642":2791,"9643":2785,"9644":2779,"9645":2786,"9646":2783,"9647":2767,"9650":2792,"9651":2787,"9654":2781,"9655":2765,"9660":2793,"9661":2788,"9664":2780,"9665":2764,"9670":2528,"9675":2766,"9679":2782,"9702":2784,"9734":2789,"9742":2809,"9747":2762,"9756":2794,"9758":2795,"9792":2808,"9794":2807,"9827":2796,"9829":2798,"9830":2797,"9837":2806,"9839":2805,"10003":2803,"10007":2804,"10013":2777,"10016":2800,"10216":2748,"10217":2750,"10240":16787456,"10241":16787457,"10242":16787458,"10243":16787459,"10244":16787460,"10245":16787461,"10246":16787462,"10247":16787463,"10248":16787464,"10249":16787465,"10250":16787466,"10251":16787467,"10252":16787468,"10253":16787469,"10254":16787470,"10255":16787471,"10256":16787472,"10257":16787473,"10258":16787474,"10259":16787475,"10260":16787476,"10261":16787477,"10262":16787478,"10263":16787479,"10264":16787480,"10265":16787481,"10266":16787482,"10267":16787483,"10268":16787484,"10269":16787485,"10270":16787486,"10271":16787487,"10272":16787488,"10273":16787489,"10274":16787490,"10275":16787491,"10276":16787492,"10277":16787493,"10278":16787494,"10279":16787495,"10280":16787496,"10281":16787497,"10282":16787498,"10283":16787499,"10284":16787500,"10285":16787501,"10286":16787502,"10287":16787503,"10288":16787504,"10289":16787505,"10290":16787506,"10291":16787507,"10292":16787508,"10293":16787509,"10294":16787510,"10295":16787511,"10296":16787512,"10297":16787513,"10298":16787514,"10299":16787515,"10300":16787516,"10301":16787517,"10302":16787518,"10303":16787519,"10304":16787520,"10305":16787521,"10306":16787522,"10307":16787523,"10308":16787524,"10309":16787525,"10310":16787526,"10311":16787527,"10312":16787528,"10313":16787529,"10314":16787530,"10315":16787531,"10316":16787532,"10317":16787533,"10318":16787534,"10319":16787535,"10320":16787536,"10321":16787537,"10322":16787538,"10323":16787539,"10324":16787540,"10325":16787541,"10326":16787542,"10327":16787543,"10328":16787544,"10329":16787545,"10330":16787546,"10331":16787547,"10332":16787548,"10333":16787549,"10334":16787550,"10335":16787551,"10336":16787552,"10337":16787553,"10338":16787554,"10339":16787555,"10340":16787556,"10341":16787557,"10342":16787558,"10343":16787559,"10344":16787560,"10345":16787561,"10346":16787562,"10347":16787563,"10348":16787564,"10349":16787565,"10350":16787566,"10351":16787567,"10352":16787568,"10353":16787569,"10354":16787570,"10355":16787571,"10356":16787572,"10357":16787573,"10358":16787574,"10359":16787575,"10360":16787576,"10361":16787577,"10362":16787578,"10363":16787579,"10364":16787580,"10365":16787581,"10366":16787582,"10367":16787583,"10368":16787584,"10369":16787585,"10370":16787586,"10371":16787587,"10372":16787588,"10373":16787589,"10374":16787590,"10375":16787591,"10376":16787592,"10377":16787593,"10378":16787594,"10379":16787595,"10380":16787596,"10381":16787597,"10382":16787598,"10383":16787599,"10384":16787600,"10385":16787601,"10386":16787602,"10387":16787603,"10388":16787604,"10389":16787605,"10390":16787606,"10391":16787607,"10392":16787608,"10393":16787609,"10394":16787610,"10395":16787611,"10396":16787612,"10397":16787613,"10398":16787614,"10399":16787615,"10400":16787616,"10401":16787617,"10402":16787618,"10403":16787619,"10404":16787620,"10405":16787621,"10406":16787622,"10407":16787623,"10408":16787624,"10409":16787625,"10410":16787626,"10411":16787627,"10412":16787628,"10413":16787629,"10414":16787630,"10415":16787631,"10416":16787632,"10417":16787633,"10418":16787634,"10419":16787635,"10420":16787636,"10421":16787637,"10422":16787638,"10423":16787639,"10424":16787640,"10425":16787641,"10426":16787642,"10427":16787643,"10428":16787644,"10429":16787645,"10430":16787646,"10431":16787647,"10432":16787648,"10433":16787649,"10434":16787650,"10435":16787651,"10436":16787652,"10437":16787653,"10438":16787654,"10439":16787655,"10440":16787656,"10441":16787657,"10442":16787658,"10443":16787659,"10444":16787660,"10445":16787661,"10446":16787662,"10447":16787663,"10448":16787664,"10449":16787665,"10450":16787666,"10451":16787667,"10452":16787668,"10453":16787669,"10454":16787670,"10455":16787671,"10456":16787672,"10457":16787673,"10458":16787674,"10459":16787675,"10460":16787676,"10461":16787677,"10462":16787678,"10463":16787679,"10464":16787680,"10465":16787681,"10466":16787682,"10467":16787683,"10468":16787684,"10469":16787685,"10470":16787686,"10471":16787687,"10472":16787688,"10473":16787689,"10474":16787690,"10475":16787691,"10476":16787692,"10477":16787693,"10478":16787694,"10479":16787695,"10480":16787696,"10481":16787697,"10482":16787698,"10483":16787699,"10484":16787700,"10485":16787701,"10486":16787702,"10487":16787703,"10488":16787704,"10489":16787705,"10490":16787706,"10491":16787707,"10492":16787708,"10493":16787709,"10494":16787710,"10495":16787711,"12289":1188,"12290":1185,"12300":1186,"12301":1187,"12443":1246,"12444":1247,"12449":1191,"12450":1201,"12451":1192,"12452":1202,"12453":1193,"12454":1203,"12455":1194,"12456":1204,"12457":1195,"12458":1205,"12459":1206,"12461":1207,"12463":1208,"12465":1209,"12467":1210,"12469":1211,"12471":1212,"12473":1213,"12475":1214,"12477":1215,"12479":1216,"12481":1217,"12483":1199,"12484":1218,"12486":1219,"12488":1220,"12490":1221,"12491":1222,"12492":1223,"12493":1224,"12494":1225,"12495":1226,"12498":1227,"12501":1228,"12504":1229,"12507":1230,"12510":1231,"12511":1232,"12512":1233,"12513":1234,"12514":1235,"12515":1196,"12516":1236,"12517":1197,"12518":1237,"12519":1198,"12520":1238,"12521":1239,"12522":1240,"12523":1241,"12524":1242,"12525":1243,"12527":1244,"12530":1190,"12531":1245,"12539":1189,"12540":1200}; function lookup(k) { return k ? {keysym: k, keyname: keynames ? keynames[k] : k} : undefined; } + return { fromUnicode : function(u) { var keysym = codepoints[u]; @@ -20,6 +21,4 @@ var keysyms = (function(){ }, lookup : lookup }; -})(); - -/* [module] export default keysyms */ +}); diff --git a/core/input/util.js b/core/input/util.js index 533688f0..e0a6aafd 100644 --- a/core/input/util.js +++ b/core/input/util.js @@ -1,13 +1,17 @@ -/* [module] - * import KeyTable from "./keysym"; - * import keysyms from "./keysymdef"; +/* + * noVNC: HTML5 VNC client + * Copyright (C) 2012 Joel Martin + * Copyright (C) 2017 Pierre Ossman for Cendio AB + * Licensed under MPL 2.0 or any later version (see LICENSE.txt) */ +/*jslint browser: true, white: false */ + "use strict"; -var KeyboardUtil = {}; - -(function() { +define(["core/input/keysym", "core/input/keysymdef"], +function (KeyTable, keysyms) { + var KeyboardUtil = {}; function substituteCodepoint(cp) { // Any Unicode code points which do not have corresponding keysym entries @@ -287,387 +291,387 @@ var KeyboardUtil = {}; KeyboardUtil.keysymFromKeyCode = keysymFromKeyCode; KeyboardUtil.nonCharacterKey = nonCharacterKey; KeyboardUtil.substituteCodepoint = substituteCodepoint; -})(); -KeyboardUtil.QEMUKeyEventDecoder = function(modifierState, next) { - function sendAll(evts) { - for (var i = 0; i < evts.length; ++i) { - next(evts[i]); - } - } - - var numPadCodes = ["Numpad0", "Numpad1", "Numpad2", - "Numpad3", "Numpad4", "Numpad5", "Numpad6", - "Numpad7", "Numpad8", "Numpad9", "NumpadDecimal"]; - - var numLockOnKeySyms = { - "Numpad0": 0xffb0, "Numpad1": 0xffb1, "Numpad2": 0xffb2, - "Numpad3": 0xffb3, "Numpad4": 0xffb4, "Numpad5": 0xffb5, - "Numpad6": 0xffb6, "Numpad7": 0xffb7, "Numpad8": 0xffb8, - "Numpad9": 0xffb9, "NumpadDecimal": 0xffac - }; - - var numLockOnKeyCodes = [96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 108, 110]; - - function isNumPadMultiKey(evt) { - return (numPadCodes.indexOf(evt.code) !== -1); - } - - function getNumPadKeySym(evt) { - if (numLockOnKeyCodes.indexOf(evt.keyCode) !== -1) { - return numLockOnKeySyms[evt.code]; - } - return 0; - } - - function process(evt, type) { - var result = {type: type}; - result.code = evt.code; - result.keysym = 0; - - if (isNumPadMultiKey(evt)) { - result.keysym = getNumPadKeySym(evt); - } - - var hasModifier = modifierState.hasShortcutModifier() || !!modifierState.activeCharModifier(); - var isShift = evt.keyCode === 0x10 || evt.key === 'Shift'; - - var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!KeyboardUtil.nonCharacterKey(evt)); - - next(result); - return suppress; - } - return { - keydown: function(evt) { - sendAll(modifierState.keydown(evt)); - return process(evt, 'keydown'); - }, - keypress: function(evt) { - return true; - }, - keyup: function(evt) { - sendAll(modifierState.keyup(evt)); - return process(evt, 'keyup'); - }, - syncModifiers: function(evt) { - sendAll(modifierState.syncAny(evt)); - }, - releaseAll: function() { next({type: 'releaseall'}); } - }; -}; - -KeyboardUtil.TrackQEMUKeyState = function(next) { - var state = []; - - return function (evt) { - var last = state.length !== 0 ? state[state.length-1] : null; - - switch (evt.type) { - case 'keydown': - - if (!last || last.code !== evt.code) { - last = {code: evt.code}; - - if (state.length > 0 && state[state.length-1].code == 'ControlLeft') { - if (evt.code !== 'AltRight') { - next({code: 'ControlLeft', type: 'keydown', keysym: 0}); - } else { - state.pop(); - } - } - state.push(last); - } - if (evt.code !== 'ControlLeft') { - next(evt); - } - break; - - case 'keyup': - if (state.length === 0) { - return; - } - var idx = null; - // do we have a matching key tracked as being down? - for (var i = 0; i !== state.length; ++i) { - if (state[i].code === evt.code) { - idx = i; - break; - } - } - // if we couldn't find a match (it happens), assume it was the last key pressed - if (idx === null) { - if (evt.code === 'ControlLeft') { - return; - } - idx = state.length - 1; - } - - state.splice(idx, 1); - next(evt); - break; - case 'releaseall': - /* jshint shadow: true */ - for (var i = 0; i < state.length; ++i) { - next({code: state[i].code, keysym: 0, type: 'keyup'}); - } - /* jshint shadow: false */ - state = []; - } - }; -}; - -// Takes a DOM keyboard event and: -// - determines which keysym it represents -// - determines a keyId identifying the key that was pressed (corresponding to the key/keyCode properties on the DOM event) -// - synthesizes events to synchronize modifier key state between which modifiers are actually down, and which we thought were down -// - marks each event with an 'escape' property if a modifier was down which should be "escaped" -// - generates a "stall" event in cases where it might be necessary to wait and see if a keypress event follows a keydown -// This information is collected into an object which is passed to the next() function. (one call per event) -KeyboardUtil.KeyEventDecoder = function(modifierState, next) { - function sendAll(evts) { - for (var i = 0; i < evts.length; ++i) { - next(evts[i]); - } - } - function process(evt, type) { - var result = {type: type}; - var keyId = KeyboardUtil.getKey(evt); - if (keyId) { - result.keyId = keyId; - } - - var keysym = KeyboardUtil.getKeysym(evt); - - var hasModifier = modifierState.hasShortcutModifier() || !!modifierState.activeCharModifier(); - // Is this a case where we have to decide on the keysym right away, rather than waiting for the keypress? - // "special" keys like enter, tab or backspace don't send keypress events, - // and some browsers don't send keypresses at all if a modifier is down - if (keysym && (type !== 'keydown' || KeyboardUtil.nonCharacterKey(evt) || hasModifier)) { - result.keysym = keysym; - } - - var isShift = evt.keyCode === 0x10 || evt.key === 'Shift'; - - // Should we prevent the browser from handling the event? - // Doing so on a keydown (in most browsers) prevents keypress from being generated - // so only do that if we have to. - var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!KeyboardUtil.nonCharacterKey(evt)); - - // If a char modifier is down on a keydown, we need to insert a stall, - // so VerifyCharModifier knows to wait and see if a keypress is comnig - var stall = type === 'keydown' && modifierState.activeCharModifier() && !KeyboardUtil.nonCharacterKey(evt); - - // if a char modifier is pressed, get the keys it consists of (on Windows, AltGr is equivalent to Ctrl+Alt) - var active = modifierState.activeCharModifier(); - - // If we have a char modifier down, and we're able to determine a keysym reliably - // then (a) we know to treat the modifier as a char modifier, - // and (b) we'll have to "escape" the modifier to undo the modifier when sending the char. - if (active && keysym) { - var isCharModifier = false; - for (var i = 0; i < active.length; ++i) { - if (active[i] === keysym.keysym) { - isCharModifier = true; - } - } - if (type === 'keypress' && !isCharModifier) { - result.escape = modifierState.activeCharModifier(); + KeyboardUtil.QEMUKeyEventDecoder = function(modifierState, next) { + function sendAll(evts) { + for (var i = 0; i < evts.length; ++i) { + next(evts[i]); } } - if (stall) { - // insert a fake "stall" event - next({type: 'stall'}); - } - next(result); + var numPadCodes = ["Numpad0", "Numpad1", "Numpad2", + "Numpad3", "Numpad4", "Numpad5", "Numpad6", + "Numpad7", "Numpad8", "Numpad9", "NumpadDecimal"]; - return suppress; - } - - return { - keydown: function(evt) { - sendAll(modifierState.keydown(evt)); - return process(evt, 'keydown'); - }, - keypress: function(evt) { - return process(evt, 'keypress'); - }, - keyup: function(evt) { - sendAll(modifierState.keyup(evt)); - return process(evt, 'keyup'); - }, - syncModifiers: function(evt) { - sendAll(modifierState.syncAny(evt)); - }, - releaseAll: function() { next({type: 'releaseall'}); } - }; -}; - -// Combines keydown and keypress events where necessary to handle char modifiers. -// On some OS'es, a char modifier is sometimes used as a shortcut modifier. -// For example, on Windows, AltGr is synonymous with Ctrl-Alt. On a Danish keyboard layout, AltGr-2 yields a @, but Ctrl-Alt-D does nothing -// so when used with the '2' key, Ctrl-Alt counts as a char modifier (and should be escaped), but when used with 'D', it does not. -// The only way we can distinguish these cases is to wait and see if a keypress event arrives -// When we receive a "stall" event, wait a few ms before processing the next keydown. If a keypress has also arrived, merge the two -KeyboardUtil.VerifyCharModifier = function(next) { - var queue = []; - var timer = null; - function process() { - if (timer) { - return; - } - - var delayProcess = function () { - clearTimeout(timer); - timer = null; - process(); + var numLockOnKeySyms = { + "Numpad0": 0xffb0, "Numpad1": 0xffb1, "Numpad2": 0xffb2, + "Numpad3": 0xffb3, "Numpad4": 0xffb4, "Numpad5": 0xffb5, + "Numpad6": 0xffb6, "Numpad7": 0xffb7, "Numpad8": 0xffb8, + "Numpad9": 0xffb9, "NumpadDecimal": 0xffac }; - while (queue.length !== 0) { - var cur = queue[0]; - queue = queue.splice(1); - switch (cur.type) { - case 'stall': - // insert a delay before processing available events. - /* jshint loopfunc: true */ - timer = setTimeout(delayProcess, 5); - /* jshint loopfunc: false */ - return; + var numLockOnKeyCodes = [96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 108, 110]; + + function isNumPadMultiKey(evt) { + return (numPadCodes.indexOf(evt.code) !== -1); + } + + function getNumPadKeySym(evt) { + if (numLockOnKeyCodes.indexOf(evt.keyCode) !== -1) { + return numLockOnKeySyms[evt.code]; + } + return 0; + } + + function process(evt, type) { + var result = {type: type}; + result.code = evt.code; + result.keysym = 0; + + if (isNumPadMultiKey(evt)) { + result.keysym = getNumPadKeySym(evt); + } + + var hasModifier = modifierState.hasShortcutModifier() || !!modifierState.activeCharModifier(); + var isShift = evt.keyCode === 0x10 || evt.key === 'Shift'; + + var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!KeyboardUtil.nonCharacterKey(evt)); + + next(result); + return suppress; + } + return { + keydown: function(evt) { + sendAll(modifierState.keydown(evt)); + return process(evt, 'keydown'); + }, + keypress: function(evt) { + return true; + }, + keyup: function(evt) { + sendAll(modifierState.keyup(evt)); + return process(evt, 'keyup'); + }, + syncModifiers: function(evt) { + sendAll(modifierState.syncAny(evt)); + }, + releaseAll: function() { next({type: 'releaseall'}); } + }; + }; + + KeyboardUtil.TrackQEMUKeyState = function(next) { + var state = []; + + return function (evt) { + var last = state.length !== 0 ? state[state.length-1] : null; + + switch (evt.type) { case 'keydown': - // is the next element a keypress? Then we should merge the two - if (queue.length !== 0 && queue[0].type === 'keypress') { - // Firefox sends keypress even when no char is generated. - // so, if keypress keysym is the same as we'd have guessed from keydown, - // the modifier didn't have any effect, and should not be escaped - if (queue[0].escape && (!cur.keysym || cur.keysym.keysym !== queue[0].keysym.keysym)) { - cur.escape = queue[0].escape; + + if (!last || last.code !== evt.code) { + last = {code: evt.code}; + + if (state.length > 0 && state[state.length-1].code == 'ControlLeft') { + if (evt.code !== 'AltRight') { + next({code: 'ControlLeft', type: 'keydown', keysym: 0}); + } else { + state.pop(); + } } - cur.keysym = queue[0].keysym; - queue = queue.splice(1); + state.push(last); + } + if (evt.code !== 'ControlLeft') { + next(evt); } break; - } - // swallow stall events, and pass all others to the next stage - if (cur.type !== 'stall') { - next(cur); + case 'keyup': + if (state.length === 0) { + return; + } + var idx = null; + // do we have a matching key tracked as being down? + for (var i = 0; i !== state.length; ++i) { + if (state[i].code === evt.code) { + idx = i; + break; + } + } + // if we couldn't find a match (it happens), assume it was the last key pressed + if (idx === null) { + if (evt.code === 'ControlLeft') { + return; + } + idx = state.length - 1; + } + + state.splice(idx, 1); + next(evt); + break; + case 'releaseall': + /* jshint shadow: true */ + for (var i = 0; i < state.length; ++i) { + next({code: state[i].code, keysym: 0, type: 'keyup'}); + } + /* jshint shadow: false */ + state = []; + } + }; + }; + + // Takes a DOM keyboard event and: + // - determines which keysym it represents + // - determines a keyId identifying the key that was pressed (corresponding to the key/keyCode properties on the DOM event) + // - synthesizes events to synchronize modifier key state between which modifiers are actually down, and which we thought were down + // - marks each event with an 'escape' property if a modifier was down which should be "escaped" + // - generates a "stall" event in cases where it might be necessary to wait and see if a keypress event follows a keydown + // This information is collected into an object which is passed to the next() function. (one call per event) + KeyboardUtil.KeyEventDecoder = function(modifierState, next) { + function sendAll(evts) { + for (var i = 0; i < evts.length; ++i) { + next(evts[i]); } } - } - return function(evt) { - queue.push(evt); - process(); + function process(evt, type) { + var result = {type: type}; + var keyId = KeyboardUtil.getKey(evt); + if (keyId) { + result.keyId = keyId; + } + + var keysym = KeyboardUtil.getKeysym(evt); + + var hasModifier = modifierState.hasShortcutModifier() || !!modifierState.activeCharModifier(); + // Is this a case where we have to decide on the keysym right away, rather than waiting for the keypress? + // "special" keys like enter, tab or backspace don't send keypress events, + // and some browsers don't send keypresses at all if a modifier is down + if (keysym && (type !== 'keydown' || KeyboardUtil.nonCharacterKey(evt) || hasModifier)) { + result.keysym = keysym; + } + + var isShift = evt.keyCode === 0x10 || evt.key === 'Shift'; + + // Should we prevent the browser from handling the event? + // Doing so on a keydown (in most browsers) prevents keypress from being generated + // so only do that if we have to. + var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!KeyboardUtil.nonCharacterKey(evt)); + + // If a char modifier is down on a keydown, we need to insert a stall, + // so VerifyCharModifier knows to wait and see if a keypress is comnig + var stall = type === 'keydown' && modifierState.activeCharModifier() && !KeyboardUtil.nonCharacterKey(evt); + + // if a char modifier is pressed, get the keys it consists of (on Windows, AltGr is equivalent to Ctrl+Alt) + var active = modifierState.activeCharModifier(); + + // If we have a char modifier down, and we're able to determine a keysym reliably + // then (a) we know to treat the modifier as a char modifier, + // and (b) we'll have to "escape" the modifier to undo the modifier when sending the char. + if (active && keysym) { + var isCharModifier = false; + for (var i = 0; i < active.length; ++i) { + if (active[i] === keysym.keysym) { + isCharModifier = true; + } + } + if (type === 'keypress' && !isCharModifier) { + result.escape = modifierState.activeCharModifier(); + } + } + + if (stall) { + // insert a fake "stall" event + next({type: 'stall'}); + } + next(result); + + return suppress; + } + + return { + keydown: function(evt) { + sendAll(modifierState.keydown(evt)); + return process(evt, 'keydown'); + }, + keypress: function(evt) { + return process(evt, 'keypress'); + }, + keyup: function(evt) { + sendAll(modifierState.keyup(evt)); + return process(evt, 'keyup'); + }, + syncModifiers: function(evt) { + sendAll(modifierState.syncAny(evt)); + }, + releaseAll: function() { next({type: 'releaseall'}); } + }; }; -}; -// Keeps track of which keys we (and the server) believe are down -// When a keyup is received, match it against this list, to determine the corresponding keysym(s) -// in some cases, a single key may produce multiple keysyms, so the corresponding keyup event must release all of these chars -// key repeat events should be merged into a single entry. -// Because we can't always identify which entry a keydown or keyup event corresponds to, we sometimes have to guess -KeyboardUtil.TrackKeyState = function(next) { - var state = []; - - return function (evt) { - var last = state.length !== 0 ? state[state.length-1] : null; - - switch (evt.type) { - case 'keydown': - // insert a new entry if last seen key was different. - if (!last || !evt.keyId || last.keyId !== evt.keyId) { - last = {keyId: evt.keyId, keysyms: {}}; - state.push(last); - } - if (evt.keysym) { - // make sure last event contains this keysym (a single "logical" keyevent - // can cause multiple key events to be sent to the VNC server) - last.keysyms[evt.keysym.keysym] = evt.keysym; - last.ignoreKeyPress = true; - next(evt); - } - break; - case 'keypress': - if (!last) { - last = {keyId: evt.keyId, keysyms: {}}; - state.push(last); - } - if (!evt.keysym) { - console.log('keypress with no keysym:', evt); - } - - // If we didn't expect a keypress, and already sent a keydown to the VNC server - // based on the keydown, make sure to skip this event. - if (evt.keysym && !last.ignoreKeyPress) { - last.keysyms[evt.keysym.keysym] = evt.keysym; - evt.type = 'keydown'; - next(evt); - } - break; - case 'keyup': - if (state.length === 0) { + // Combines keydown and keypress events where necessary to handle char modifiers. + // On some OS'es, a char modifier is sometimes used as a shortcut modifier. + // For example, on Windows, AltGr is synonymous with Ctrl-Alt. On a Danish keyboard layout, AltGr-2 yields a @, but Ctrl-Alt-D does nothing + // so when used with the '2' key, Ctrl-Alt counts as a char modifier (and should be escaped), but when used with 'D', it does not. + // The only way we can distinguish these cases is to wait and see if a keypress event arrives + // When we receive a "stall" event, wait a few ms before processing the next keydown. If a keypress has also arrived, merge the two + KeyboardUtil.VerifyCharModifier = function(next) { + var queue = []; + var timer = null; + function process() { + if (timer) { return; } - var idx = null; - // do we have a matching key tracked as being down? - for (var i = 0; i !== state.length; ++i) { - if (state[i].keyId === evt.keyId) { - idx = i; + + var delayProcess = function () { + clearTimeout(timer); + timer = null; + process(); + }; + + while (queue.length !== 0) { + var cur = queue[0]; + queue = queue.splice(1); + switch (cur.type) { + case 'stall': + // insert a delay before processing available events. + /* jshint loopfunc: true */ + timer = setTimeout(delayProcess, 5); + /* jshint loopfunc: false */ + return; + case 'keydown': + // is the next element a keypress? Then we should merge the two + if (queue.length !== 0 && queue[0].type === 'keypress') { + // Firefox sends keypress even when no char is generated. + // so, if keypress keysym is the same as we'd have guessed from keydown, + // the modifier didn't have any effect, and should not be escaped + if (queue[0].escape && (!cur.keysym || cur.keysym.keysym !== queue[0].keysym.keysym)) { + cur.escape = queue[0].escape; + } + cur.keysym = queue[0].keysym; + queue = queue.splice(1); + } break; } - } - // if we couldn't find a match (it happens), assume it was the last key pressed - if (idx === null) { - idx = state.length - 1; - } - var item = state.splice(idx, 1)[0]; - // for each keysym tracked by this key entry, clone the current event and override the keysym - var clone = (function(){ - function Clone(){} - return function (obj) { Clone.prototype=obj; return new Clone(); }; - }()); - for (var key in item.keysyms) { - var out = clone(evt); - out.keysym = item.keysyms[key]; - next(out); - } - break; - case 'releaseall': - /* jshint shadow: true */ - for (var i = 0; i < state.length; ++i) { - for (var key in state[i].keysyms) { - var keysym = state[i].keysyms[key]; - next({keyId: 0, keysym: keysym, type: 'keyup'}); + // swallow stall events, and pass all others to the next stage + if (cur.type !== 'stall') { + next(cur); } } - /* jshint shadow: false */ - state = []; } + return function(evt) { + queue.push(evt); + process(); + }; }; -}; -// Handles "escaping" of modifiers: if a char modifier is used to produce a keysym (such as AltGr-2 to generate an @), -// then the modifier must be "undone" before sending the @, and "redone" afterwards. -KeyboardUtil.EscapeModifiers = function(next) { - return function(evt) { - if (evt.type !== 'keydown' || evt.escape === undefined) { + // Keeps track of which keys we (and the server) believe are down + // When a keyup is received, match it against this list, to determine the corresponding keysym(s) + // in some cases, a single key may produce multiple keysyms, so the corresponding keyup event must release all of these chars + // key repeat events should be merged into a single entry. + // Because we can't always identify which entry a keydown or keyup event corresponds to, we sometimes have to guess + KeyboardUtil.TrackKeyState = function(next) { + var state = []; + + return function (evt) { + var last = state.length !== 0 ? state[state.length-1] : null; + + switch (evt.type) { + case 'keydown': + // insert a new entry if last seen key was different. + if (!last || !evt.keyId || last.keyId !== evt.keyId) { + last = {keyId: evt.keyId, keysyms: {}}; + state.push(last); + } + if (evt.keysym) { + // make sure last event contains this keysym (a single "logical" keyevent + // can cause multiple key events to be sent to the VNC server) + last.keysyms[evt.keysym.keysym] = evt.keysym; + last.ignoreKeyPress = true; + next(evt); + } + break; + case 'keypress': + if (!last) { + last = {keyId: evt.keyId, keysyms: {}}; + state.push(last); + } + if (!evt.keysym) { + console.log('keypress with no keysym:', evt); + } + + // If we didn't expect a keypress, and already sent a keydown to the VNC server + // based on the keydown, make sure to skip this event. + if (evt.keysym && !last.ignoreKeyPress) { + last.keysyms[evt.keysym.keysym] = evt.keysym; + evt.type = 'keydown'; + next(evt); + } + break; + case 'keyup': + if (state.length === 0) { + return; + } + var idx = null; + // do we have a matching key tracked as being down? + for (var i = 0; i !== state.length; ++i) { + if (state[i].keyId === evt.keyId) { + idx = i; + break; + } + } + // if we couldn't find a match (it happens), assume it was the last key pressed + if (idx === null) { + idx = state.length - 1; + } + + var item = state.splice(idx, 1)[0]; + // for each keysym tracked by this key entry, clone the current event and override the keysym + var clone = (function(){ + function Clone(){} + return function (obj) { Clone.prototype=obj; return new Clone(); }; + }()); + for (var key in item.keysyms) { + var out = clone(evt); + out.keysym = item.keysyms[key]; + next(out); + } + break; + case 'releaseall': + /* jshint shadow: true */ + for (var i = 0; i < state.length; ++i) { + for (var key in state[i].keysyms) { + var keysym = state[i].keysyms[key]; + next({keyId: 0, keysym: keysym, type: 'keyup'}); + } + } + /* jshint shadow: false */ + state = []; + } + }; + }; + + // Handles "escaping" of modifiers: if a char modifier is used to produce a keysym (such as AltGr-2 to generate an @), + // then the modifier must be "undone" before sending the @, and "redone" afterwards. + KeyboardUtil.EscapeModifiers = function(next) { + return function(evt) { + if (evt.type !== 'keydown' || evt.escape === undefined) { + next(evt); + return; + } + // undo modifiers + for (var i = 0; i < evt.escape.length; ++i) { + next({type: 'keyup', keyId: 0, keysym: keysyms.lookup(evt.escape[i])}); + } + // send the character event next(evt); - return; - } - // undo modifiers - for (var i = 0; i < evt.escape.length; ++i) { - next({type: 'keyup', keyId: 0, keysym: keysyms.lookup(evt.escape[i])}); - } - // send the character event - next(evt); - // redo modifiers - /* jshint shadow: true */ - for (var i = 0; i < evt.escape.length; ++i) { - next({type: 'keydown', keyId: 0, keysym: keysyms.lookup(evt.escape[i])}); - } - /* jshint shadow: false */ + // redo modifiers + /* jshint shadow: true */ + for (var i = 0; i < evt.escape.length; ++i) { + next({type: 'keydown', keyId: 0, keysym: keysyms.lookup(evt.escape[i])}); + } + /* jshint shadow: false */ + }; }; -}; -/* [module] export default KeyboardUtil; */ + return KeyboardUtil; +}); diff --git a/core/input/xtscancodes.js b/core/input/xtscancodes.js index 7aa4bf00..3d846fe6 100644 --- a/core/input/xtscancodes.js +++ b/core/input/xtscancodes.js @@ -1,153 +1,155 @@ "use strict"; -var XtScancode = { - "Escape": 0x0001, - "Digit1": 0x0002, - "Digit2": 0x0003, - "Digit3": 0x0004, - "Digit4": 0x0005, - "Digit5": 0x0006, - "Digit6": 0x0007, - "Digit7": 0x0008, - "Digit8": 0x0009, - "Digit9": 0x000A, - "Digit0": 0x000B, - "Minus": 0x000C, - "Equal": 0x000D, - "Backspace": 0x000E, - "Tab": 0x000F, - "KeyQ": 0x0010, - "KeyW": 0x0011, - "KeyE": 0x0012, - "KeyR": 0x0013, - "KeyT": 0x0014, - "KeyY": 0x0015, - "KeyU": 0x0016, - "KeyI": 0x0017, - "KeyO": 0x0018, - "KeyP": 0x0019, - "BracketLeft": 0x001A, - "BracketRight": 0x001B, - "Enter": 0x001C, - "ControlLeft": 0x001D, - "KeyA": 0x001E, - "KeyS": 0x001F, - "KeyD": 0x0020, - "KeyF": 0x0021, - "KeyG": 0x0022, - "KeyH": 0x0023, - "KeyJ": 0x0024, - "KeyK": 0x0025, - "KeyL": 0x0026, - "Semicolon": 0x0027, - "Quote": 0x0028, - "Backquote": 0x0029, - "ShiftLeft": 0x002A, - "Backslash": 0x002B, - "KeyZ": 0x002C, - "KeyX": 0x002D, - "KeyC": 0x002E, - "KeyV": 0x002F, - "KeyB": 0x0030, - "KeyN": 0x0031, - "KeyM": 0x0032, - "Comma": 0x0033, - "Period": 0x0034, - "Slash": 0x0035, - "ShiftRight": 0x0036, - "NumpadMultiply": 0x0037, - "AltLeft": 0x0038, - "Space": 0x0039, - "CapsLock": 0x003A, - "F1": 0x003B, - "F2": 0x003C, - "F3": 0x003D, - "F4": 0x003E, - "F5": 0x003F, - "F6": 0x0040, - "F7": 0x0041, - "F8": 0x0042, - "F9": 0x0043, - "F10": 0x0044, - "Pause": 0xE045, - "ScrollLock": 0x0046, - "Numpad7": 0x0047, - "Numpad8": 0x0048, - "Numpad9": 0x0049, - "NumpadSubtract": 0x004A, - "Numpad4": 0x004B, - "Numpad5": 0x004C, - "Numpad6": 0x004D, - "NumpadAdd": 0x004E, - "Numpad1": 0x004F, - "Numpad2": 0x0050, - "Numpad3": 0x0051, - "Numpad0": 0x0052, - "NumpadDecimal": 0x0053, - "IntlBackslash": 0x0056, - "F11": 0x0057, - "F12": 0x0058, - "IntlYen": 0x007D, - "MediaTrackPrevious": 0xE010, - "MediaTrackNext": 0xE019, - "NumpadEnter": 0xE01C, - "ControlRight": 0xE01D, - "VolumeMute": 0xE020, - "MediaPlayPause": 0xE022, - "MediaStop": 0xE024, - "VolumeDown": 0xE02E, - "VolumeUp": 0xE030, - "BrowserHome": 0xE032, - "NumpadDivide": 0xE035, - "PrintScreen": 0xE037, - "AltRight": 0xE038, - "NumLock": 0x0045, - "Home": 0xE047, - "ArrowUp": 0xE048, - "PageUp": 0xE049, - "ArrowLeft": 0xE04B, - "ArrowRight": 0xE04D, - "End": 0xE04F, - "ArrowDown": 0xE050, - "PageDown": 0xE051, - "Insert": 0xE052, - "Delete": 0xE053, - "MetaLeft": 0xE05B, - "MetaRight": 0xE05C, - "OSLeft": 0xE05B, // OSLeft and OSRight are kept for compatability since - "OSRight": 0xE05C, // Firefox haven't updated to MetaLeft and MetaRight yet - "ContextMenu": 0xE05D, - "BrowserSearch": 0xE065, - "BrowserFavorites": 0xE066, - "BrowserRefresh": 0xE067, - "BrowserStop": 0xE068, - "BrowserForward": 0xE069, - "BrowserBack": 0xE06A, - "NumpadComma": 0x007E, - "NumpadEqual": 0x0059, - "F13": 0x0064, - "F14": 0x0065, - "F15": 0x0066, - "F16": 0x0067, - "F17": 0x0068, - "F18": 0x0069, - "F19": 0x006A, - "F20": 0x006B, - "F21": 0x006C, - "F22": 0x006D, - "F23": 0x006E, - "F24": 0x0076, - "KanaMode": 0x0070, - "Lang2": 0x0071, - "Lang1": 0x0072, - "IntlRo": 0x0073, - "Convert": 0x0079, - "NonConvert": 0x007B, - "LaunchApp2": 0xE021, - "Power": 0xE05E, - "LaunchApp1": 0xE06B, - "LaunchMail": 0xE06C, - "MediaSelect": 0xE06D, -}; +define(function () { + var XtScancode = { + "Escape": 0x0001, + "Digit1": 0x0002, + "Digit2": 0x0003, + "Digit3": 0x0004, + "Digit4": 0x0005, + "Digit5": 0x0006, + "Digit6": 0x0007, + "Digit7": 0x0008, + "Digit8": 0x0009, + "Digit9": 0x000A, + "Digit0": 0x000B, + "Minus": 0x000C, + "Equal": 0x000D, + "Backspace": 0x000E, + "Tab": 0x000F, + "KeyQ": 0x0010, + "KeyW": 0x0011, + "KeyE": 0x0012, + "KeyR": 0x0013, + "KeyT": 0x0014, + "KeyY": 0x0015, + "KeyU": 0x0016, + "KeyI": 0x0017, + "KeyO": 0x0018, + "KeyP": 0x0019, + "BracketLeft": 0x001A, + "BracketRight": 0x001B, + "Enter": 0x001C, + "ControlLeft": 0x001D, + "KeyA": 0x001E, + "KeyS": 0x001F, + "KeyD": 0x0020, + "KeyF": 0x0021, + "KeyG": 0x0022, + "KeyH": 0x0023, + "KeyJ": 0x0024, + "KeyK": 0x0025, + "KeyL": 0x0026, + "Semicolon": 0x0027, + "Quote": 0x0028, + "Backquote": 0x0029, + "ShiftLeft": 0x002A, + "Backslash": 0x002B, + "KeyZ": 0x002C, + "KeyX": 0x002D, + "KeyC": 0x002E, + "KeyV": 0x002F, + "KeyB": 0x0030, + "KeyN": 0x0031, + "KeyM": 0x0032, + "Comma": 0x0033, + "Period": 0x0034, + "Slash": 0x0035, + "ShiftRight": 0x0036, + "NumpadMultiply": 0x0037, + "AltLeft": 0x0038, + "Space": 0x0039, + "CapsLock": 0x003A, + "F1": 0x003B, + "F2": 0x003C, + "F3": 0x003D, + "F4": 0x003E, + "F5": 0x003F, + "F6": 0x0040, + "F7": 0x0041, + "F8": 0x0042, + "F9": 0x0043, + "F10": 0x0044, + "Pause": 0xE045, + "ScrollLock": 0x0046, + "Numpad7": 0x0047, + "Numpad8": 0x0048, + "Numpad9": 0x0049, + "NumpadSubtract": 0x004A, + "Numpad4": 0x004B, + "Numpad5": 0x004C, + "Numpad6": 0x004D, + "NumpadAdd": 0x004E, + "Numpad1": 0x004F, + "Numpad2": 0x0050, + "Numpad3": 0x0051, + "Numpad0": 0x0052, + "NumpadDecimal": 0x0053, + "IntlBackslash": 0x0056, + "F11": 0x0057, + "F12": 0x0058, + "IntlYen": 0x007D, + "MediaTrackPrevious": 0xE010, + "MediaTrackNext": 0xE019, + "NumpadEnter": 0xE01C, + "ControlRight": 0xE01D, + "VolumeMute": 0xE020, + "MediaPlayPause": 0xE022, + "MediaStop": 0xE024, + "VolumeDown": 0xE02E, + "VolumeUp": 0xE030, + "BrowserHome": 0xE032, + "NumpadDivide": 0xE035, + "PrintScreen": 0xE037, + "AltRight": 0xE038, + "NumLock": 0x0045, + "Home": 0xE047, + "ArrowUp": 0xE048, + "PageUp": 0xE049, + "ArrowLeft": 0xE04B, + "ArrowRight": 0xE04D, + "End": 0xE04F, + "ArrowDown": 0xE050, + "PageDown": 0xE051, + "Insert": 0xE052, + "Delete": 0xE053, + "MetaLeft": 0xE05B, + "MetaRight": 0xE05C, + "OSLeft": 0xE05B, // OSLeft and OSRight are kept for compatability since + "OSRight": 0xE05C, // Firefox haven't updated to MetaLeft and MetaRight yet + "ContextMenu": 0xE05D, + "BrowserSearch": 0xE065, + "BrowserFavorites": 0xE066, + "BrowserRefresh": 0xE067, + "BrowserStop": 0xE068, + "BrowserForward": 0xE069, + "BrowserBack": 0xE06A, + "NumpadComma": 0x007E, + "NumpadEqual": 0x0059, + "F13": 0x0064, + "F14": 0x0065, + "F15": 0x0066, + "F16": 0x0067, + "F17": 0x0068, + "F18": 0x0069, + "F19": 0x006A, + "F20": 0x006B, + "F21": 0x006C, + "F22": 0x006D, + "F23": 0x006E, + "F24": 0x0076, + "KanaMode": 0x0070, + "Lang2": 0x0071, + "Lang1": 0x0072, + "IntlRo": 0x0073, + "Convert": 0x0079, + "NonConvert": 0x007B, + "LaunchApp2": 0xE021, + "Power": 0xE05E, + "LaunchApp1": 0xE06B, + "LaunchMail": 0xE06C, + "MediaSelect": 0xE06D, + }; -/* [module] export default XtScancode */ + return XtScancode; +}); diff --git a/core/rfb.js b/core/rfb.js index 5a6d3849..1d0c0103 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -2,6 +2,7 @@ * noVNC: HTML5 VNC client * Copyright (C) 2012 Joel Martin * Copyright (C) 2016 Samuel Mannehed for Cendio AB + * Copyright (C) 2017 Pierre Ossman for Cendio AB * Licensed under MPL 2.0 (see LICENSE.txt) * * See README.md for usage and integration instructions. @@ -10,262 +11,255 @@ * (c) 2012 Michael Tinglof, Joe Balaz, Les Piech (Mercuri.ca) */ -/* [module] - * import Util from "./util"; - * import Display from "./display"; - * import { Keyboard, Mouse } from "./input/devices" - * import Websock from "./websock" - * import Base64 from "./base64"; - * import DES from "./des"; - * import KeyTable from "./input/keysym"; - * import XtScancode from "./input/xtscancodes"; - * import Inflator from "./inflator.mod"; - */ /*jslint white: false, browser: true */ -/*global window, Util, Display, Keyboard, Mouse, Websock, Websock_native, Base64, DES, KeyTable, Inflator, XtScancode */ "use strict"; -/* [module] export default */ function RFB(defaults) { - if (!defaults) { - defaults = {}; - } - - this._rfb_host = ''; - this._rfb_port = 5900; - this._rfb_password = ''; - this._rfb_path = ''; - - this._rfb_connection_state = ''; - this._rfb_init_state = ''; - this._rfb_version = 0; - this._rfb_max_version = 3.8; - this._rfb_auth_scheme = ''; - this._rfb_disconnect_reason = ""; - - this._rfb_tightvnc = false; - this._rfb_xvp_ver = 0; - - // In preference order - this._encodings = [ - ['COPYRECT', 0x01 ], - ['TIGHT', 0x07 ], - ['TIGHT_PNG', -260 ], - ['HEXTILE', 0x05 ], - ['RRE', 0x02 ], - ['RAW', 0x00 ], - - // Psuedo-encoding settings - - //['JPEG_quality_lo', -32 ], - ['JPEG_quality_med', -26 ], - //['JPEG_quality_hi', -23 ], - //['compress_lo', -255 ], - ['compress_hi', -247 ], - - ['DesktopSize', -223 ], - ['last_rect', -224 ], - ['Cursor', -239 ], - ['QEMUExtendedKeyEvent', -258 ], - ['ExtendedDesktopSize', -308 ], - ['xvp', -309 ], - ['Fence', -312 ], - ['ContinuousUpdates', -313 ] - ]; - - this._encHandlers = {}; - this._encNames = {}; - this._encStats = {}; - - this._sock = null; // Websock object - this._display = null; // Display object - this._flushing = false; // Display flushing state - this._keyboard = null; // Keyboard input handler object - this._mouse = null; // Mouse input handler object - this._disconnTimer = null; // disconnection timer - - this._supportsFence = false; - - this._supportsContinuousUpdates = false; - this._enabledContinuousUpdates = false; - - // Frame buffer update state - this._FBU = { - rects: 0, - subrects: 0, // RRE - lines: 0, // RAW - tiles: 0, // HEXTILE - bytes: 0, - x: 0, - y: 0, - width: 0, - height: 0, - encoding: 0, - subencoding: -1, - background: null, - zlib: [] // TIGHT zlib streams - }; - - this._fb_Bpp = 4; - this._fb_depth = 3; - this._fb_width = 0; - this._fb_height = 0; - this._fb_name = ""; - - this._destBuff = null; - this._paletteBuff = new Uint8Array(1024); // 256 * 4 (max palette size * max bytes-per-pixel) - - this._rre_chunk_sz = 100; - - this._timing = { - last_fbu: 0, - fbu_total: 0, - fbu_total_cnt: 0, - full_fbu_total: 0, - full_fbu_cnt: 0, - - fbu_rt_start: 0, - fbu_rt_total: 0, - fbu_rt_cnt: 0, - pixels: 0 - }; - - this._supportsSetDesktopSize = false; - this._screen_id = 0; - this._screen_flags = 0; - - // Mouse state - this._mouse_buttonMask = 0; - this._mouse_arr = []; - this._viewportDragging = false; - this._viewportDragPos = {}; - this._viewportHasMoved = false; - - // QEMU Extended Key Event support - default to false - this._qemuExtKeyEventSupported = false; - - // set the default value on user-facing properties - Util.set_defaults(this, defaults, { - 'target': 'null', // VNC display rendering Canvas object - 'focusContainer': document, // DOM element that captures keyboard input - 'encrypt': false, // Use TLS/SSL/wss encryption - 'true_color': true, // Request true color pixel data - 'local_cursor': false, // Request locally rendered cursor - 'shared': true, // Request shared mode - 'view_only': false, // Disable client mouse/keyboard - 'xvp_password_sep': '@', // Separator for XVP password fields - 'disconnectTimeout': 3, // Time (s) to wait for disconnection - 'wsProtocols': ['binary'], // Protocols to use in the WebSocket connection - 'repeaterID': '', // [UltraVNC] RepeaterID to connect to - 'viewportDrag': false, // Move the viewport on mouse drags - - // Callback functions - 'onUpdateState': function () { }, // onUpdateState(rfb, state, oldstate): connection state change - 'onNotification': function () { }, // onNotification(rfb, msg, level, options): notification for UI - 'onDisconnected': function () { }, // onDisconnected(rfb, reason): disconnection finished - 'onPasswordRequired': function () { }, // onPasswordRequired(rfb, msg): VNC password is required - 'onClipboard': function () { }, // onClipboard(rfb, text): RFB clipboard contents received - 'onBell': function () { }, // onBell(rfb): RFB Bell message received - 'onFBUReceive': function () { }, // onFBUReceive(rfb, fbu): RFB FBU received but not yet processed - 'onFBUComplete': function () { }, // onFBUComplete(rfb, fbu): RFB FBU received and processed - 'onFBResize': function () { }, // onFBResize(rfb, width, height): frame buffer resized - 'onDesktopName': function () { }, // onDesktopName(rfb, name): desktop name received - 'onXvpInit': function () { } // onXvpInit(version): XVP extensions active for this connection - }); - - // main setup - Util.Debug(">> RFB.constructor"); - - // populate encHandlers with bound versions - Object.keys(RFB.encodingHandlers).forEach(function (encName) { - this._encHandlers[encName] = RFB.encodingHandlers[encName].bind(this); - }.bind(this)); - - // Create lookup tables based on encoding number - for (var i = 0; i < this._encodings.length; i++) { - this._encHandlers[this._encodings[i][1]] = this._encHandlers[this._encodings[i][0]]; - this._encNames[this._encodings[i][1]] = this._encodings[i][0]; - this._encStats[this._encodings[i][1]] = [0, 0]; - } - - // NB: nothing that needs explicit teardown should be done - // before this point, since this can throw an exception - try { - this._display = new Display({target: this._target, - onFlush: this._onFlush.bind(this)}); - } catch (exc) { - Util.Error("Display exception: " + exc); - throw exc; - } - - this._keyboard = new Keyboard({target: this._focusContainer, - onKeyPress: this._handleKeyPress.bind(this)}); - - this._mouse = new Mouse({target: this._target, - onMouseButton: this._handleMouseButton.bind(this), - onMouseMove: this._handleMouseMove.bind(this), - notify: this._keyboard.sync.bind(this._keyboard)}); - - this._sock = new Websock(); - this._sock.on('message', this._handle_message.bind(this)); - this._sock.on('open', function () { - if ((this._rfb_connection_state === 'connecting') && - (this._rfb_init_state === '')) { - this._rfb_init_state = 'ProtocolVersion'; - Util.Debug("Starting VNC handshake"); - } else { - this._fail("Unexpected server connection"); - } - }.bind(this)); - this._sock.on('close', function (e) { - Util.Warn("WebSocket on-close event"); - var msg = ""; - if (e.code) { - msg = " (code: " + e.code; - if (e.reason) { - msg += ", reason: " + e.reason; - } - msg += ")"; - } - switch (this._rfb_connection_state) { - case 'disconnecting': - this._updateConnectionState('disconnected'); - break; - case 'connecting': - this._fail('Failed to connect to server', msg); - break; - case 'connected': - // Handle disconnects that were initiated server-side - this._updateConnectionState('disconnecting'); - this._updateConnectionState('disconnected'); - break; - case 'disconnected': - this._fail("Unexpected server disconnect", - "Already disconnected: " + msg); - break; - default: - this._fail("Unexpected server disconnect", - "Not in any state yet: " + msg); - break; - } - this._sock.off('close'); - }.bind(this)); - this._sock.on('error', function (e) { - Util.Warn("WebSocket on-error event"); - }); - - this._init_vars(); - this._cleanup(); - - var rmode = this._display.get_render_mode(); - Util.Info("Using native WebSockets, render mode: " + rmode); - - Util.Debug("<< RFB.constructor"); -}; - -(function() { +define(["core/util", "core/display", "core/websock", + "core/inflator", "core/des", + "core/input/devices", "core/input/keysym", + "core/input/xtscancodes"], +function (Util, display, websock, Inflator, DES, devices, + KeyTable, XtScancode) { var _ = Util.Localisation.get; + function RFB(defaults) { + if (!defaults) { + defaults = {}; + } + + this._rfb_host = ''; + this._rfb_port = 5900; + this._rfb_password = ''; + this._rfb_path = ''; + + this._rfb_connection_state = ''; + this._rfb_init_state = ''; + this._rfb_version = 0; + this._rfb_max_version = 3.8; + this._rfb_auth_scheme = ''; + this._rfb_disconnect_reason = ""; + + this._rfb_tightvnc = false; + this._rfb_xvp_ver = 0; + + // In preference order + this._encodings = [ + ['COPYRECT', 0x01 ], + ['TIGHT', 0x07 ], + ['TIGHT_PNG', -260 ], + ['HEXTILE', 0x05 ], + ['RRE', 0x02 ], + ['RAW', 0x00 ], + + // Psuedo-encoding settings + + //['JPEG_quality_lo', -32 ], + ['JPEG_quality_med', -26 ], + //['JPEG_quality_hi', -23 ], + //['compress_lo', -255 ], + ['compress_hi', -247 ], + + ['DesktopSize', -223 ], + ['last_rect', -224 ], + ['Cursor', -239 ], + ['QEMUExtendedKeyEvent', -258 ], + ['ExtendedDesktopSize', -308 ], + ['xvp', -309 ], + ['Fence', -312 ], + ['ContinuousUpdates', -313 ] + ]; + + this._encHandlers = {}; + this._encNames = {}; + this._encStats = {}; + + this._sock = null; // Websock object + this._display = null; // Display object + this._flushing = false; // Display flushing state + this._keyboard = null; // Keyboard input handler object + this._mouse = null; // Mouse input handler object + this._disconnTimer = null; // disconnection timer + + this._supportsFence = false; + + this._supportsContinuousUpdates = false; + this._enabledContinuousUpdates = false; + + // Frame buffer update state + this._FBU = { + rects: 0, + subrects: 0, // RRE + lines: 0, // RAW + tiles: 0, // HEXTILE + bytes: 0, + x: 0, + y: 0, + width: 0, + height: 0, + encoding: 0, + subencoding: -1, + background: null, + zlib: [] // TIGHT zlib streams + }; + + this._fb_Bpp = 4; + this._fb_depth = 3; + this._fb_width = 0; + this._fb_height = 0; + this._fb_name = ""; + + this._destBuff = null; + this._paletteBuff = new Uint8Array(1024); // 256 * 4 (max palette size * max bytes-per-pixel) + + this._rre_chunk_sz = 100; + + this._timing = { + last_fbu: 0, + fbu_total: 0, + fbu_total_cnt: 0, + full_fbu_total: 0, + full_fbu_cnt: 0, + + fbu_rt_start: 0, + fbu_rt_total: 0, + fbu_rt_cnt: 0, + pixels: 0 + }; + + this._supportsSetDesktopSize = false; + this._screen_id = 0; + this._screen_flags = 0; + + // Mouse state + this._mouse_buttonMask = 0; + this._mouse_arr = []; + this._viewportDragging = false; + this._viewportDragPos = {}; + this._viewportHasMoved = false; + + // QEMU Extended Key Event support - default to false + this._qemuExtKeyEventSupported = false; + + // set the default value on user-facing properties + Util.set_defaults(this, defaults, { + 'target': 'null', // VNC display rendering Canvas object + 'focusContainer': document, // DOM element that captures keyboard input + 'encrypt': false, // Use TLS/SSL/wss encryption + 'true_color': true, // Request true color pixel data + 'local_cursor': false, // Request locally rendered cursor + 'shared': true, // Request shared mode + 'view_only': false, // Disable client mouse/keyboard + 'xvp_password_sep': '@', // Separator for XVP password fields + 'disconnectTimeout': 3, // Time (s) to wait for disconnection + 'wsProtocols': ['binary'], // Protocols to use in the WebSocket connection + 'repeaterID': '', // [UltraVNC] RepeaterID to connect to + 'viewportDrag': false, // Move the viewport on mouse drags + + // Callback functions + 'onUpdateState': function () { }, // onUpdateState(rfb, state, oldstate): connection state change + 'onNotification': function () { }, // onNotification(rfb, msg, level, options): notification for UI + 'onDisconnected': function () { }, // onDisconnected(rfb, reason): disconnection finished + 'onPasswordRequired': function () { }, // onPasswordRequired(rfb, msg): VNC password is required + 'onClipboard': function () { }, // onClipboard(rfb, text): RFB clipboard contents received + 'onBell': function () { }, // onBell(rfb): RFB Bell message received + 'onFBUReceive': function () { }, // onFBUReceive(rfb, fbu): RFB FBU received but not yet processed + 'onFBUComplete': function () { }, // onFBUComplete(rfb, fbu): RFB FBU received and processed + 'onFBResize': function () { }, // onFBResize(rfb, width, height): frame buffer resized + 'onDesktopName': function () { }, // onDesktopName(rfb, name): desktop name received + 'onXvpInit': function () { } // onXvpInit(version): XVP extensions active for this connection + }); + + // main setup + Util.Debug(">> RFB.constructor"); + + // populate encHandlers with bound versions + Object.keys(RFB.encodingHandlers).forEach(function (encName) { + this._encHandlers[encName] = RFB.encodingHandlers[encName].bind(this); + }.bind(this)); + + // Create lookup tables based on encoding number + for (var i = 0; i < this._encodings.length; i++) { + this._encHandlers[this._encodings[i][1]] = this._encHandlers[this._encodings[i][0]]; + this._encNames[this._encodings[i][1]] = this._encodings[i][0]; + this._encStats[this._encodings[i][1]] = [0, 0]; + } + + // NB: nothing that needs explicit teardown should be done + // before this point, since this can throw an exception + try { + this._display = new display.Display({target: this._target, + onFlush: this._onFlush.bind(this)}); + } catch (exc) { + Util.Error("Display exception: " + exc); + throw exc; + } + + this._keyboard = new devices.Keyboard({target: this._focusContainer, + onKeyPress: this._handleKeyPress.bind(this)}); + + this._mouse = new devices.Mouse({target: this._target, + onMouseButton: this._handleMouseButton.bind(this), + onMouseMove: this._handleMouseMove.bind(this), + notify: this._keyboard.sync.bind(this._keyboard)}); + + this._sock = new websock.Websock(); + this._sock.on('message', this._handle_message.bind(this)); + this._sock.on('open', function () { + if ((this._rfb_connection_state === 'connecting') && + (this._rfb_init_state === '')) { + this._rfb_init_state = 'ProtocolVersion'; + Util.Debug("Starting VNC handshake"); + } else { + this._fail("Unexpected server connection"); + } + }.bind(this)); + this._sock.on('close', function (e) { + Util.Warn("WebSocket on-close event"); + var msg = ""; + if (e.code) { + msg = " (code: " + e.code; + if (e.reason) { + msg += ", reason: " + e.reason; + } + msg += ")"; + } + switch (this._rfb_connection_state) { + case 'disconnecting': + this._updateConnectionState('disconnected'); + break; + case 'connecting': + this._fail('Failed to connect to server', msg); + break; + case 'connected': + // Handle disconnects that were initiated server-side + this._updateConnectionState('disconnecting'); + this._updateConnectionState('disconnected'); + break; + case 'disconnected': + this._fail("Unexpected server disconnect", + "Already disconnected: " + msg); + break; + default: + this._fail("Unexpected server disconnect", + "Not in any state yet: " + msg); + break; + } + this._sock.off('close'); + }.bind(this)); + this._sock.on('error', function (e) { + Util.Warn("WebSocket on-error event"); + }); + + this._init_vars(); + this._cleanup(); + + var rmode = this._display.get_render_mode(); + Util.Info("Using native WebSockets, render mode: " + rmode); + + Util.Debug("<< RFB.constructor"); + }; + RFB.prototype = { // Public methods connect: function (host, port, password, path) { @@ -2443,4 +2437,6 @@ Util.Error("Server sent compress level pseudo-encoding"); } }; -})(); + + return { RFB: RFB }; +}); diff --git a/core/util.js b/core/util.js index 96c07046..4f08efed 100644 --- a/core/util.js +++ b/core/util.js @@ -1,282 +1,276 @@ /* * noVNC: HTML5 VNC client * Copyright (C) 2012 Joel Martin + * Copyright (C) 2017 Pierre Ossman for Cendio AB * Licensed under MPL 2.0 (see LICENSE.txt) * * See README.md for usage and integration instructions. */ /* jshint white: false, nonstandard: true */ -/*global window, console, document, navigator, ActiveXObject, INCLUDE_URI */ "use strict"; -var Util = {}; +define(function() { + var Util = {}; -/* - * ------------------------------------------------------ - * Namespaced in Util - * ------------------------------------------------------ - */ + /* + * Logging/debug routines + */ -/* - * Logging/debug routines - */ - -Util._log_level = 'warn'; -Util.init_logging = function (level) { - if (typeof level === 'undefined') { - level = Util._log_level; - } else { - Util._log_level = level; - } - - Util.Debug = Util.Info = Util.Warn = Util.Error = function (msg) {}; - if (typeof window.console !== "undefined") { - /* jshint -W086 */ - switch (level) { - case 'debug': - Util.Debug = function (msg) { console.log(msg); }; - case 'info': - Util.Info = function (msg) { console.info(msg); }; - case 'warn': - Util.Warn = function (msg) { console.warn(msg); }; - case 'error': - Util.Error = function (msg) { console.error(msg); }; - case 'none': - break; - default: - throw new Error("invalid logging type '" + level + "'"); + var _log_level = 'warn'; + Util.init_logging = function (level) { + if (typeof level === 'undefined') { + level = _log_level; + } else { + _log_level = level; } - /* jshint +W086 */ - } -}; -Util.get_logging = function () { - return Util._log_level; -}; -// Initialize logging level -Util.init_logging(); -Util.make_property = function (proto, name, mode, type) { + Util.Debug = Util.Info = Util.Warn = Util.Error = function (msg) {}; + if (typeof window.console !== "undefined") { + /* jshint -W086 */ + switch (level) { + case 'debug': + Util.Debug = function (msg) { console.log(msg); }; + case 'info': + Util.Info = function (msg) { console.info(msg); }; + case 'warn': + Util.Warn = function (msg) { console.warn(msg); }; + case 'error': + Util.Error = function (msg) { console.error(msg); }; + case 'none': + break; + default: + throw new Error("invalid logging type '" + level + "'"); + } + /* jshint +W086 */ + } + }; + Util.get_logging = function () { + return _log_level; + }; + // Initialize logging level + Util.init_logging(); - var getter; - if (type === 'arr') { - getter = function (idx) { - if (typeof idx !== 'undefined') { - return this['_' + name][idx]; - } else { + Util.make_property = function (proto, name, mode, type) { + + var getter; + if (type === 'arr') { + getter = function (idx) { + if (typeof idx !== 'undefined') { + return this['_' + name][idx]; + } else { + return this['_' + name]; + } + }; + } else { + getter = function () { return this['_' + name]; + }; + } + + var make_setter = function (process_val) { + if (process_val) { + return function (val, idx) { + if (typeof idx !== 'undefined') { + this['_' + name][idx] = process_val(val); + } else { + this['_' + name] = process_val(val); + } + }; + } else { + return function (val, idx) { + if (typeof idx !== 'undefined') { + this['_' + name][idx] = val; + } else { + this['_' + name] = val; + } + }; } }; - } else { - getter = function () { - return this['_' + name]; - }; - } - var make_setter = function (process_val) { - if (process_val) { - return function (val, idx) { - if (typeof idx !== 'undefined') { - this['_' + name][idx] = process_val(val); + var setter; + if (type === 'bool') { + setter = make_setter(function (val) { + if (!val || (val in {'0': 1, 'no': 1, 'false': 1})) { + return false; } else { - this['_' + name] = process_val(val); + return true; } - }; + }); + } else if (type === 'int') { + setter = make_setter(function (val) { return parseInt(val, 10); }); + } else if (type === 'float') { + setter = make_setter(parseFloat); + } else if (type === 'str') { + setter = make_setter(String); + } else if (type === 'func') { + setter = make_setter(function (val) { + if (!val) { + return function () {}; + } else { + return val; + } + }); + } else if (type === 'arr' || type === 'dom' || type == 'raw') { + setter = make_setter(); } else { - return function (val, idx) { - if (typeof idx !== 'undefined') { - this['_' + name][idx] = val; - } else { - this['_' + name] = val; - } - }; + throw new Error('Unknown property type ' + type); // some sanity checking + } + + // set the getter + if (typeof proto['get_' + name] === 'undefined') { + proto['get_' + name] = getter; + } + + // set the setter if needed + if (typeof proto['set_' + name] === 'undefined') { + if (mode === 'rw') { + proto['set_' + name] = setter; + } else if (mode === 'wo') { + proto['set_' + name] = function (val, idx) { + if (typeof this['_' + name] !== 'undefined') { + throw new Error(name + " can only be set once"); + } + setter.call(this, val, idx); + }; + } + } + + // make a special setter that we can use in set defaults + proto['_raw_set_' + name] = function (val, idx) { + setter.call(this, val, idx); + //delete this['_init_set_' + name]; // remove it after use + }; + }; + + Util.make_properties = function (constructor, arr) { + for (var i = 0; i < arr.length; i++) { + Util.make_property(constructor.prototype, arr[i][0], arr[i][1], arr[i][2]); } }; - var setter; - if (type === 'bool') { - setter = make_setter(function (val) { - if (!val || (val in {'0': 1, 'no': 1, 'false': 1})) { - return false; - } else { - return true; - } - }); - } else if (type === 'int') { - setter = make_setter(function (val) { return parseInt(val, 10); }); - } else if (type === 'float') { - setter = make_setter(parseFloat); - } else if (type === 'str') { - setter = make_setter(String); - } else if (type === 'func') { - setter = make_setter(function (val) { - if (!val) { - return function () {}; - } else { - return val; - } - }); - } else if (type === 'arr' || type === 'dom' || type == 'raw') { - setter = make_setter(); - } else { - throw new Error('Unknown property type ' + type); // some sanity checking - } + Util.set_defaults = function (obj, conf, defaults) { + var defaults_keys = Object.keys(defaults); + var conf_keys = Object.keys(conf); + var keys_obj = {}; + var i; + for (i = 0; i < defaults_keys.length; i++) { keys_obj[defaults_keys[i]] = 1; } + for (i = 0; i < conf_keys.length; i++) { keys_obj[conf_keys[i]] = 1; } + var keys = Object.keys(keys_obj); - // set the getter - if (typeof proto['get_' + name] === 'undefined') { - proto['get_' + name] = getter; - } + for (i = 0; i < keys.length; i++) { + var setter = obj['_raw_set_' + keys[i]]; + if (!setter) { + Util.Warn('Invalid property ' + keys[i]); + continue; + } - // set the setter if needed - if (typeof proto['set_' + name] === 'undefined') { - if (mode === 'rw') { - proto['set_' + name] = setter; - } else if (mode === 'wo') { - proto['set_' + name] = function (val, idx) { - if (typeof this['_' + name] !== 'undefined') { - throw new Error(name + " can only be set once"); - } - setter.call(this, val, idx); - }; + if (keys[i] in conf) { + setter.call(obj, conf[keys[i]]); + } else { + setter.call(obj, defaults[keys[i]]); + } } - } - - // make a special setter that we can use in set defaults - proto['_raw_set_' + name] = function (val, idx) { - setter.call(this, val, idx); - //delete this['_init_set_' + name]; // remove it after use }; -}; -Util.make_properties = function (constructor, arr) { - for (var i = 0; i < arr.length; i++) { - Util.make_property(constructor.prototype, arr[i][0], arr[i][1], arr[i][2]); - } -}; + /* + * Decode from UTF-8 + */ + Util.decodeUTF8 = function (utf8string) { + return decodeURIComponent(escape(utf8string)); + }; -Util.set_defaults = function (obj, conf, defaults) { - var defaults_keys = Object.keys(defaults); - var conf_keys = Object.keys(conf); - var keys_obj = {}; - var i; - for (i = 0; i < defaults_keys.length; i++) { keys_obj[defaults_keys[i]] = 1; } - for (i = 0; i < conf_keys.length; i++) { keys_obj[conf_keys[i]] = 1; } - var keys = Object.keys(keys_obj); - for (i = 0; i < keys.length; i++) { - var setter = obj['_raw_set_' + keys[i]]; - if (!setter) { - Util.Warn('Invalid property ' + keys[i]); - continue; + + /* + * Cross-browser routines + */ + + Util.getPosition = function(obj) { + // NB(sross): the Mozilla developer reference seems to indicate that + // getBoundingClientRect includes border and padding, so the canvas + // style should NOT include either. + var objPosition = obj.getBoundingClientRect(); + return {'x': objPosition.left + window.pageXOffset, 'y': objPosition.top + window.pageYOffset, + 'width': objPosition.width, 'height': objPosition.height}; + }; + + Util.getPointerEvent = function (e) { + var evt; + evt = (e ? e : window.event); + evt = (evt.changedTouches ? evt.changedTouches[0] : evt.touches ? evt.touches[0] : evt); + return evt; + }; + + // Get mouse event position in DOM element + Util.getEventPosition = function (e, obj, scale) { + var evt, docX, docY, pos; + evt = Util.getPointerEvent(e); + if (evt.pageX || evt.pageY) { + docX = evt.pageX; + docY = evt.pageY; + } else if (evt.clientX || evt.clientY) { + docX = evt.clientX + document.body.scrollLeft + + document.documentElement.scrollLeft; + docY = evt.clientY + document.body.scrollTop + + document.documentElement.scrollTop; } - - if (keys[i] in conf) { - setter.call(obj, conf[keys[i]]); - } else { - setter.call(obj, defaults[keys[i]]); + pos = Util.getPosition(obj); + if (typeof scale === "undefined") { + scale = 1; } - } -}; + var realx = docX - pos.x; + var realy = docY - pos.y; + var x = Math.max(Math.min(realx, pos.width - 1), 0); + var y = Math.max(Math.min(realy, pos.height - 1), 0); + return {'x': x / scale, 'y': y / scale, 'realx': realx / scale, 'realy': realy / scale}; + }; -/* - * Decode from UTF-8 - */ -Util.decodeUTF8 = function (utf8string) { - return decodeURIComponent(escape(utf8string)); -}; + Util.stopEvent = function (e) { + e.stopPropagation(); + e.preventDefault(); + }; + // Touch detection + Util.isTouchDevice = ('ontouchstart' in document.documentElement) || + // requried for Chrome debugger + (document.ontouchstart !== undefined) || + // required for MS Surface + (navigator.maxTouchPoints > 0) || + (navigator.msMaxTouchPoints > 0); + window.addEventListener('touchstart', function onFirstTouch() { + Util.isTouchDevice = true; + window.removeEventListener('touchstart', onFirstTouch, false); + }, false); + var _cursor_uris_supported = null; -/* - * Cross-browser routines - */ + Util.browserSupportsCursorURIs = function () { + if (_cursor_uris_supported === null) { + try { + var target = document.createElement('canvas'); + target.style.cursor = 'url("data:image/x-icon;base64,AAACAAEACAgAAAIAAgA4AQAAFgAAACgAAAAIAAAAEAAAAAEAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAA==") 2 2, default'; -Util.getPosition = function(obj) { - // NB(sross): the Mozilla developer reference seems to indicate that - // getBoundingClientRect includes border and padding, so the canvas - // style should NOT include either. - var objPosition = obj.getBoundingClientRect(); - return {'x': objPosition.left + window.pageXOffset, 'y': objPosition.top + window.pageYOffset, - 'width': objPosition.width, 'height': objPosition.height}; -}; - -Util.getPointerEvent = function (e) { - var evt; - evt = (e ? e : window.event); - evt = (evt.changedTouches ? evt.changedTouches[0] : evt.touches ? evt.touches[0] : evt); - return evt; -}; - -// Get mouse event position in DOM element -Util.getEventPosition = function (e, obj, scale) { - var evt, docX, docY, pos; - evt = Util.getPointerEvent(e); - if (evt.pageX || evt.pageY) { - docX = evt.pageX; - docY = evt.pageY; - } else if (evt.clientX || evt.clientY) { - docX = evt.clientX + document.body.scrollLeft + - document.documentElement.scrollLeft; - docY = evt.clientY + document.body.scrollTop + - document.documentElement.scrollTop; - } - pos = Util.getPosition(obj); - if (typeof scale === "undefined") { - scale = 1; - } - var realx = docX - pos.x; - var realy = docY - pos.y; - var x = Math.max(Math.min(realx, pos.width - 1), 0); - var y = Math.max(Math.min(realy, pos.height - 1), 0); - return {'x': x / scale, 'y': y / scale, 'realx': realx / scale, 'realy': realy / scale}; -}; - -Util.stopEvent = function (e) { - e.stopPropagation(); - e.preventDefault(); -}; - -// Touch detection -Util.isTouchDevice = ('ontouchstart' in document.documentElement) || - // requried for Chrome debugger - (document.ontouchstart !== undefined) || - // required for MS Surface - (navigator.maxTouchPoints > 0) || - (navigator.msMaxTouchPoints > 0); -window.addEventListener('touchstart', function onFirstTouch() { - Util.isTouchDevice = true; - window.removeEventListener('touchstart', onFirstTouch, false); -}, false); - -Util._cursor_uris_supported = null; - -Util.browserSupportsCursorURIs = function () { - if (Util._cursor_uris_supported === null) { - try { - var target = document.createElement('canvas'); - target.style.cursor = 'url("data:image/x-icon;base64,AAACAAEACAgAAAIAAgA4AQAAFgAAACgAAAAIAAAAEAAAAAEAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAA==") 2 2, default'; - - if (target.style.cursor) { - Util.Info("Data URI scheme cursor supported"); - Util._cursor_uris_supported = true; - } else { - Util.Warn("Data URI scheme cursor not supported"); - Util._cursor_uris_supported = false; + if (target.style.cursor) { + Util.Info("Data URI scheme cursor supported"); + _cursor_uris_supported = true; + } else { + Util.Warn("Data URI scheme cursor not supported"); + _cursor_uris_supported = false; + } + } catch (exc) { + Util.Error("Data URI scheme cursor test exception: " + exc); + _cursor_uris_supported = false; } - } catch (exc) { - Util.Error("Data URI scheme cursor test exception: " + exc); - Util._cursor_uris_supported = false; } - } - return Util._cursor_uris_supported; -}; + return _cursor_uris_supported; + }; -// Set browser engine versions. Based on mootools. -Util.Features = {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)}; + // Set browser engine versions. Based on mootools. + Util.Features = {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)}; -(function () { // 'presto': (function () { return (!window.opera) ? false : true; }()), var detectPresto = function () { return !!window.opera; @@ -343,172 +337,202 @@ Util.Features = {xpath: !!(document.evaluate), air: !!(window.runtime), query: ! // Extract actual webkit version if available Util.Engine.webkit = detectActualWebkit(Util.Engine.webkit); } -})(); -Util.Flash = (function () { - var v, version; - try { - v = navigator.plugins['Shockwave Flash'].description; - } catch (err1) { + Util.Flash = (function () { + var v, version; try { - v = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); - } catch (err2) { - v = '0 r0'; + v = navigator.plugins['Shockwave Flash'].description; + } catch (err1) { + try { + v = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); + } catch (err2) { + v = '0 r0'; + } } - } - version = v.match(/\d+/g); - return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0}; -}()); + version = v.match(/\d+/g); + return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0}; + }()); -Util.Localisation = { - // Currently configured language - language: 'en', + Util.Localisation = { + // Currently configured language + language: 'en', - // Configure suitable language based on user preferences - setup: function (supportedLanguages) { - var userLanguages; + // Translation data + _translations: null, - Util.Localisation.language = 'en'; // Default: US English + // Configure and load suitable language based on user preferences + setup: function (supportedLanguages, basedir, callback) { + Util.Localisation._setLanguageCode(supportedLanguages); - /* - * Navigator.languages only available in Chrome (32+) and FireFox (32+) - * Fall back to navigator.language for other browsers - */ - if (typeof window.navigator.languages == 'object') { - userLanguages = window.navigator.languages; - } else { - userLanguages = [navigator.language || navigator.userLanguage]; - } + if (Util.Localisation.language === 'en') { + if (callback !== undefined) { + callback(); + } - for (var i = 0;i < userLanguages.length;i++) { - var userLang = userLanguages[i]; - userLang = userLang.toLowerCase(); - userLang = userLang.replace("_", "-"); - userLang = userLang.split("-"); - - // Built-in default? - if ((userLang[0] === 'en') && - ((userLang[1] === undefined) || (userLang[1] === 'us'))) { return; } - // First pass: perfect match - for (var j = 0;j < supportedLanguages.length;j++) { - var supLang = supportedLanguages[j]; - supLang = supLang.toLowerCase(); - supLang = supLang.replace("_", "-"); - supLang = supLang.split("-"); - - if (userLang[0] !== supLang[0]) - continue; - if (userLang[1] !== supLang[1]) - continue; - - Util.Localisation.language = supportedLanguages[j]; - return; + if (basedir[basedir.length - 1] !== '/') { + basedir = basedir + '/'; } - // Second pass: fallback - for (var j = 0;j < supportedLanguages.length;j++) { - supLang = supportedLanguages[j]; - supLang = supLang.toLowerCase(); - supLang = supLang.replace("_", "-"); - supLang = supLang.split("-"); + require([basedir + Util.Localisation.language], + function(lang) { + Util.Localisation._translations = lang; - if (userLang[0] !== supLang[0]) - continue; - if (supLang[1] !== undefined) - continue; + if (callback !== undefined) { + callback(); + } + }); + }, - Util.Localisation.language = supportedLanguages[j]; - return; - } - } - }, + // Internal function to figure out the proper language code + _setLanguageCode: function (supportedLanguages) { + var userLanguages; - // Retrieve localised text - get: function (id) { - if (typeof Language !== 'undefined' && Language[id]) { - return Language[id]; - } else { - return id; - } - }, + Util.Localisation.language = 'en'; // Default: US English - // Traverses the DOM and translates relevant fields - // See https://html.spec.whatwg.org/multipage/dom.html#attr-translate - translateDOM: function () { - function process(elem, enabled) { - function isAnyOf(searchElement, items) { - return items.indexOf(searchElement) !== -1; + /* + * Navigator.languages only available in Chrome (32+) and FireFox (32+) + * Fall back to navigator.language for other browsers + */ + if (typeof window.navigator.languages == 'object') { + userLanguages = window.navigator.languages; + } else { + userLanguages = [navigator.language || navigator.userLanguage]; } - function translateAttribute(elem, attr) { - var str = elem.getAttribute(attr); - str = Util.Localisation.get(str); - elem.setAttribute(attr, str); + for (var i = 0;i < userLanguages.length;i++) { + var userLang = userLanguages[i]; + userLang = userLang.toLowerCase(); + userLang = userLang.replace("_", "-"); + userLang = userLang.split("-"); + + // Built-in default? + if ((userLang[0] === 'en') && + ((userLang[1] === undefined) || (userLang[1] === 'us'))) { + return; + } + + // First pass: perfect match + for (var j = 0;j < supportedLanguages.length;j++) { + var supLang = supportedLanguages[j]; + supLang = supLang.toLowerCase(); + supLang = supLang.replace("_", "-"); + supLang = supLang.split("-"); + + if (userLang[0] !== supLang[0]) + continue; + if (userLang[1] !== supLang[1]) + continue; + + Util.Localisation.language = supportedLanguages[j]; + return; + } + + // Second pass: fallback + for (var j = 0;j < supportedLanguages.length;j++) { + supLang = supportedLanguages[j]; + supLang = supLang.toLowerCase(); + supLang = supLang.replace("_", "-"); + supLang = supLang.split("-"); + + if (userLang[0] !== supLang[0]) + continue; + if (supLang[1] !== undefined) + continue; + + Util.Localisation.language = supportedLanguages[j]; + return; + } + } + }, + + // Retrieve localised text + get: function (id) { + if ((Util.Localisation._translations === null) || + (Util.Localisation._translations[id] === undefined)) { + return id; } - function translateTextNode(node) { - var str = node.data.trim(); - str = Util.Localisation.get(str); - node.data = str; - } + return Util.Localisation._translations[id]; + }, - if (elem.hasAttribute("translate")) { - if (isAnyOf(elem.getAttribute("translate"), ["", "yes"])) { - enabled = true; - } else if (isAnyOf(elem.getAttribute("translate"), ["no"])) { - enabled = false; + // Traverses the DOM and translates relevant fields + // See https://html.spec.whatwg.org/multipage/dom.html#attr-translate + translateDOM: function () { + function process(elem, enabled) { + function isAnyOf(searchElement, items) { + return items.indexOf(searchElement) !== -1; + } + + function translateAttribute(elem, attr) { + var str = elem.getAttribute(attr); + str = Util.Localisation.get(str); + elem.setAttribute(attr, str); + } + + function translateTextNode(node) { + var str = node.data.trim(); + str = Util.Localisation.get(str); + node.data = str; + } + + if (elem.hasAttribute("translate")) { + if (isAnyOf(elem.getAttribute("translate"), ["", "yes"])) { + enabled = true; + } else if (isAnyOf(elem.getAttribute("translate"), ["no"])) { + enabled = false; + } + } + + if (enabled) { + if (elem.hasAttribute("abbr") && + elem.tagName === "TH") { + translateAttribute(elem, "abbr"); + } + if (elem.hasAttribute("alt") && + isAnyOf(elem.tagName, ["AREA", "IMG", "INPUT"])) { + translateAttribute(elem, "alt"); + } + if (elem.hasAttribute("download") && + isAnyOf(elem.tagName, ["A", "AREA"])) { + translateAttribute(elem, "download"); + } + if (elem.hasAttribute("label") && + isAnyOf(elem.tagName, ["MENUITEM", "MENU", "OPTGROUP", + "OPTION", "TRACK"])) { + translateAttribute(elem, "label"); + } + // FIXME: Should update "lang" + if (elem.hasAttribute("placeholder") && + isAnyOf(elem.tagName in ["INPUT", "TEXTAREA"])) { + translateAttribute(elem, "placeholder"); + } + if (elem.hasAttribute("title")) { + translateAttribute(elem, "title"); + } + if (elem.hasAttribute("value") && + elem.tagName === "INPUT" && + isAnyOf(elem.getAttribute("type"), ["reset", "button"])) { + translateAttribute(elem, "value"); + } + } + + for (var i = 0;i < elem.childNodes.length;i++) { + var node = elem.childNodes[i]; + if (node.nodeType === node.ELEMENT_NODE) { + process(node, enabled); + } else if (node.nodeType === node.TEXT_NODE && enabled) { + translateTextNode(node); + } } } - if (enabled) { - if (elem.hasAttribute("abbr") && - elem.tagName === "TH") { - translateAttribute(elem, "abbr"); - } - if (elem.hasAttribute("alt") && - isAnyOf(elem.tagName, ["AREA", "IMG", "INPUT"])) { - translateAttribute(elem, "alt"); - } - if (elem.hasAttribute("download") && - isAnyOf(elem.tagName, ["A", "AREA"])) { - translateAttribute(elem, "download"); - } - if (elem.hasAttribute("label") && - isAnyOf(elem.tagName, ["MENUITEM", "MENU", "OPTGROUP", - "OPTION", "TRACK"])) { - translateAttribute(elem, "label"); - } - // FIXME: Should update "lang" - if (elem.hasAttribute("placeholder") && - isAnyOf(elem.tagName in ["INPUT", "TEXTAREA"])) { - translateAttribute(elem, "placeholder"); - } - if (elem.hasAttribute("title")) { - translateAttribute(elem, "title"); - } - if (elem.hasAttribute("value") && - elem.tagName === "INPUT" && - isAnyOf(elem.getAttribute("type"), ["reset", "button"])) { - translateAttribute(elem, "value"); - } - } + process(document.body, true); + }, + }; - for (var i = 0;i < elem.childNodes.length;i++) { - node = elem.childNodes[i]; - if (node.nodeType === node.ELEMENT_NODE) { - process(node, enabled); - } else if (node.nodeType === node.TEXT_NODE && enabled) { - translateTextNode(node); - } - } - } - - process(document.body, true); - }, -}; - -/* [module] export default Util; */ + return Util; +}); diff --git a/core/websock.js b/core/websock.js index de2366eb..f1477c4e 100644 --- a/core/websock.js +++ b/core/websock.js @@ -14,44 +14,39 @@ * read binary data off of the receive queue. */ -/* [module] - * import Util from "./util"; - * import Base64 from "./base64"; - */ - /*jslint browser: true, bitwise: true */ -/*global Util*/ "use strict"; -/* [module] export default */ function Websock() { +define(["core/util"], +function (Util) { - this._websocket = null; // WebSocket object + function Websock() { + this._websocket = null; // WebSocket object - this._rQi = 0; // Receive queue index - this._rQlen = 0; // Next write position in the receive queue - this._rQbufferSize = 1024 * 1024 * 4; // Receive queue buffer size (4 MiB) - this._rQmax = this._rQbufferSize / 8; - // called in init: this._rQ = new Uint8Array(this._rQbufferSize); - this._rQ = null; // Receive queue + this._rQi = 0; // Receive queue index + this._rQlen = 0; // Next write position in the receive queue + this._rQbufferSize = 1024 * 1024 * 4; // Receive queue buffer size (4 MiB) + this._rQmax = this._rQbufferSize / 8; + // called in init: this._rQ = new Uint8Array(this._rQbufferSize); + this._rQ = null; // Receive queue - this._sQbufferSize = 1024 * 10; // 10 KiB - // called in init: this._sQ = new Uint8Array(this._sQbufferSize); - this._sQlen = 0; - this._sQ = null; // Send queue + this._sQbufferSize = 1024 * 10; // 10 KiB + // called in init: this._sQ = new Uint8Array(this._sQbufferSize); + this._sQlen = 0; + this._sQ = null; // Send queue - this._mode = 'binary'; // Current WebSocket mode: 'binary', 'base64' - this.maxBufferedAmount = 200; + this._mode = 'binary'; // Current WebSocket mode: 'binary', 'base64' + this.maxBufferedAmount = 200; - this._eventHandlers = { - 'message': function () {}, - 'open': function () {}, - 'close': function () {}, - 'error': function () {} + this._eventHandlers = { + 'message': function () {}, + 'open': function () {}, + 'close': function () {}, + 'error': function () {} + }; }; -}; -(function () { // this has performance issues in some versions Chromium, and // doesn't gain a tremendous amount of performance increase in Firefox // at the moment. It may be valuable to turn it on in the future. @@ -423,4 +418,6 @@ } } }; -})(); + + return { Websock: Websock }; +}); diff --git a/docs/notes b/docs/notes index dfef0bd6..e2f20187 100644 --- a/docs/notes +++ b/docs/notes @@ -1,5 +1,5 @@ Rebuilding inflator.js - Download pako from npm -- Install browserify using npm -- browserify core/inflator.mod.js -o core/inflator.js -s Inflator +- Install requirejs using npm +- make -C inflator install diff --git a/inflator/Makefile b/inflator/Makefile new file mode 100644 index 00000000..a73e4ec4 --- /dev/null +++ b/inflator/Makefile @@ -0,0 +1,19 @@ +.PHONY: all install clean + +all: inflator-merged.js + +RJS := r.js + +inflator-merged.js: build.js inflator.js pako + r.js -o build.js + +pako: ../node_modules/pako + $(RJS) -convert $< pako/ + +install: all + rm -f ../core/inflator.js + cp inflator-merged.js ../core/inflator.js + +clean: + rm -f inflator.js + rm -rf pako diff --git a/inflator/build.js b/inflator/build.js new file mode 100644 index 00000000..cbcf4f7e --- /dev/null +++ b/inflator/build.js @@ -0,0 +1,8 @@ +({ + baseUrl: ".", + name: "core/inflator", + paths: { + "core": ".", + }, + out: "inflator-merged.js" +}) diff --git a/inflator/inflator.js b/inflator/inflator.js new file mode 100644 index 00000000..2381483d --- /dev/null +++ b/inflator/inflator.js @@ -0,0 +1,52 @@ +/* + * noVNC: HTML5 VNC client + * Copyright (C) 2012 Joel Martin + * Copyright (C) 2017 Pierre Ossman for Cendio AB + * Licensed under MPL 2.0 or any later version (see LICENSE.txt) + */ + +/*jslint browser: true, white: false */ + +"use strict"; + +define(["pako/lib/zlib/inflate.js", "pako/lib/zlib/zstream.js"], +function (zlib, ZStream) { + + function Inflate() { + this.strm = new ZStream(); + this.chunkSize = 1024 * 10 * 10; + this.strm.output = new Uint8Array(this.chunkSize); + this.windowBits = 5; + + zlib.inflateInit(this.strm, this.windowBits); + }; + + Inflate.prototype = { + inflate: function (data, flush, expected) { + this.strm.input = data; + this.strm.avail_in = this.strm.input.length; + this.strm.next_in = 0; + this.strm.next_out = 0; + + // resize our output buffer if it's too small + // (we could just use multiple chunks, but that would cause an extra + // allocation each time to flatten the chunks) + if (expected > this.chunkSize) { + this.chunkSize = expected; + this.strm.output = new Uint8Array(this.chunkSize); + } + + this.strm.avail_out = this.chunkSize; + + zlib.inflate(this.strm, flush); + + return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out); + }, + + reset: function () { + zlib.inflateReset(this.strm); + } + }; + + return { Inflate: Inflate }; +}); diff --git a/karma.conf.js b/karma.conf.js index 5f3c20b9..5b01221b 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -108,34 +108,15 @@ module.exports = function(config) { // list of files / patterns to load in the browser (loaded in order) files: [ + 'node_modules/requirejs/require.js', + 'tests/test-main.js', 'tests/fake.*.js', 'tests/assertions.js', - 'core/util.js', // load first to avoid issues, since methods are called immediately - //'../core/*.js', - 'core/base64.js', - 'core/input/keysym.js', - 'core/input/keysymdef.js', - 'core/input/xtscancodes.js', - 'core/input/util.js', - 'core/input/devices.js', - 'core/websock.js', - 'core/rfb.js', - 'core/des.js', - 'core/display.js', - 'core/inflator.js', - 'tests/test.*.js' - ], - - client: { - mocha: { - 'ui': 'bdd' - } - }, - - // list of files to exclude - exclude: [ - '../tests/playback.js', - '../app/ui.js' + 'tests/test.*.js', + // Only packaged, not included in browser as RequireJS will + // do the actual loading + {pattern: 'core/*.js', included: false}, + {pattern: 'core/input/*.js', included: false}, ], customLaunchers: customLaunchers, diff --git a/package.json b/package.json index 52f76f6d..dd1a1e04 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "open": "^0.0.5", "phantomjs-prebuilt": "^2.1.13", "po2json": "*", + "requirejs": "*", "sinon": "^1.17.6", "sinon-chai": "^2.8.0", "spooky": "^0.2.5", diff --git a/po/po2js b/po/po2js index 972f0b2c..88db9e11 100755 --- a/po/po2js +++ b/po/po2js @@ -40,7 +40,10 @@ var output = " * DO NOT EDIT!\n" + " */\n" + "\n" + -"Language = {\n"; +"\"use strict\";\n" + +"\n" + +"define(function() {\n" + +"return {\n"; for (msgid in data) { if (msgid === "") @@ -52,5 +55,6 @@ for (msgid in data) { } output += "};\n"; +output += "});\n"; fs.writeFileSync(opt.argv[1], output); diff --git a/tests/run_from_console.js b/tests/run_from_console.js index a743d47a..fa332c1e 100755 --- a/tests/run_from_console.js +++ b/tests/run_from_console.js @@ -99,6 +99,8 @@ if (program.autoInject) { template.header += "\n" + template.script_tag(get_path('node_modules/mocha/mocha.js')); template.header += "\n" + template.script_tag(get_path('node_modules/sinon/pkg/sinon.js')); template.header += "\n" + template.script_tag(get_path('node_modules/sinon-chai/lib/sinon-chai.js')); + template.header += "\n" + template.script_tag(get_path('node_modules/requirejs/require.js')); + template.header += "\n"; template.header += "\n"; diff --git a/tests/test-main.js b/tests/test-main.js new file mode 100644 index 00000000..652137a4 --- /dev/null +++ b/tests/test-main.js @@ -0,0 +1,5 @@ +requirejs.config({ + // Karma serves files under /base + baseUrl: '/base' +}); + diff --git a/tests/test.base64.js b/tests/test.base64.js index b2646a0f..44655f2a 100644 --- a/tests/test.base64.js +++ b/tests/test.base64.js @@ -1,10 +1,19 @@ -// requires local modules: base64 var assert = chai.assert; var expect = chai.expect; -describe('Base64 Tools', function() { +describe('Base64 Tools', function(done) { "use strict"; + var Base64; + + before(function (done) { + requirejs(["core/base64"], + function (b) { + Base64 = b; + done(); + }); + }); + var BIN_ARR = new Array(256); for (var i = 0; i < 256; i++) { BIN_ARR[i] = i; diff --git a/tests/test.display.js b/tests/test.display.js index 5f4eed12..b3c78d04 100644 --- a/tests/test.display.js +++ b/tests/test.display.js @@ -1,9 +1,22 @@ -// requires local modules: util, base64, display // requires test modules: assertions /* jshint expr: true */ var expect = chai.expect; describe('Display/Canvas Helper', function () { + "use strict"; + + var Util, Base64, Display; + + before(function (done) { + requirejs(["core/util", "core/base64", "core/display"], + function (u, b, d) { + Util = u; + Base64 = b; + Display = d.Display; + done(); + }); + }); + var checked_data = [ 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, diff --git a/tests/test.helper.js b/tests/test.helper.js index caa10a66..482369fe 100644 --- a/tests/test.helper.js +++ b/tests/test.helper.js @@ -1,10 +1,20 @@ -// requires local modules: input/keysym, input/keysymdef, input/util - var assert = chai.assert; var expect = chai.expect; describe('Helpers', function() { "use strict"; + + var keysyms, KeyboardUtil; + + before(function (done) { + requirejs(["core/input/keysymdef", "core/input/util"], + function (k, u) { + keysyms = k; + KeyboardUtil = u; + done(); + }); + }); + describe('keysymFromKeyCode', function() { it('should map known keycodes to keysyms', function() { expect(KeyboardUtil.keysymFromKeyCode(0x41, false), 'a').to.be.equal(0x61); diff --git a/tests/test.keyboard.js b/tests/test.keyboard.js index 0019be9a..c098e9cc 100644 --- a/tests/test.keyboard.js +++ b/tests/test.keyboard.js @@ -1,10 +1,21 @@ -// requires local modules: input/devices, input/util, input/keysymdef, input/keysym var assert = chai.assert; var expect = chai.expect; /* jshint newcap: false, expr: true */ describe('Key Event Pipeline Stages', function() { "use strict"; + + var keysyms, KeyboardUtil; + + before(function (done) { + requirejs(["core/input/keysymdef", "core/input/util"], + function (k, u) { + keysyms = k; + KeyboardUtil = u; + done(); + }); + }); + describe('Decode Keyboard Events', function() { it('should pass events to the next stage', function(done) { KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { diff --git a/tests/test.rfb.js b/tests/test.rfb.js index 229cfe58..a1a1008a 100644 --- a/tests/test.rfb.js +++ b/tests/test.rfb.js @@ -1,9 +1,10 @@ -// requires local modules: util, websock, rfb, input/util, input/keysym, input/keysymdef, input/devices, inflator, des, display // requires test modules: fake.websocket, assertions /* jshint expr: true */ var assert = chai.assert; var expect = chai.expect; +var RFB; + function make_rfb (extra_opts) { if (!extra_opts) { extra_opts = {}; @@ -34,9 +35,21 @@ var push32 = function (arr, num) { describe('Remote Frame Buffer Protocol Client', function() { "use strict"; + before(FakeWebSocket.replace); after(FakeWebSocket.restore); + var Websock; + + before(function (done) { + requirejs(["core/rfb", "core/websock"], + function (r, w) { + RFB = r.RFB; + Websock = w.Websock; + done(); + }); + }); + before(function () { this.clock = sinon.useFakeTimers(); // Use a single set of buffers instead of reallocating to diff --git a/tests/test.util.js b/tests/test.util.js index 60cdb582..55ec5e95 100644 --- a/tests/test.util.js +++ b/tests/test.util.js @@ -1,4 +1,3 @@ -// requires local modules: util /* jshint expr: true */ var assert = chai.assert; @@ -7,6 +6,16 @@ var expect = chai.expect; describe('Utils', function() { "use strict"; + var Util; + + before(function (done) { + requirejs(["core/util"], + function (u) { + Util = u; + done(); + }); + }); + describe('logging functions', function () { beforeEach(function () { sinon.spy(console, 'log'); @@ -57,7 +66,7 @@ describe('Utils', function() { }); describe('language selection', function () { - var origNavigator; + var origNavigator, origRequire; beforeEach(function () { // window.navigator is a protected read-only property in many // environments, so we need to redefine it whilst running these @@ -77,8 +86,13 @@ describe('Utils', function() { } window.navigator.languages = []; + + // Prevent the code from trying to actually load translations + origRequire = require; + require = function (mods, func) { func([]); }; }); afterEach(function () { + require = origRequire; Object.defineProperty(window, "navigator", origNavigator); }); @@ -87,37 +101,37 @@ describe('Utils', function() { }); it('should use English if no user language matches', function() { window.navigator.languages = ["nl", "de"]; - Util.Localisation.setup(["es", "fr"]); + Util.Localisation.setup(["es", "fr"], "."); expect(Util.Localisation.language).to.equal('en'); }); it('should use the most preferred user language', function() { window.navigator.languages = ["nl", "de", "fr"]; - Util.Localisation.setup(["es", "fr", "de"]); + Util.Localisation.setup(["es", "fr", "de"], "."); expect(Util.Localisation.language).to.equal('de'); }); it('should prefer sub-languages languages', function() { window.navigator.languages = ["pt-BR"]; - Util.Localisation.setup(["pt", "pt-BR"]); + Util.Localisation.setup(["pt", "pt-BR"], "."); expect(Util.Localisation.language).to.equal('pt-BR'); }); it('should fall back to language "parents"', function() { window.navigator.languages = ["pt-BR"]; - Util.Localisation.setup(["fr", "pt", "de"]); + Util.Localisation.setup(["fr", "pt", "de"], "."); expect(Util.Localisation.language).to.equal('pt'); }); it('should not use specific language when user asks for a generic language', function() { window.navigator.languages = ["pt", "de"]; - Util.Localisation.setup(["fr", "pt-BR", "de"]); + Util.Localisation.setup(["fr", "pt-BR", "de"], "."); expect(Util.Localisation.language).to.equal('de'); }); it('should handle underscore as a separator', function() { window.navigator.languages = ["pt-BR"]; - Util.Localisation.setup(["pt_BR"]); + Util.Localisation.setup(["pt_BR"], "."); expect(Util.Localisation.language).to.equal('pt_BR'); }); it('should handle difference in case', function() { window.navigator.languages = ["pt-br"]; - Util.Localisation.setup(["pt-BR"]); + Util.Localisation.setup(["pt-BR"], "."); expect(Util.Localisation.language).to.equal('pt-BR'); }); }); diff --git a/tests/test.websock.js b/tests/test.websock.js index f708e04b..5899eb49 100644 --- a/tests/test.websock.js +++ b/tests/test.websock.js @@ -1,4 +1,3 @@ -// requires local modules: websock, util // requires test modules: fake.websocket, assertions /* jshint expr: true */ var assert = chai.assert; @@ -7,6 +6,16 @@ var expect = chai.expect; describe('Websock', function() { "use strict"; + var Websock; + + before(function (done) { + requirejs(["core/websock"], + function (w) { + Websock = w.Websock; + done(); + }); + }); + describe('Queue methods', function () { var sock; var RQ_TEMPLATE = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]); diff --git a/utils/parse.js b/utils/parse.js index fd79b12b..1668f5d8 100644 --- a/utils/parse.js +++ b/utils/parse.js @@ -80,12 +80,15 @@ var out = "// This file describes mappings from Unicode codepoints to the keysym "// (and optionally, key names) expected by the RFB protocol\n" + "// How this file was generated:\n" + "// " + process.argv.join(" ") + "\n" + -"var keysyms = (function(){\n" + -" \"use strict\";\n" + +"\n" + +"\"use strict\";\n" + +"\n" + +"define(function () {\n" + " var keynames = {keysyms};\n" + " var codepoints = {codepoints};\n" + "\n" + " function lookup(k) { return k ? {keysym: k, keyname: keynames ? keynames[k] : k} : undefined; }\n" + +"\n" + " return {\n" + " fromUnicode : function(u) {\n" + " var keysym = codepoints[u];\n" + @@ -96,7 +99,7 @@ var out = "// This file describes mappings from Unicode codepoints to the keysym " },\n" + " lookup : lookup\n" + " };\n" + -"})();\n"; +"});\n"; out = out.replace('{keysyms}', use_keynames ? JSON.stringify(keysyms) : "null"); out = out.replace('{codepoints}', JSON.stringify(codepoints)); diff --git a/vnc.html b/vnc.html index 5e241a2a..d9a32391 100644 --- a/vnc.html +++ b/vnc.html @@ -55,10 +55,7 @@ - + @@ -314,12 +311,5 @@ - - - - - - - diff --git a/vnc_auto.html b/vnc_auto.html index e4fc4676..84291692 100644 --- a/vnc_auto.html +++ b/vnc_auto.html @@ -38,12 +38,7 @@ - - - + @@ -74,148 +69,143 @@