webutil.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * noVNC: HTML5 VNC client
  3. * Copyright (C) 2019 The noVNC Authors
  4. * Licensed under MPL 2.0 (see LICENSE.txt)
  5. *
  6. * See README.md for usage and integration instructions.
  7. */
  8. import * as Log from '../core/util/logging.js';
  9. // init log level reading the logging HTTP param
  10. export function initLogging(level) {
  11. "use strict";
  12. if (typeof level !== "undefined") {
  13. Log.initLogging(level);
  14. } else {
  15. const param = document.location.href.match(/logging=([A-Za-z0-9._-]*)/);
  16. Log.initLogging(param || undefined);
  17. }
  18. }
  19. // Read a query string variable
  20. // A URL with a query parameter can look like this (But will most probably get logged on the http server):
  21. // https://www.example.com?myqueryparam=myvalue
  22. //
  23. // For privacy (Using a hastag #, the parameters will not be sent to the server)
  24. // the url can be requested in the following way:
  25. // https://www.example.com#myqueryparam=myvalue&password=secretvalue
  26. //
  27. // Even Mixing public and non public parameters will work:
  28. // https://www.example.com?nonsecretparam=example.com#password=secretvalue
  29. export function getQueryVar(name, defVal) {
  30. "use strict";
  31. const re = new RegExp('.*[?&]' + name + '=([^&#]*)'),
  32. match = document.location.href.match(re);
  33. if (typeof defVal === 'undefined') { defVal = null; }
  34. if (match) {
  35. return decodeURIComponent(match[1]);
  36. }
  37. return defVal;
  38. }
  39. // Read a hash fragment variable
  40. export function getHashVar(name, defVal) {
  41. "use strict";
  42. const re = new RegExp('.*[&#]' + name + '=([^&]*)'),
  43. match = document.location.hash.match(re);
  44. if (typeof defVal === 'undefined') { defVal = null; }
  45. if (match) {
  46. return decodeURIComponent(match[1]);
  47. }
  48. return defVal;
  49. }
  50. // Read a variable from the fragment or the query string
  51. // Fragment takes precedence
  52. export function getConfigVar(name, defVal) {
  53. "use strict";
  54. const val = getHashVar(name);
  55. if (val === null) {
  56. return getQueryVar(name, defVal);
  57. }
  58. return val;
  59. }
  60. /*
  61. * Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html
  62. */
  63. // No days means only for this browser session
  64. export function createCookie(name, value, days) {
  65. "use strict";
  66. let date, expires;
  67. if (days) {
  68. date = new Date();
  69. date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
  70. expires = "; expires=" + date.toGMTString();
  71. } else {
  72. expires = "";
  73. }
  74. let secure;
  75. if (document.location.protocol === "https:") {
  76. secure = "; secure";
  77. } else {
  78. secure = "";
  79. }
  80. document.cookie = name + "=" + value + expires + "; path=/" + secure;
  81. }
  82. export function readCookie(name, defaultValue) {
  83. "use strict";
  84. const nameEQ = name + "=";
  85. const ca = document.cookie.split(';');
  86. for (let i = 0; i < ca.length; i += 1) {
  87. let c = ca[i];
  88. while (c.charAt(0) === ' ') {
  89. c = c.substring(1, c.length);
  90. }
  91. if (c.indexOf(nameEQ) === 0) {
  92. return c.substring(nameEQ.length, c.length);
  93. }
  94. }
  95. return (typeof defaultValue !== 'undefined') ? defaultValue : null;
  96. }
  97. export function eraseCookie(name) {
  98. "use strict";
  99. createCookie(name, "", -1);
  100. }
  101. /*
  102. * Setting handling.
  103. */
  104. let settings = {};
  105. export function initSettings() {
  106. if (!window.chrome || !window.chrome.storage) {
  107. settings = {};
  108. return Promise.resolve();
  109. }
  110. return new Promise(resolve => window.chrome.storage.sync.get(resolve))
  111. .then((cfg) => { settings = cfg; });
  112. }
  113. // Update the settings cache, but do not write to permanent storage
  114. export function setSetting(name, value) {
  115. settings[name] = value;
  116. }
  117. // No days means only for this browser session
  118. export function writeSetting(name, value) {
  119. "use strict";
  120. if (settings[name] === value) return;
  121. settings[name] = value;
  122. if (window.chrome && window.chrome.storage) {
  123. window.chrome.storage.sync.set(settings);
  124. } else {
  125. localStorageSet(name, value);
  126. }
  127. }
  128. export function readSetting(name, defaultValue) {
  129. "use strict";
  130. let value;
  131. if ((name in settings) || (window.chrome && window.chrome.storage)) {
  132. value = settings[name];
  133. } else {
  134. value = localStorageGet(name);
  135. settings[name] = value;
  136. }
  137. if (typeof value === "undefined") {
  138. value = null;
  139. }
  140. if (value === null && typeof defaultValue !== "undefined") {
  141. return defaultValue;
  142. }
  143. return value;
  144. }
  145. export function eraseSetting(name) {
  146. "use strict";
  147. // Deleting here means that next time the setting is read when using local
  148. // storage, it will be pulled from local storage again.
  149. // If the setting in local storage is changed (e.g. in another tab)
  150. // between this delete and the next read, it could lead to an unexpected
  151. // value change.
  152. delete settings[name];
  153. if (window.chrome && window.chrome.storage) {
  154. window.chrome.storage.sync.remove(name);
  155. } else {
  156. localStorageRemove(name);
  157. }
  158. }
  159. let loggedMsgs = [];
  160. function logOnce(msg, level = "warn") {
  161. if (!loggedMsgs.includes(msg)) {
  162. switch (level) {
  163. case "error":
  164. Log.Error(msg);
  165. break;
  166. case "warn":
  167. Log.Warn(msg);
  168. break;
  169. case "debug":
  170. Log.Debug(msg);
  171. break;
  172. default:
  173. Log.Info(msg);
  174. }
  175. loggedMsgs.push(msg);
  176. }
  177. }
  178. let cookiesMsg = "Couldn't access noVNC settings, are cookies disabled?";
  179. function localStorageGet(name) {
  180. let r;
  181. try {
  182. r = localStorage.getItem(name);
  183. } catch (e) {
  184. if (e instanceof DOMException) {
  185. logOnce(cookiesMsg);
  186. logOnce("'localStorage.getItem(" + name + ")' failed: " + e,
  187. "debug");
  188. } else {
  189. throw e;
  190. }
  191. }
  192. return r;
  193. }
  194. function localStorageSet(name, value) {
  195. try {
  196. localStorage.setItem(name, value);
  197. } catch (e) {
  198. if (e instanceof DOMException) {
  199. logOnce(cookiesMsg);
  200. logOnce("'localStorage.setItem(" + name + "," + value +
  201. ")' failed: " + e, "debug");
  202. } else {
  203. throw e;
  204. }
  205. }
  206. }
  207. function localStorageRemove(name) {
  208. try {
  209. localStorage.removeItem(name);
  210. } catch (e) {
  211. if (e instanceof DOMException) {
  212. logOnce(cookiesMsg);
  213. logOnce("'localStorage.removeItem(" + name + ")' failed: " + e,
  214. "debug");
  215. } else {
  216. throw e;
  217. }
  218. }
  219. }