Subversion Repositories oidplus

Rev

Rev 421 | Go to most recent revision | View as "text/javascript" | Blame | Last modification | View Log | RSS feed

  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.  
  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.  
  22. min_password_length = 10; // see also plugins/publicPages/092_forgot_password_admin/script.js
  23. password_salt_length = 10;
  24.  
  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++);
  30.                 if ((a | b | c) > 255) throw new Error(_L('String contains an invalid character'));
  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.  
  67. function adminGeneratePassword(password) {
  68.         var salt = generateRandomString(password_salt_length);
  69.         return salt+'$'+hexToBase64(sha3_512(salt+password));
  70. }
  71.  
  72. function rebuild() {
  73.         var error = false;
  74.  
  75.         if (document.getElementById('config') == null) return;
  76.  
  77.         // Check 1: Has the password the correct length?
  78.         if (document.getElementById('admin_password').value.length < min_password_length)
  79.         {
  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
  82.                 error = true;
  83.         } else {
  84.                 document.getElementById('password_warn').innerHTML = '';
  85.         }
  86.  
  87.         // Check 2: Do the passwords match?
  88.         if (document.getElementById('admin_password').value != document.getElementById('admin_password2').value) {
  89.                 document.getElementById('password_warn2').innerHTML = '<font color="red">'+_L('The passwords do not match!')+'</font>';
  90.                 error = true;
  91.         } else {
  92.                 document.getElementById('password_warn2').innerHTML = '';
  93.         }
  94.  
  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.                 }
  101.         }
  102.  
  103.         // Continue
  104.         if (!error)
  105.         {
  106.                 var e = document.getElementById("db_plugin");
  107.                 var strPlugin = e.options[e.selectedIndex].value;
  108.  
  109.                 document.getElementById('config').innerHTML = '<b>&lt?php</b><br><br>' +
  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
  112.                         '<br>' +
  113.                         'OIDplus::baseConfig()->setValue(\'CONFIG_VERSION\',    2.1);<br>' +
  114.                         '<br>' +
  115.                         // Passwords are Base64 encoded to avoid that passwords can be read upon first sight,
  116.                         // e.g. if collegues are looking over your shoulder while you accidently open (and quickly close) userdata/baseconfig/config.inc.php
  117.                         'OIDplus::baseConfig()->setValue(\'ADMIN_PASSWORD\',    \'' + adminGeneratePassword(document.getElementById('admin_password').value) + '\'); // salted, base64 encoded SHA3-512 hash<br>' +
  118.                         '<br>' +
  119.                         'OIDplus::baseConfig()->setValue(\'DATABASE_PLUGIN\',   \''+strPlugin+'\');<br>';
  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.                 }
  127.                 document.getElementById('config').innerHTML = document.getElementById('config').innerHTML +
  128.                         '<br>' +
  129.                         'OIDplus::baseConfig()->setValue(\'TABLENAME_PREFIX\',  \''+document.getElementById('tablename_prefix').value+'\');<br>' +
  130.                         '<br>' +
  131.                         'OIDplus::baseConfig()->setValue(\'SERVER_SECRET\',     \''+generateRandomString(32)+'\');<br>' +
  132.                         '<br>' +
  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>' +
  136.                         '<br>' +
  137.                         'OIDplus::baseConfig()->setValue(\'ENFORCE_SSL\',       '+document.getElementById('enforce_ssl').value+');<br>';
  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) {
  144.                 document.getElementById('step2').style.display = "None";
  145.                 document.getElementById('step3').style.display = "None";
  146.                 document.getElementById('step4').style.display = "None";
  147.         } else {
  148.                 document.getElementById('step2').style.display = "Block";
  149.                 document.getElementById('step3').style.display = "Block";
  150.                 document.getElementById('step4').style.display = "Block";
  151.         }
  152. }
  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';
  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>';
  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");
  195.         //checkAccess("plugins/publicPages/100_whois/whois/cli/index.html");
  196. }
  197.  
  198. function setupOnLoad() {
  199.         rebuild();
  200.         dbplugin_changed();
  201.         performAccessCheck();
  202. }
  203.  
  204. function getCookie(cname) {
  205.         // Source: https://www.w3schools.com/js/js_cookies.asp
  206.         var name = cname + "=";
  207.         var decodedCookie = decodeURIComponent(document.cookie);
  208.         var ca = decodedCookie.split(';');
  209.         for(var i = 0; i <ca.length; i++) {
  210.                 var c = ca[i];
  211.                 while (c.charAt(0) == ' ') {
  212.                         c = c.substring(1);
  213.                 }
  214.                 if (c.indexOf(name) == 0) {
  215.                         return c.substring(name.length, c.length);
  216.                 }
  217.         }
  218.         return undefined;
  219. }
  220.  
  221. function getCurrentLang() {
  222.         // Note: If the argument "?lang=" is used, PHP will automatically set a Cookie, so it is OK when we only check for the cookie
  223.         var lang = getCookie('LANGUAGE');
  224.         return (typeof lang != "undefined") ? lang : DEFAULT_LANGUAGE;
  225. }
  226.  
  227. function _L() {
  228.         var args = Array.prototype.slice.call(arguments);
  229.         var str = args.shift();
  230.  
  231.         var tmp = "";
  232.         if (typeof language_messages[getCurrentLang()] == "undefined") {
  233.                 tmp = str;
  234.         } else {
  235.                 var msg = language_messages[getCurrentLang()][str];
  236.                 if (typeof msg != "undefined") {
  237.                         tmp = msg;
  238.                 } else {
  239.                         tmp = str;
  240.                 }
  241.         }
  242.  
  243.         tmp = tmp.replace('###', language_tblprefix);
  244.  
  245.         var n = 1;
  246.         while (args.length > 0) {
  247.                 var val = args.shift();
  248.                 tmp = tmp.replace("%"+n, val);
  249.                 n++;
  250.         }
  251.  
  252.         tmp = tmp.replace("%%", "%");
  253.  
  254.         return tmp;
  255. }
  256.  
  257. window.onload = setupOnLoad;
  258.