]> git.proxmox.com Git - mirror_novnc.git/blob - app/webutil.js
feat: add French localization strings
[mirror_novnc.git] / app / webutil.js
1 /*
2 * noVNC: HTML5 VNC client
3 * Copyright (C) 2012 Joel Martin
4 * Copyright (C) 2013 NTT corp.
5 * Licensed under MPL 2.0 (see LICENSE.txt)
6 *
7 * See README.md for usage and integration instructions.
8 */
9
10 import { init_logging as main_init_logging } from '../core/util/logging.js';
11
12 // init log level reading the logging HTTP param
13 export function init_logging (level) {
14 "use strict";
15 if (typeof level !== "undefined") {
16 main_init_logging(level);
17 } else {
18 const param = document.location.href.match(/logging=([A-Za-z0-9._-]*)/);
19 main_init_logging(param || undefined);
20 }
21 }
22
23 // Read a query string variable
24 export function getQueryVar (name, defVal) {
25 "use strict";
26 const re = new RegExp('.*[?&]' + name + '=([^&#]*)'),
27 match = document.location.href.match(re);
28 if (typeof defVal === 'undefined') { defVal = null; }
29
30 if (match) {
31 return decodeURIComponent(match[1]);
32 }
33
34 return defVal;
35 }
36
37 // Read a hash fragment variable
38 export function getHashVar (name, defVal) {
39 "use strict";
40 const re = new RegExp('.*[&#]' + name + '=([^&]*)'),
41 match = document.location.hash.match(re);
42 if (typeof defVal === 'undefined') { defVal = null; }
43
44 if (match) {
45 return decodeURIComponent(match[1]);
46 }
47
48 return defVal;
49 }
50
51 // Read a variable from the fragment or the query string
52 // Fragment takes precedence
53 export function getConfigVar (name, defVal) {
54 "use strict";
55 const val = getHashVar(name);
56
57 if (val === null) {
58 return getQueryVar(name, defVal);
59 }
60
61 return val;
62 }
63
64 /*
65 * Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html
66 */
67
68 // No days means only for this browser session
69 export function createCookie (name, value, days) {
70 "use strict";
71 let date, expires;
72 if (days) {
73 date = new Date();
74 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
75 expires = "; expires=" + date.toGMTString();
76 } else {
77 expires = "";
78 }
79
80 let secure;
81 if (document.location.protocol === "https:") {
82 secure = "; secure";
83 } else {
84 secure = "";
85 }
86 document.cookie = name + "=" + value + expires + "; path=/" + secure;
87 }
88
89 export function readCookie (name, defaultValue) {
90 "use strict";
91 const nameEQ = name + "=";
92 const ca = document.cookie.split(';');
93
94 for (let i = 0; i < ca.length; i += 1) {
95 let c = ca[i];
96 while (c.charAt(0) === ' ') {
97 c = c.substring(1, c.length);
98 }
99 if (c.indexOf(nameEQ) === 0) {
100 return c.substring(nameEQ.length, c.length);
101 }
102 }
103
104 return (typeof defaultValue !== 'undefined') ? defaultValue : null;
105 }
106
107 export function eraseCookie (name) {
108 "use strict";
109 createCookie(name, "", -1);
110 }
111
112 /*
113 * Setting handling.
114 */
115
116 let settings = {};
117
118 export function initSettings (callback /*, ...callbackArgs */) {
119 "use strict";
120 const callbackArgs = Array.prototype.slice.call(arguments, 1);
121 if (window.chrome && window.chrome.storage) {
122 window.chrome.storage.sync.get((cfg) => {
123 settings = cfg;
124 if (callback) {
125 callback.apply(this, callbackArgs);
126 }
127 });
128 } else {
129 settings = {};
130 if (callback) {
131 callback.apply(this, callbackArgs);
132 }
133 }
134 }
135
136 // Update the settings cache, but do not write to permanent storage
137 export function setSetting (name, value) {
138 settings[name] = value;
139 }
140
141 // No days means only for this browser session
142 export function writeSetting (name, value) {
143 "use strict";
144 if (settings[name] === value) return;
145 settings[name] = value;
146 if (window.chrome && window.chrome.storage) {
147 window.chrome.storage.sync.set(settings);
148 } else {
149 localStorage.setItem(name, value);
150 }
151 }
152
153 export function readSetting (name, defaultValue) {
154 "use strict";
155 let value;
156 if ((name in settings) || (window.chrome && window.chrome.storage)) {
157 value = settings[name];
158 } else {
159 value = localStorage.getItem(name);
160 settings[name] = value;
161 }
162 if (typeof value === "undefined") {
163 value = null;
164 }
165
166 if (value === null && typeof defaultValue !== "undefined") {
167 return defaultValue;
168 }
169
170 return value;
171 }
172
173 export function eraseSetting (name) {
174 "use strict";
175 // Deleting here means that next time the setting is read when using local
176 // storage, it will be pulled from local storage again.
177 // If the setting in local storage is changed (e.g. in another tab)
178 // between this delete and the next read, it could lead to an unexpected
179 // value change.
180 delete settings[name];
181 if (window.chrome && window.chrome.storage) {
182 window.chrome.storage.sync.remove(name);
183 } else {
184 localStorage.removeItem(name);
185 }
186 }
187
188 export function injectParamIfMissing (path, param, value) {
189 // force pretend that we're dealing with a relative path
190 // (assume that we wanted an extra if we pass one in)
191 path = "/" + path;
192
193 const elem = document.createElement('a');
194 elem.href = path;
195
196 const param_eq = encodeURIComponent(param) + "=";
197 let query;
198 if (elem.search) {
199 query = elem.search.slice(1).split('&');
200 } else {
201 query = [];
202 }
203
204 if (!query.some(v => v.startsWith(param_eq))) {
205 query.push(param_eq + encodeURIComponent(value));
206 elem.search = "?" + query.join("&");
207 }
208
209 // some browsers (e.g. IE11) may occasionally omit the leading slash
210 // in the elem.pathname string. Handle that case gracefully.
211 if (elem.pathname.charAt(0) == "/") {
212 return elem.pathname.slice(1) + elem.search + elem.hash;
213 }
214
215 return elem.pathname + elem.search + elem.hash;
216 }
217
218 // sadly, we can't use the Fetch API until we decide to drop
219 // IE11 support or polyfill promises and fetch in IE11.
220 // resolve will receive an object on success, while reject
221 // will receive either an event or an error on failure.
222 export function fetchJSON(path, resolve, reject) {
223 // NB: IE11 doesn't support JSON as a responseType
224 const req = new XMLHttpRequest();
225 req.open('GET', path);
226
227 req.onload = () => {
228 if (req.status === 200) {
229 let resObj;
230 try {
231 resObj = JSON.parse(req.responseText);
232 } catch (err) {
233 reject(err);
234 }
235 resolve(resObj);
236 } else {
237 reject(new Error("XHR got non-200 status while trying to load '" + path + "': " + req.status));
238 }
239 };
240
241 req.onerror = evt => reject(new Error("XHR encountered an error while trying to load '" + path + "': " + evt.message));
242
243 req.ontimeout = evt => reject(new Error("XHR timed out while trying to load '" + path + "'"));
244
245 req.send();
246 }