Subversion Repositories oidplus

Rev

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>&lt?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>&lt?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(' ', '&nbsp;');
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;