Rev 424 | Rev 456 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5 | daniel-mar | 1 | /* |
2 | * OIDplus 2.0 |
||
3 | * Copyright 2019 Daniel Marschall, ViaThinkSoft |
||
4 | * |
||
5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
||
6 | * you may not use this file except in compliance with the License. |
||
7 | * You may obtain a copy of the License at |
||
8 | * |
||
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
||
10 | * |
||
11 | * Unless required by applicable law or agreed to in writing, software |
||
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
||
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||
14 | * See the License for the specific language governing permissions and |
||
15 | * limitations under the License. |
||
16 | */ |
||
17 | |||
362 | daniel-mar | 18 | // DEFAULT_LANGUAGE will be set by setup.js.php |
19 | // language_messages will be set by setup.js.php |
||
20 | // language_tblprefix will be set by setup.js.php |
||
21 | |||
149 | daniel-mar | 22 | min_password_length = 10; // see also plugins/publicPages/092_forgot_password_admin/script.js |
421 | daniel-mar | 23 | password_salt_length = 10; |
80 | daniel-mar | 24 | |
2 | daniel-mar | 25 | function btoa(bin) { |
26 | var tableStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
||
27 | var table = tableStr.split(""); |
||
28 | for (var i = 0, j = 0, len = bin.length / 3, base64 = []; i < len; ++i) { |
||
29 | var a = bin.charCodeAt(j++), b = bin.charCodeAt(j++), c = bin.charCodeAt(j++); |
||
362 | daniel-mar | 30 | if ((a | b | c) > 255) throw new Error(_L('String contains an invalid character')); |
2 | daniel-mar | 31 | base64[base64.length] = table[a >> 2] + table[((a << 4) & 63) | (b >> 4)] + |
32 | (isNaN(b) ? "=" : table[((b << 2) & 63) | (c >> 6)]) + |
||
33 | (isNaN(b + c) ? "=" : table[c & 63]); |
||
34 | } |
||
35 | return base64.join(""); |
||
36 | }; |
||
37 | |||
38 | function hexToBase64(str) { |
||
39 | return btoa(String.fromCharCode.apply(null, |
||
40 | str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" "))); |
||
41 | } |
||
42 | |||
43 | function b64EncodeUnicode(str) { |
||
44 | // first we use encodeURIComponent to get percent-encoded UTF-8, |
||
45 | // then we convert the percent encodings into raw bytes which |
||
46 | // can be fed into btoa. |
||
47 | return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, |
||
48 | function toSolidBytes(match, p1) { |
||
49 | return String.fromCharCode('0x' + p1); |
||
50 | })); |
||
51 | } |
||
52 | |||
53 | function generateRandomString(length) { |
||
54 | var charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", |
||
55 | retVal = ""; |
||
56 | for (var i = 0, n = charset.length; i < length; ++i) { |
||
57 | retVal += charset.charAt(Math.floor(Math.random() * n)); |
||
58 | } |
||
59 | return retVal; |
||
60 | } |
||
61 | |||
62 | String.prototype.replaceAll = function(search, replacement) { |
||
63 | var target = this; |
||
64 | return target.replace(new RegExp(search, 'g'), replacement); |
||
65 | }; |
||
66 | |||
421 | daniel-mar | 67 | function adminGeneratePassword(password) { |
68 | var salt = generateRandomString(password_salt_length); |
||
69 | return salt+'$'+hexToBase64(sha3_512(salt+password)); |
||
70 | } |
||
71 | |||
2 | daniel-mar | 72 | function rebuild() { |
73 | var error = false; |
||
74 | |||
150 | daniel-mar | 75 | if (document.getElementById('config') == null) return; |
76 | |||
81 | daniel-mar | 77 | // Check 1: Has the password the correct length? |
78 | if (document.getElementById('admin_password').value.length < min_password_length) |
||
79 | { |
||
362 | daniel-mar | 80 | document.getElementById('password_warn').innerHTML = '<font color="red">'+_L('Password must be at least %1 characters long',min_password_length)+'</font>'; |
81 | document.getElementById('config').innerHTML = '<b><?php</b><br><br><i>// ERROR: Password must be at least '+min_password_length+' characters long</i>'; // do not translate |
||
81 | daniel-mar | 82 | error = true; |
83 | } else { |
||
84 | document.getElementById('password_warn').innerHTML = ''; |
||
85 | } |
||
86 | |||
87 | // Check 2: Do the passwords match? |
||
2 | daniel-mar | 88 | if (document.getElementById('admin_password').value != document.getElementById('admin_password2').value) { |
362 | daniel-mar | 89 | document.getElementById('password_warn2').innerHTML = '<font color="red">'+_L('The passwords do not match!')+'</font>'; |
2 | daniel-mar | 90 | error = true; |
91 | } else { |
||
92 | document.getElementById('password_warn2').innerHTML = ''; |
||
93 | } |
||
94 | |||
150 | daniel-mar | 95 | // Check 3: Ask the database plugins for verification of their data |
96 | for (var i = 0; i < rebuild_callbacks.length; i++) { |
||
97 | var f = rebuild_callbacks[i]; |
||
98 | if (!f()) { |
||
99 | error = true; |
||
100 | } |
||
2 | daniel-mar | 101 | } |
81 | daniel-mar | 102 | |
149 | daniel-mar | 103 | // Continue |
81 | daniel-mar | 104 | if (!error) |
105 | { |
||
150 | daniel-mar | 106 | var e = document.getElementById("db_plugin"); |
107 | var strPlugin = e.options[e.selectedIndex].value; |
||
108 | |||
2 | daniel-mar | 109 | document.getElementById('config').innerHTML = '<b><?php</b><br><br>' + |
362 | daniel-mar | 110 | '<i>// To renew this file, please run setup/ in your browser.</i><br>' + // do not translate |
111 | '<i>// If you don\'t want to run setup again, you can also change most of the settings directly in this file.</i><br>' + // do not translate |
||
2 | daniel-mar | 112 | '<br>' + |
261 | daniel-mar | 113 | 'OIDplus::baseConfig()->setValue(\'CONFIG_VERSION\', 2.1);<br>' + |
2 | daniel-mar | 114 | '<br>' + |
150 | daniel-mar | 115 | // Passwords are Base64 encoded to avoid that passwords can be read upon first sight, |
294 | daniel-mar | 116 | // e.g. if collegues are looking over your shoulder while you accidently open (and quickly close) userdata/baseconfig/config.inc.php |
421 | daniel-mar | 117 | 'OIDplus::baseConfig()->setValue(\'ADMIN_PASSWORD\', \'' + adminGeneratePassword(document.getElementById('admin_password').value) + '\'); // salted, base64 encoded SHA3-512 hash<br>' + |
2 | daniel-mar | 118 | '<br>' + |
261 | daniel-mar | 119 | 'OIDplus::baseConfig()->setValue(\'DATABASE_PLUGIN\', \''+strPlugin+'\');<br>'; |
150 | daniel-mar | 120 | for (var i = 0; i < rebuild_config_callbacks.length; i++) { |
121 | var f = rebuild_config_callbacks[i]; |
||
122 | var cont = f(); |
||
123 | if (cont) { |
||
124 | document.getElementById('config').innerHTML = document.getElementById('config').innerHTML + cont; |
||
125 | } |
||
126 | } |
||
239 | daniel-mar | 127 | document.getElementById('config').innerHTML = document.getElementById('config').innerHTML + |
2 | daniel-mar | 128 | '<br>' + |
261 | daniel-mar | 129 | 'OIDplus::baseConfig()->setValue(\'TABLENAME_PREFIX\', \''+document.getElementById('tablename_prefix').value+'\');<br>' + |
2 | daniel-mar | 130 | '<br>' + |
261 | daniel-mar | 131 | 'OIDplus::baseConfig()->setValue(\'SERVER_SECRET\', \''+generateRandomString(32)+'\');<br>' + |
2 | daniel-mar | 132 | '<br>' + |
261 | daniel-mar | 133 | 'OIDplus::baseConfig()->setValue(\'RECAPTCHA_ENABLED\', '+(document.getElementById('recaptcha_enabled').checked ? 'true' : 'false')+');<br>' + |
134 | 'OIDplus::baseConfig()->setValue(\'RECAPTCHA_PUBLIC\', \''+document.getElementById('recaptcha_public').value+'\');<br>' + |
||
135 | 'OIDplus::baseConfig()->setValue(\'RECAPTCHA_PRIVATE\', \''+document.getElementById('recaptcha_private').value+'\');<br>' + |
||
80 | daniel-mar | 136 | '<br>' + |
261 | daniel-mar | 137 | 'OIDplus::baseConfig()->setValue(\'ENFORCE_SSL\', '+document.getElementById('enforce_ssl').value+');<br>'; |
2 | daniel-mar | 138 | |
139 | document.getElementById('config').innerHTML = document.getElementById('config').innerHTML.replaceAll(' ', ' '); |
||
140 | } |
||
141 | |||
142 | // In case something is not good, do not allow the user to continue with the other configuration steps: |
||
143 | if (error) { |
||
150 | daniel-mar | 144 | document.getElementById('step2').style.display = "None"; |
145 | document.getElementById('step3').style.display = "None"; |
||
146 | document.getElementById('step4').style.display = "None"; |
||
2 | daniel-mar | 147 | } else { |
150 | daniel-mar | 148 | document.getElementById('step2').style.display = "Block"; |
149 | document.getElementById('step3').style.display = "Block"; |
||
150 | document.getElementById('step4').style.display = "Block"; |
||
2 | daniel-mar | 151 | } |
152 | } |
||
362 | daniel-mar | 153 | |
154 | function RemoveLastDirectoryPartOf(the_url) { |
||
155 | var the_arr = the_url.split('/'); |
||
156 | if (the_arr.pop() == '') the_arr.pop(); |
||
157 | return( the_arr.join('/') ); |
||
158 | } |
||
159 | |||
160 | function checkAccess(dir) { |
||
161 | var url = '../' + dir; |
||
162 | var visibleUrl = RemoveLastDirectoryPartOf(window.location.href) + '/' + dir; // xhr.responseURL not available in IE |
||
163 | |||
164 | var xhr = new XMLHttpRequest(); |
||
165 | xhr.onreadystatechange = function() { |
||
166 | if (xhr.readyState === 4) { |
||
167 | if (xhr.status === 200) { |
||
168 | document.getElementById('systemCheckCaption').style.display = 'block'; |
||
363 | daniel-mar | 169 | document.getElementById('dirAccessWarning').innerHTML = document.getElementById('dirAccessWarning').innerHTML + _L('Attention: The following directory is world-readable: %1 ! You need to configure your web server to restrict access to this directory! (For Apache see <i>.htaccess</i>, for Microsoft IIS see <i>web.config</i>, for Nginx see <i>nginx.conf</i>).','<a target="_blank" href="'+url+'">'+visibleUrl+'</a>') + '<br>'; |
362 | daniel-mar | 170 | } |
171 | } |
||
172 | }; |
||
173 | |||
174 | xhr.open('GET', url); |
||
175 | xhr.send(); |
||
176 | } |
||
177 | |||
178 | function dbplugin_changed() { |
||
179 | var e = document.getElementById("db_plugin"); |
||
180 | var strPlugin = e.options[e.selectedIndex].value; |
||
181 | |||
182 | for (var i = 0; i < plugin_combobox_change_callbacks.length; i++) { |
||
183 | var f = plugin_combobox_change_callbacks[i]; |
||
184 | f(strPlugin); |
||
185 | } |
||
186 | |||
187 | rebuild(); |
||
188 | } |
||
189 | |||
190 | function performAccessCheck() { |
||
191 | document.getElementById("dirAccessWarning").innerHTML = ""; |
||
192 | checkAccess("userdata/index.html"); |
||
193 | checkAccess("dev/index.html"); |
||
194 | checkAccess("includes/index.html"); |
||
448 | daniel-mar | 195 | checkAccess("setup/includes/index.html"); |
362 | daniel-mar | 196 | //checkAccess("plugins/publicPages/100_whois/whois/cli/index.html"); |
197 | } |
||
198 | |||
199 | function setupOnLoad() { |
||
200 | rebuild(); |
||
201 | dbplugin_changed(); |
||
202 | performAccessCheck(); |
||
203 | } |
||
204 | |||
205 | function getCookie(cname) { |
||
206 | // Source: https://www.w3schools.com/js/js_cookies.asp |
||
207 | var name = cname + "="; |
||
208 | var decodedCookie = decodeURIComponent(document.cookie); |
||
209 | var ca = decodedCookie.split(';'); |
||
210 | for(var i = 0; i <ca.length; i++) { |
||
211 | var c = ca[i]; |
||
212 | while (c.charAt(0) == ' ') { |
||
213 | c = c.substring(1); |
||
214 | } |
||
215 | if (c.indexOf(name) == 0) { |
||
216 | return c.substring(name.length, c.length); |
||
217 | } |
||
218 | } |
||
219 | return undefined; |
||
220 | } |
||
221 | |||
222 | function getCurrentLang() { |
||
223 | // Note: If the argument "?lang=" is used, PHP will automatically set a Cookie, so it is OK when we only check for the cookie |
||
224 | var lang = getCookie('LANGUAGE'); |
||
225 | return (typeof lang != "undefined") ? lang : DEFAULT_LANGUAGE; |
||
226 | } |
||
227 | |||
228 | function _L() { |
||
229 | var args = Array.prototype.slice.call(arguments); |
||
230 | var str = args.shift(); |
||
231 | |||
232 | var tmp = ""; |
||
233 | if (typeof language_messages[getCurrentLang()] == "undefined") { |
||
234 | tmp = str; |
||
235 | } else { |
||
236 | var msg = language_messages[getCurrentLang()][str]; |
||
237 | if (typeof msg != "undefined") { |
||
238 | tmp = msg; |
||
239 | } else { |
||
240 | tmp = str; |
||
241 | } |
||
242 | } |
||
243 | |||
244 | tmp = tmp.replace('###', language_tblprefix); |
||
245 | |||
246 | var n = 1; |
||
247 | while (args.length > 0) { |
||
248 | var val = args.shift(); |
||
249 | tmp = tmp.replace("%"+n, val); |
||
250 | n++; |
||
251 | } |
||
252 | |||
370 | daniel-mar | 253 | tmp = tmp.replace("%%", "%"); |
254 | |||
362 | daniel-mar | 255 | return tmp; |
256 | } |
||
257 | |||
258 | window.onload = setupOnLoad; |