diff --git a/ajax/settings.php b/ajax/settings.php index 77de46f..ed0f406 100644 --- a/ajax/settings.php +++ b/ajax/settings.php @@ -1,7 +1,7 @@ @@ -21,22 +21,22 @@ * */ - /** - * This is the AJAX portion of the settings page. - * - * It can: - * - Verify the connection settings - * - Load autocomplete values for tables - * - Load autocomplete values for columns - * - Save settings for a given domain - * - Load settings for a given domain - * - * It always returns JSON encoded responses - */ - +/** + * This is the AJAX portion of the settings page. + * + * It can: + * - Verify the connection settings + * - Load autocomplete values for tables + * - Load autocomplete values for columns + * - Save settings for a given domain + * - Load settings for a given domain + * + * It always returns JSON encoded responses + */ + namespace OCA\user_sql; -// Init owncloud +// Init Nextcloud // Check if we are a user \OCP\User::checkAdminUser(); @@ -50,53 +50,49 @@ $helper = new \OCA\user_sql\lib\Helper; $l = \OC::$server->getL10N('user_sql'); -$params = $helper -> getParameterArray(); +$params = $helper->getParameterArray(); $response = new \OCP\AppFramework\Http\JSONResponse(); // Check if the request is for us -if(isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POST['function']) && isset($_POST['domain'])) -{ +if (isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POST['function']) && isset($_POST['domain'])) { $domain = $_POST['domain']; - switch($_POST['function']) - { + switch ($_POST['function']) { // Save the settings for the given domain to the database case 'saveSettings': - $parameters = array('host' => $_POST['sql_hostname'], + $parameters = array( + 'host' => $_POST['sql_hostname'], 'password' => $_POST['sql_password'], 'user' => $_POST['sql_username'], 'dbname' => $_POST['sql_database'], 'tablePrefix' => '' ); - + // Check if the table exists - if(!$helper->verifyTable($parameters, $_POST['sql_driver'], $_POST['sql_table'])) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('The selected SQL table '.$_POST['sql_table'].' does not exist!')))); + if (!$helper->verifyTable($parameters, $_POST['sql_driver'], $_POST['sql_table'])) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('The selected SQL table ' . $_POST['sql_table'] . ' does not exist!')) + )); break; } - if(!empty($_POST['sql_group_table']) && !$helper->verifyTable($parameters, $_POST['sql_driver'], $_POST['sql_group_table'])) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('The selected SQL table '.$_POST['sql_group_table'].' does not exist!')))); + if (!empty($_POST['sql_group_table']) && !$helper->verifyTable($parameters, $_POST['sql_driver'], + $_POST['sql_group_table'])) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('The selected SQL table ' . $_POST['sql_group_table'] . ' does not exist!')) + )); break; } - + // Retrieve all column settings $columns = array(); $group_columns = array(); - foreach($params as $param) - { - if(strpos($param, 'col_') === 0) - { - if(isset($_POST[$param]) && $_POST[$param] !== '') - { - if(strpos($param, 'col_group_') === 0) - { + foreach ($params as $param) { + if (strpos($param, 'col_') === 0) { + if (isset($_POST[$param]) && $_POST[$param] !== '') { + if (strpos($param, 'col_group_') === 0) { $group_columns[] = $_POST[$param]; - } - else - { + } else { $columns[] = $_POST[$param]; } } @@ -105,97 +101,85 @@ if(isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POS // Check if the columns exist $status = $helper->verifyColumns($parameters, $_POST['sql_driver'], $_POST['sql_table'], $columns); - if(!empty($_POST['sql_group_table']) && $status === true) - { - $status = $helper->verifyColumns($parameters, $_POST['sql_driver'], $_POST['sql_group_table'], $group_columns); + if (!empty($_POST['sql_group_table']) && $status === true) { + $status = $helper->verifyColumns($parameters, $_POST['sql_driver'], $_POST['sql_group_table'], + $group_columns); } - if($status !== true) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('The selected SQL column(s) do(es) not exist: '.$status)))); + if ($status !== true) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('The selected SQL column(s) do(es) not exist: ' . $status)) + )); break; } // If we reach this point, all settings have been verified - foreach($params as $param) - { + foreach ($params as $param) { // Special handling for checkbox fields - if(isset($_POST[$param])) - { - if($param === 'set_strip_domain') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_strip_domain_'.$domain, 'true'); - } - elseif($param === 'set_allow_pwchange') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_allow_pwchange_'.$domain, 'true'); + if (isset($_POST[$param])) { + if ($param === 'set_strip_domain') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_strip_domain_' . $domain, 'true'); + } elseif ($param === 'set_allow_pwchange') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_allow_pwchange_' . $domain, 'true'); + } elseif ($param === 'set_active_invert') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_active_invert_' . $domain, 'true'); + } elseif ($param === 'set_enable_gethome') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_enable_gethome_' . $domain, 'true'); + } else { + \OC::$server->getConfig()->setAppValue('user_sql', $param . '_' . $domain, $_POST[$param]); } - elseif($param === 'set_active_invert') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_active_invert_'.$domain, 'true'); - } - elseif($param === 'set_enable_gethome') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_enable_gethome_'.$domain, 'true'); - } - else - { - \OC::$server->getConfig()->setAppValue('user_sql', $param.'_'.$domain, $_POST[$param]); - } - } else - { - if($param === 'set_strip_domain') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_strip_domain_'.$domain, 'false'); - } - elseif($param === 'set_allow_pwchange') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_allow_pwchange_'.$domain, 'false'); - } - elseif($param === 'set_active_invert') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_active_invert_'.$domain, 'false'); - } - elseif($param === 'set_enable_gethome') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_enable_gethome_'.$domain, 'false'); + } else { + if ($param === 'set_strip_domain') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_strip_domain_' . $domain, 'false'); + } elseif ($param === 'set_allow_pwchange') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_allow_pwchange_' . $domain, 'false'); + } elseif ($param === 'set_active_invert') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_active_invert_' . $domain, 'false'); + } elseif ($param === 'set_enable_gethome') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_enable_gethome_' . $domain, 'false'); } } } - $response->setData(array('status' => 'success', - 'data' => array('message' => $l -> t('Application settings successfully stored.')))); - break; + $response->setData(array( + 'status' => 'success', + 'data' => array('message' => $l->t('Application settings successfully stored.')) + )); + break; // Load the settings for a given domain case 'loadSettingsForDomain': $retArr = array(); - foreach($params as $param) - { - $retArr[$param] = \OC::$server->getConfig()->getAppValue('user_sql', $param.'_'.$domain, ''); + foreach ($params as $param) { + $retArr[$param] = \OC::$server->getConfig()->getAppValue('user_sql', $param . '_' . $domain, ''); } - $response->setData(array('status' => 'success', - 'settings' => $retArr)); - break; + $response->setData(array( + 'status' => 'success', + 'settings' => $retArr + )); + break; // Try to verify the database connection settings case 'verifySettings': $cm = new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig()); - if(!isset($_POST['sql_driver'])) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('Error connecting to database: No driver specified.')))); + if (!isset($_POST['sql_driver'])) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('Error connecting to database: No driver specified.')) + )); break; } - if(($_POST['sql_hostname'] === '') || ($_POST['sql_database'] === '')) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('Error connecting to database: You must specify at least host and database')))); + if (($_POST['sql_hostname'] === '') || ($_POST['sql_database'] === '')) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('Error connecting to database: You must specify at least host and database')) + )); break; } - $parameters = array('host' => $_POST['sql_hostname'], + $parameters = array( + 'host' => $_POST['sql_hostname'], 'password' => $_POST['sql_password'], 'user' => $_POST['sql_username'], 'dbname' => $_POST['sql_database'], @@ -203,22 +187,25 @@ if(isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POS ); try { - $conn = $cm -> getConnection($_POST['sql_driver'], $parameters); - $response->setData(array('status' => 'success', - 'data' => array('message' => $l -> t('Successfully connected to database')))); + $conn = $cm->getConnection($_POST['sql_driver'], $parameters); + $response->setData(array( + 'status' => 'success', + 'data' => array('message' => $l->t('Successfully connected to database')) + )); + } catch (\Exception $e) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('Error connecting to database: ') . $e->getMessage()) + )); } - catch(\Exception $e) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('Error connecting to database: ').$e->getMessage()))); - } - break; + break; // Get the autocompletion values for a column case 'getColumnAutocomplete': - - - $parameters = array('host' => $_POST['sql_hostname'], + + + $parameters = array( + 'host' => $_POST['sql_hostname'], 'password' => $_POST['sql_password'], 'user' => $_POST['sql_username'], 'dbname' => $_POST['sql_database'], @@ -231,28 +218,30 @@ if(isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POS $sql_table = $_POST['sql_table']; } - if($helper->verifyTable($parameters, $_POST['sql_driver'], $_POST['sql_table'])) + if ($helper->verifyTable($parameters, $_POST['sql_driver'], $_POST['sql_table'])) { $columns = $helper->getColumns($parameters, $_POST['sql_driver'], $sql_table); - else + } else { $columns = array(); - + } + $search = $_POST['request']; $ret = array(); - foreach($columns as $name) - { - if(($search === '') || ($search === 'search') || (strpos($name, $search) === 0)) - { - $ret[] = array('label' => $name, - 'value' => $name); + foreach ($columns as $name) { + if (($search === '') || ($search === 'search') || (strpos($name, $search) === 0)) { + $ret[] = array( + 'label' => $name, + 'value' => $name + ); } } - $response -> setData($ret); - break; + $response->setData($ret); + break; // Get the autocompletion values for a table case 'getTableAutocomplete': - $parameters = array('host' => $_POST['sql_hostname'], + $parameters = array( + 'host' => $_POST['sql_hostname'], 'password' => $_POST['sql_password'], 'user' => $_POST['sql_username'], 'dbname' => $_POST['sql_database'], @@ -263,23 +252,24 @@ if(isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POS $search = $_POST['request']; $ret = array(); - foreach($tables as $name) - { - if(($search === '') || ($search === 'search') || (strpos($name, $search) === 0)) - { - $ret[] = array('label' => $name, - 'value' => $name); + foreach ($tables as $name) { + if (($search === '') || ($search === 'search') || (strpos($name, $search) === 0)) { + $ret[] = array( + 'label' => $name, + 'value' => $name + ); } } - $response -> setData($ret); - break; + $response->setData($ret); + break; } -} else -{ +} else { // If the request was not for us, set an error message - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('Not submitted for us.')))); + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('Not submitted for us.')) + )); } // Return the JSON array diff --git a/appinfo/app.php b/appinfo/app.php index df34741..b984edd 100644 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -1,31 +1,31 @@ -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE -* License as published by the Free Software Foundation; either -* version 3 of the License, or any later version. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU AFFERO GENERAL PUBLIC LICENSE for more details. -* -* You should have received a copy of the GNU Affero General Public -* License along with this library. If not, see . -* -*/ + * Nextcloud - user_sql + * + * @author Andreas Böhler + * @copyright 2012-2015 Andreas Böhler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see . + * + */ require_once(__DIR__ . '/../lib/user_sql.php'); require_once __DIR__ . '/../lib/group_sql.php'; + $backend = new \OCA\user_sql\OC_USER_SQL; $group_backend = new \OCA\user_sql\OC_GROUP_SQL; \OC::$server->getUserManager()->registerBackend($backend); \OC::$server->getGroupManager()->addBackend($group_backend); -?> diff --git a/appinfo/info.xml b/appinfo/info.xml index 1c5d6bf..fa70152 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -1,27 +1,28 @@ - user_sql - SQL user backend - Authenticate Users by SQL - Authenticate Users by SQL - 3.1.0 - agpl - Andreas Boehler <dev (at) aboehler (dot) at > - user_sql - https://github.com/nextcloud/user_sql/issues - https://github.com/nextcloud/user_sql - https://raw.githubusercontent.com/nextcloud/user_sql/v2.4.0/screenshot.png - - - - auth - - - mysql - pgsql - - - \OCA\user_sql\Settings\Admin - OCA\user_sql\Settings\Section - + user_sql + SQL User Backend + Authenticate Users by SQL + Authenticate users and retrieve their groups from external database by native SQL queries. + 4.0.0-dev + agpl + Andreas Boehler <dev (at) aboehler (dot) at > + user_sql + https://github.com/nextcloud/user_sql/issues + https://github.com/nextcloud/user_sql + https://raw.githubusercontent.com/nextcloud/user_sql/v4.0.0/img/screenshot.png + + + + auth + + + + mysql + pgsql + + + \OCA\user_sql\Settings\Admin + OCA\user_sql\Settings\Section + diff --git a/appinfo/routes.php b/appinfo/routes.php index afb4fea..1617c63 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -1,8 +1,9 @@ -* This file is licensed under the Affero General Public License version 3 or later. -* See the COPYING-README file. -*/ + * Copyright (c) 2015, Andreas Böhler + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + /** @var $this \OCP\Route\IRouter */ $this->create('user_sql_ajax_settings', 'ajax/settings.php')->actionInclude('user_sql/ajax/settings.php'); diff --git a/appinfo/update.php b/appinfo/update.php deleted file mode 100644 index 6312a16..0000000 --- a/appinfo/update.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU AFFERO GENERAL PUBLIC LICENSE for more details. - * - * You should have received a copy of the GNU Affero General Public - * License along with this library. If not, see . - * - */ - -$installedVersion = \OC::$server->getConfig()->getAppValue('user_sql', 'installed_version'); - -$params = array('sql_host' => 'sql_hostname', - 'sql_user' => 'sql_username', - 'sql_database' => 'sql_database', - 'sql_password' => 'sql_password', - 'sql_table' => 'sql_table', - 'sql_column_username' => 'col_username', - 'sql_column_password' => 'col_password', - 'sql_type' => 'sql_driver', - 'sql_column_active' => 'col_active', - 'strip_domain' => 'set_strip_domain', - 'default_domain' => 'set_default_domain', - 'crypt_type' => 'set_crypt_type', - 'sql_column_displayname' => 'col_displayname', - 'allow_password_change' => 'set_allow_pwchange', - 'sql_column_active_invert' => 'set_active_invert', - 'sql_column_email' => 'col_email', - 'mail_sync_mode' => 'set_mail_sync_mode' - ); - -$delParams = array('domain_settings', - 'map_array', - 'domain_array' - ); - -if(version_compare($installedVersion, '1.99', '<')) -{ - foreach($params as $oldPar => $newPar) - { - $val = \OC::$server->getConfig()->getAppValue('user_sql', $oldPar); - if(($oldPar === 'strip_domain') || ($oldPar === 'allow_password_change') || ($oldPar === 'sql_column_active_invert')) - { - if($val) - $val = 'true'; - else - $val = 'false'; - } - if($val) - \OC::$server->getConfig()->setAppValue('user_sql', $newPar.'_default', $val); - \OC::$server->getConfig()->deleteAppValue('user_sql', $oldPar); - } - - foreach($delParams as $param) - { - \OC::$server->getConfig()->deleteAppValue('user_sql', $param); - } -} diff --git a/css/settings.css b/css/settings.css index 87f19b7..0f90ec3 100644 --- a/css/settings.css +++ b/css/settings.css @@ -1,15 +1,18 @@ .statusmessage { - background-color: #DDDDFF; + background-color: #DDDDFF; } + .errormessage { - background-color: #FFDDDD; + background-color: #FFDDDD; } + .successmessage { - background-color: #DDFFDD; + background-color: #DDFFDD; } -.statusmessage,.errormessage,.successmessage{ - display:none; - padding: 1px; + +.statusmessage, .errormessage, .successmessage { + display: none; + padding: 1px; } #sql-1 p label:first-child, diff --git a/img/app-dark.svg b/img/app-dark.svg index 54939fa..24168c8 100644 --- a/img/app-dark.svg +++ b/img/app-dark.svg @@ -1,4 +1,5 @@ - + diff --git a/screenshot.png b/img/screenshot.png similarity index 100% rename from screenshot.png rename to img/screenshot.png diff --git a/js/settings.js b/js/settings.js index f9f6b44..4b63b53 100644 --- a/js/settings.js +++ b/js/settings.js @@ -2,63 +2,57 @@ // declare namespace var user_sql = user_sql || -{ -}; + {}; /** * init admin settings view */ -user_sql.adminSettingsUI = function() -{ +user_sql.adminSettingsUI = function () { - if($('#sqlDiv').length > 0) - { + if ($('#sqlDiv').length > 0) { // enable tabs on settings page $('#sqlDiv').tabs(); - + // Attach auto-completion to all column fields $('#col_username, #col_password, #col_displayname, #col_active, #col_email, #col_gethome').autocomplete({ - source: function(request, response) - { + source: function (request, response) { var post = $('#sqlForm').serializeArray(); var domain = $('#sql_domain_chooser option:selected').val(); - + post.push({ name: 'function', value: 'getColumnAutocomplete' }); - + post.push({ name: 'domain', value: domain }); - + post.push({ name: 'request', value: request.term }); - + // Ajax foobar $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, response, 'json'); }, minLength: 0, - open: function() { + open: function () { $(this).attr('state', 'open'); }, - close: function() { + close: function () { $(this).attr('state', 'closed'); } - }).focus(function() { - if($(this).attr('state') != 'open') - { - $(this).autocomplete("search"); - } + }).focus(function () { + if ($(this).attr('state') != 'open') { + $(this).autocomplete("search"); + } }); // Attach auto-completion to all group column fields $('#col_group_name, #col_group_username').autocomplete({ - source: function(request, response) - { + source: function (request, response) { var post = $('#sqlForm').serializeArray(); var domain = $('#sql_domain_chooser option:selected').val(); @@ -86,71 +80,67 @@ user_sql.adminSettingsUI = function() $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, response, 'json'); }, minLength: 0, - open: function() { + open: function () { $(this).attr('state', 'open'); }, - close: function() { + close: function () { $(this).attr('state', 'closed'); } - }).focus(function() { - if($(this).attr('state') != 'open') - { - $(this).autocomplete("search"); - } + }).focus(function () { + if ($(this).attr('state') != 'open') { + $(this).autocomplete("search"); + } }); - + // Attach auto-completion to all table fields $('#sql_table, #sql_group_table').autocomplete({ - source: function(request, response) - { + source: function (request, response) { var post = $('#sqlForm').serializeArray(); var domain = $('#sql_domain_chooser option:selected').val(); - + post.push({ name: 'function', value: 'getTableAutocomplete' }); - + post.push({ name: 'domain', value: domain }); - + post.push({ name: 'request', value: request.term }); - + // Ajax foobar $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, response, 'json'); }, minLength: 0, - open: function() { + open: function () { $(this).attr('state', 'open'); }, - close: function() { + close: function () { $(this).attr('state', 'closed'); } - }).focus(function() { - if($(this).attr('state') != 'open') - { - $(this).autocomplete("search"); - } + }).focus(function () { + if ($(this).attr('state') != 'open') { + $(this).autocomplete("search"); + } }); - + // Verify the SQL database settings - $('#sqlVerify').click(function(event) - { + $('#sqlVerify').click(function (event) { event.preventDefault(); var post = $('#sqlForm').serializeArray(); var domain = $('#sql_domain_chooser option:selected').val(); - + post.push({ name: 'function', value: 'verifySettings' }); - + post.push({ name: 'domain', value: domain @@ -161,39 +151,34 @@ user_sql.adminSettingsUI = function() $('#sql_error_message').hide(); $('#sql_update_message').hide(); // Ajax foobar - $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function(data) - { + $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function (data) { $('#sql_verify_message').hide(); - if(data.status == 'success') - { + if (data.status == 'success') { $('#sql_success_message').html(data.data.message); $('#sql_success_message').show(); - window.setTimeout(function() - { + window.setTimeout(function () { $('#sql_success_message').hide(); }, 10000); - } else - { + } else { $('#sql_error_message').html(data.data.message); $('#sql_error_message').show(); } }, 'json'); return false; - }); + }); // Save the settings for a domain - $('#sqlSubmit').click(function(event) - { + $('#sqlSubmit').click(function (event) { event.preventDefault(); var post = $('#sqlForm').serializeArray(); var domain = $('#sql_domain_chooser option:selected').val(); - + post.push({ name: 'function', value: 'saveSettings' }); - + post.push({ name: 'domain', value: domain @@ -204,19 +189,15 @@ user_sql.adminSettingsUI = function() $('#sql_verify_message').hide(); $('#sql_error_message').hide(); // Ajax foobar - $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function(data) - { + $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function (data) { $('#sql_update_message').hide(); - if(data.status == 'success') - { + if (data.status == 'success') { $('#sql_success_message').html(data.data.message); $('#sql_success_message').show(); - window.setTimeout(function() - { + window.setTimeout(function () { $('#sql_success_message').hide(); }, 10000); - } else - { + } else { $('#sql_error_message').html(data.data.message); $('#sql_error_message').show(); } @@ -225,45 +206,39 @@ user_sql.adminSettingsUI = function() }); // Attach event handler to the domain chooser - $('#sql_domain_chooser').change(function() { - user_sql.loadDomainSettings($('#sql_domain_chooser option:selected').val()); + $('#sql_domain_chooser').change(function () { + user_sql.loadDomainSettings($('#sql_domain_chooser option:selected').val()); }); - - $('#set_gethome_mode').change(function() { - user_sql.setGethomeMode(); + + $('#set_gethome_mode').change(function () { + user_sql.setGethomeMode(); }); - - $('#set_enable_gethome').change(function() { + + $('#set_enable_gethome').change(function () { user_sql.setGethomeMode(); }); } }; -user_sql.setGethomeMode = function() -{ +user_sql.setGethomeMode = function () { var enabled = $('#set_enable_gethome').prop('checked'); - if(enabled) - { + if (enabled) { $('#set_gethome_mode').prop('disabled', false); var val = $('#set_gethome_mode option:selected').val(); - if(val === 'query') - { + if (val === 'query') { $('#set_gethome').prop('disabled', true); $('#col_gethome').prop('disabled', false); } - else if(val === 'static') - { + else if (val === 'static') { $('#set_gethome').prop('disabled', false); $('#col_gethome').prop('disabled', true); } - else - { + else { $('#set_gethome').prop('disabled', true); $('#col_gethome').prop('disabled', true); } } - else - { + else { $('#set_gethome_mode').prop('disabled', true); $('#set_gethome').prop('disabled', true); $('#col_gethome').prop('disabled', true); @@ -274,8 +249,7 @@ user_sql.setGethomeMode = function() * Load the settings for the selected domain * @param string domain The domain to load */ -user_sql.loadDomainSettings = function(domain) -{ +user_sql.loadDomainSettings = function (domain) { $('#sql_success_message').hide(); $('#sql_error_message').hide(); $('#sql_verify_message').hide(); @@ -294,49 +268,40 @@ user_sql.loadDomainSettings = function(domain) value: domain } ]; - $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function(data) - { + $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function (data) { $('#sql_loading_message').hide(); - if(data.status == 'success') - { - for(key in data.settings) - { - if(key == 'set_strip_domain') - { - if(data.settings[key] == 'true') + if (data.status == 'success') { + for (key in data.settings) { + if (key == 'set_strip_domain') { + if (data.settings[key] == 'true') $('#' + key).prop('checked', true); else $('#' + key).prop('checked', false); } - else if(key == 'set_allow_pwchange') - { - if(data.settings[key] == 'true') + else if (key == 'set_allow_pwchange') { + if (data.settings[key] == 'true') $('#' + key).prop('checked', true); else $('#' + key).prop('checked', false); } - else if(key == 'set_active_invert') - { - if(data.settings[key] == 'true') + else if (key == 'set_active_invert') { + if (data.settings[key] == 'true') $('#' + key).prop('checked', true); else $('#' + key).prop('checked', false); } - else if(key == 'set_enable_gethome') - { - if(data.settings[key] == 'true') + else if (key == 'set_enable_gethome') { + if (data.settings[key] == 'true') $('#' + key).prop('checked', true); else $('#' + key).prop('checked', false); } - else - { + else { $('#' + key).val(data.settings[key]); } } } - else - { + else { $('#sql_error_message').html(data.data.message); $('#sql_error_message').show(); } @@ -346,10 +311,8 @@ user_sql.loadDomainSettings = function(domain) }; // Run our JS if the SQL settings are present -$(document).ready(function() -{ - if($('#sqlDiv')) - { +$(document).ready(function () { + if ($('#sqlDiv')) { user_sql.adminSettingsUI(); user_sql.loadDomainSettings($('#sql_domain_chooser option:selected').val()); user_sql.setGethomeMode(); diff --git a/lib/PasswordHash.php b/lib/PasswordHash.php index e363656..c414ad3 100644 --- a/lib/PasswordHash.php +++ b/lib/PasswordHash.php @@ -24,230 +24,245 @@ # Obviously, since this code is in the public domain, the above are not # requirements (there can be none), but merely suggestions. # -class PasswordHash { - var $itoa64; - var $iteration_count_log2; - var $portable_hashes; - var $random_state; +class PasswordHash +{ + var $itoa64; + var $iteration_count_log2; + var $portable_hashes; + var $random_state; - function __construct($iteration_count_log2, $portable_hashes) - { - $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + function __construct($iteration_count_log2, $portable_hashes) + { + $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) - $iteration_count_log2 = 8; - $this->iteration_count_log2 = $iteration_count_log2; + if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) { + $iteration_count_log2 = 8; + } + $this->iteration_count_log2 = $iteration_count_log2; - $this->portable_hashes = $portable_hashes; + $this->portable_hashes = $portable_hashes; - $this->random_state = microtime(); - if (function_exists('getmypid')) - $this->random_state .= getmypid(); - } + $this->random_state = microtime(); + if (function_exists('getmypid')) { + $this->random_state .= getmypid(); + } + } - function get_random_bytes($count) - { - $output = ''; - if (is_readable('/dev/urandom') && - ($fh = @fopen('/dev/urandom', 'rb'))) { - $output = fread($fh, $count); - fclose($fh); - } + function get_random_bytes($count) + { + $output = ''; + if (is_readable('/dev/urandom') && + ($fh = @fopen('/dev/urandom', 'rb'))) { + $output = fread($fh, $count); + fclose($fh); + } - if (strlen($output) < $count) { - $output = ''; - for ($i = 0; $i < $count; $i += 16) { - $this->random_state = - md5(microtime() . $this->random_state); - $output .= - pack('H*', md5($this->random_state)); - } - $output = substr($output, 0, $count); - } + if (strlen($output) < $count) { + $output = ''; + for ($i = 0; $i < $count; $i += 16) { + $this->random_state = + md5(microtime() . $this->random_state); + $output .= + pack('H*', md5($this->random_state)); + } + $output = substr($output, 0, $count); + } - return $output; - } + return $output; + } - function encode64($input, $count) - { - $output = ''; - $i = 0; - do { - $value = ord($input[$i++]); - $output .= $this->itoa64[$value & 0x3f]; - if ($i < $count) - $value |= ord($input[$i]) << 8; - $output .= $this->itoa64[($value >> 6) & 0x3f]; - if ($i++ >= $count) - break; - if ($i < $count) - $value |= ord($input[$i]) << 16; - $output .= $this->itoa64[($value >> 12) & 0x3f]; - if ($i++ >= $count) - break; - $output .= $this->itoa64[($value >> 18) & 0x3f]; - } while ($i < $count); + function encode64($input, $count) + { + $output = ''; + $i = 0; + do { + $value = ord($input[$i++]); + $output .= $this->itoa64[$value & 0x3f]; + if ($i < $count) { + $value |= ord($input[$i]) << 8; + } + $output .= $this->itoa64[($value >> 6) & 0x3f]; + if ($i++ >= $count) { + break; + } + if ($i < $count) { + $value |= ord($input[$i]) << 16; + } + $output .= $this->itoa64[($value >> 12) & 0x3f]; + if ($i++ >= $count) { + break; + } + $output .= $this->itoa64[($value >> 18) & 0x3f]; + } while ($i < $count); - return $output; - } + return $output; + } - function gensalt_private($input) - { - $output = '$P$'; - $output .= $this->itoa64[min($this->iteration_count_log2 + - ((PHP_VERSION >= '5') ? 5 : 3), 30)]; - $output .= $this->encode64($input, 6); + function gensalt_private($input) + { + $output = '$P$'; + $output .= $this->itoa64[min($this->iteration_count_log2 + + ((PHP_VERSION >= '5') ? 5 : 3), 30)]; + $output .= $this->encode64($input, 6); - return $output; - } + return $output; + } - function crypt_private($password, $setting) - { - $output = '*0'; - if (substr($setting, 0, 2) === $output) - $output = '*1'; + function crypt_private($password, $setting) + { + $output = '*0'; + if (substr($setting, 0, 2) === $output) { + $output = '*1'; + } - $id = substr($setting, 0, 3); - # We use "$P$", phpBB3 uses "$H$" for the same thing - if ($id !== '$P$' && $id !== '$H$') - return $output; + $id = substr($setting, 0, 3); + # We use "$P$", phpBB3 uses "$H$" for the same thing + if ($id !== '$P$' && $id !== '$H$') { + return $output; + } - $count_log2 = strpos($this->itoa64, $setting[3]); - if ($count_log2 < 7 || $count_log2 > 30) - return $output; + $count_log2 = strpos($this->itoa64, $setting[3]); + if ($count_log2 < 7 || $count_log2 > 30) { + return $output; + } - $count = 1 << $count_log2; + $count = 1 << $count_log2; - $salt = substr($setting, 4, 8); - if (strlen($salt) !== 8) - return $output; + $salt = substr($setting, 4, 8); + if (strlen($salt) !== 8) { + return $output; + } - # We're kind of forced to use MD5 here since it's the only - # cryptographic primitive available in all versions of PHP - # currently in use. To implement our own low-level crypto - # in PHP would result in much worse performance and - # consequently in lower iteration counts and hashes that are - # quicker to crack (by non-PHP code). - if (PHP_VERSION >= '5') { - $hash = md5($salt . $password, TRUE); - do { - $hash = md5($hash . $password, TRUE); - } while (--$count); - } else { - $hash = pack('H*', md5($salt . $password)); - do { - $hash = pack('H*', md5($hash . $password)); - } while (--$count); - } + # We're kind of forced to use MD5 here since it's the only + # cryptographic primitive available in all versions of PHP + # currently in use. To implement our own low-level crypto + # in PHP would result in much worse performance and + # consequently in lower iteration counts and hashes that are + # quicker to crack (by non-PHP code). + if (PHP_VERSION >= '5') { + $hash = md5($salt . $password, true); + do { + $hash = md5($hash . $password, true); + } while (--$count); + } else { + $hash = pack('H*', md5($salt . $password)); + do { + $hash = pack('H*', md5($hash . $password)); + } while (--$count); + } - $output = substr($setting, 0, 12); - $output .= $this->encode64($hash, 16); + $output = substr($setting, 0, 12); + $output .= $this->encode64($hash, 16); - return $output; - } + return $output; + } - function gensalt_extended($input) - { - $count_log2 = min($this->iteration_count_log2 + 8, 24); - # This should be odd to not reveal weak DES keys, and the - # maximum valid value is (2**24 - 1) which is odd anyway. - $count = (1 << $count_log2) - 1; + function gensalt_extended($input) + { + $count_log2 = min($this->iteration_count_log2 + 8, 24); + # This should be odd to not reveal weak DES keys, and the + # maximum valid value is (2**24 - 1) which is odd anyway. + $count = (1 << $count_log2) - 1; - $output = '_'; - $output .= $this->itoa64[$count & 0x3f]; - $output .= $this->itoa64[($count >> 6) & 0x3f]; - $output .= $this->itoa64[($count >> 12) & 0x3f]; - $output .= $this->itoa64[($count >> 18) & 0x3f]; + $output = '_'; + $output .= $this->itoa64[$count & 0x3f]; + $output .= $this->itoa64[($count >> 6) & 0x3f]; + $output .= $this->itoa64[($count >> 12) & 0x3f]; + $output .= $this->itoa64[($count >> 18) & 0x3f]; - $output .= $this->encode64($input, 3); + $output .= $this->encode64($input, 3); - return $output; - } + return $output; + } - function gensalt_blowfish($input) - { - # This one needs to use a different order of characters and a - # different encoding scheme from the one in encode64() above. - # We care because the last character in our encoded string will - # only represent 2 bits. While two known implementations of - # bcrypt will happily accept and correct a salt string which - # has the 4 unused bits set to non-zero, we do not want to take - # chances and we also do not want to waste an additional byte - # of entropy. - $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + function gensalt_blowfish($input) + { + # This one needs to use a different order of characters and a + # different encoding scheme from the one in encode64() above. + # We care because the last character in our encoded string will + # only represent 2 bits. While two known implementations of + # bcrypt will happily accept and correct a salt string which + # has the 4 unused bits set to non-zero, we do not want to take + # chances and we also do not want to waste an additional byte + # of entropy. + $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - $output = '$2a$'; - $output .= chr(ord('0') + $this->iteration_count_log2 / 10); - $output .= chr(ord('0') + $this->iteration_count_log2 % 10); - $output .= '$'; + $output = '$2a$'; + $output .= chr(ord('0') + $this->iteration_count_log2 / 10); + $output .= chr(ord('0') + $this->iteration_count_log2 % 10); + $output .= '$'; - $i = 0; - do { - $c1 = ord($input[$i++]); - $output .= $itoa64[$c1 >> 2]; - $c1 = ($c1 & 0x03) << 4; - if ($i >= 16) { - $output .= $itoa64[$c1]; - break; - } + $i = 0; + do { + $c1 = ord($input[$i++]); + $output .= $itoa64[$c1 >> 2]; + $c1 = ($c1 & 0x03) << 4; + if ($i >= 16) { + $output .= $itoa64[$c1]; + break; + } - $c2 = ord($input[$i++]); - $c1 |= $c2 >> 4; - $output .= $itoa64[$c1]; - $c1 = ($c2 & 0x0f) << 2; + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 4; + $output .= $itoa64[$c1]; + $c1 = ($c2 & 0x0f) << 2; - $c2 = ord($input[$i++]); - $c1 |= $c2 >> 6; - $output .= $itoa64[$c1]; - $output .= $itoa64[$c2 & 0x3f]; - } while (1); + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 6; + $output .= $itoa64[$c1]; + $output .= $itoa64[$c2 & 0x3f]; + } while (1); - return $output; - } + return $output; + } - function HashPassword($password) - { - $random = ''; + function HashPassword($password) + { + $random = ''; - if (CRYPT_BLOWFISH === 1 && !$this->portable_hashes) { - $random = $this->get_random_bytes(16); - $hash = - crypt($password, $this->gensalt_blowfish($random)); - if (strlen($hash) === 60) - return $hash; - } + if (CRYPT_BLOWFISH === 1 && !$this->portable_hashes) { + $random = $this->get_random_bytes(16); + $hash = + crypt($password, $this->gensalt_blowfish($random)); + if (strlen($hash) === 60) { + return $hash; + } + } - if (CRYPT_EXT_DES === 1 && !$this->portable_hashes) { - if (strlen($random) < 3) - $random = $this->get_random_bytes(3); - $hash = - crypt($password, $this->gensalt_extended($random)); - if (strlen($hash) === 20) - return $hash; - } + if (CRYPT_EXT_DES === 1 && !$this->portable_hashes) { + if (strlen($random) < 3) { + $random = $this->get_random_bytes(3); + } + $hash = + crypt($password, $this->gensalt_extended($random)); + if (strlen($hash) === 20) { + return $hash; + } + } - if (strlen($random) < 6) - $random = $this->get_random_bytes(6); - $hash = - $this->crypt_private($password, - $this->gensalt_private($random)); - if (strlen($hash) === 34) - return $hash; + if (strlen($random) < 6) { + $random = $this->get_random_bytes(6); + } + $hash = + $this->crypt_private($password, + $this->gensalt_private($random)); + if (strlen($hash) === 34) { + return $hash; + } - # Returning '*' on error is safe here, but would _not_ be safe - # in a crypt(3)-like function used _both_ for generating new - # hashes and for validating passwords against existing hashes. - return '*'; - } + # Returning '*' on error is safe here, but would _not_ be safe + # in a crypt(3)-like function used _both_ for generating new + # hashes and for validating passwords against existing hashes. + return '*'; + } - function CheckPassword($password, $stored_hash) - { - $hash = $this->crypt_private($password, $stored_hash); - if ($hash[0] === '*') - $hash = crypt($password, $stored_hash); + function CheckPassword($password, $stored_hash) + { + $hash = $this->crypt_private($password, $stored_hash); + if ($hash[0] === '*') { + $hash = crypt($password, $stored_hash); + } - return $hash === $stored_hash; - } + return $hash === $stored_hash; + } } - -?> diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index cf11109..bf6f5b1 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -28,73 +28,76 @@ use OCP\Defaults; use OCP\IConfig; use OCP\IL10N; use OCP\Settings\ISettings; -use OCA\user_sql\lib\Helper; -class Admin implements ISettings { - /** @var IL10N */ - private $l10n; - /** @var Defaults */ - private $defaults; - /** @var IConfig */ - private $config; +class Admin implements ISettings +{ + /** @var IL10N */ + private $l10n; + /** @var Defaults */ + private $defaults; + /** @var IConfig */ + private $config; - /** - * @param IL10N $l10n - * @param Defaults $defaults - * @param IConfig $config - */ - public function __construct(IL10N $l10n, - Defaults $defaults, - IConfig $config) { - $this->l10n = $l10n; - $this->defaults = $defaults; - $this->config = $config; - $this->helper = new \OCA\user_sql\lib\Helper(); - $this->params = $this->helper->getParameterArray(); - $this->settings = $this->helper -> loadSettingsForDomain('default'); - } + /** + * @param IL10N $l10n + * @param Defaults $defaults + * @param IConfig $config + */ + public function __construct( + IL10N $l10n, + Defaults $defaults, + IConfig $config + ) { + $this->l10n = $l10n; + $this->defaults = $defaults; + $this->config = $config; + $this->helper = new \OCA\user_sql\lib\Helper(); + $this->params = $this->helper->getParameterArray(); + $this->settings = $this->helper->loadSettingsForDomain('default'); + } - /** - * @return TemplateResponse - */ - public function getForm() { + /** + * @return TemplateResponse + */ + public function getForm() + { - $type = $this->config->getAppValue('user_sql', 'type'); - $trusted_domains = \OC::$server->getConfig()->getSystemValue('trusted_domains'); - $inserted = array('default'); - array_splice($trusted_domains, 0, 0, $inserted); + $type = $this->config->getAppValue('user_sql', 'type'); + $trusted_domains = \OC::$server->getConfig()->getSystemValue('trusted_domains'); + $inserted = array('default'); + array_splice($trusted_domains, 0, 0, $inserted); - $params = [ - 'type' => $type, - ]; - $params['allowed_domains']= array_unique($trusted_domains); + $params = [ + 'type' => $type, + ]; + $params['allowed_domains'] = array_unique($trusted_domains); - foreach($this->params as $key) - { - $value = $this->settings[$key]; - $params[$key]=$value; - } + foreach ($this->params as $key) { + $value = $this->settings[$key]; + $params[$key] = $value; + } - $params["config"]=$this->config; - return new TemplateResponse('user_sql', 'admin', $params); - } + $params["config"] = $this->config; + return new TemplateResponse('user_sql', 'admin', $params); + } - /** - * @return string the section ID, e.g. 'sharing' - */ - public function getSection() { - return 'usersql'; - } - - /** - * @return int whether the form should be rather on the top or bottom of - * the admin section. The forms are arranged in ascending order of the - * priority values. It is required to return a value between 0 and 100. - * - * keep the server setting at the top, right after "server settings" - */ - public function getPriority() { - return 0; - } + /** + * @return string the section ID, e.g. 'sharing' + */ + public function getSection() + { + return 'user_sql'; + } + /** + * @return int whether the form should be rather on the top or bottom of + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. + * + * keep the server setting at the top, right after "server settings" + */ + public function getPriority() + { + return 0; + } } diff --git a/lib/Settings/Section.php b/lib/Settings/Section.php index 091f8f2..9d6ba23 100644 --- a/lib/Settings/Section.php +++ b/lib/Settings/Section.php @@ -27,42 +27,49 @@ use OCP\IL10N; use OCP\Settings\IIconSection; use OCP\IURLGenerator; -class Section implements IIconSection { - /** @var IL10N */ - private $l; +class Section implements IIconSection +{ + /** @var IL10N */ + private $l; - /** - * @param IL10N $l - */ - public function __construct(IURLGenerator $url,IL10N $l) { - $this->l = $l; - $this->url = $url; - } + /** + * @param IL10N $l + */ + public function __construct(IURLGenerator $url, IL10N $l) + { + $this->l = $l; + $this->url = $url; + } - /** - * {@inheritdoc} - */ - public function getID() { - return 'usersql'; - } + /** + * {@inheritdoc} + */ + public function getID() + { + return 'user_sql'; + } - /** - * {@inheritdoc} - */ - public function getName() { - return $this->l->t('User SQL'); - } + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->l->t('User SQL'); + } - /** - * {@inheritdoc} - */ - public function getPriority() { - return 75; - } - /** - * {@inheritdoc} - */ - public function getIcon() { - return $this->url->imagePath('user_sql', 'app-dark.svg'); - } + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 75; + } + + /** + * {@inheritdoc} + */ + public function getIcon() + { + return $this->url->imagePath('user_sql', 'app-dark.svg'); + } } diff --git a/lib/drupal.php b/lib/drupal.php index 4c7e0a4..3b07cda 100644 --- a/lib/drupal.php +++ b/lib/drupal.php @@ -1,321 +1,330 @@ -> 6) & 0x3f]; - if ($i++ >= $count) { - break; - } - if ($i < $count) { - $value |= ord($input[$i]) << 16; - } - $output .= $itoa64[($value >> 12) & 0x3f]; - if ($i++ >= $count) { - break; - } - $output .= $itoa64[($value >> 18) & 0x3f]; - } while ($i < $count); - - return $output; -} -/** - * Returns a string of highly randomized bytes (over the full 8-bit range). - * - * This function is better than simply calling mt_rand() or any other built-in - * PHP function because it can return a long string of bytes (compared to < 4 - * bytes normally from mt_rand()) and uses the best available pseudo-random - * source. - * - * @param $count - * The number of characters (bytes) to return in the string. - */ - - function _random_bytes($count) { - // $random_state does not use static as it stores random bytes. - static $random_state, $bytes, $has_openssl; - - $missing_bytes = $count - strlen($bytes); - - if ($missing_bytes > 0) { - // PHP versions prior 5.3.4 experienced openssl_random_pseudo_bytes() - // locking on Windows and rendered it unusable. - if (!isset($has_openssl)) { - $has_openssl = version_compare(PHP_VERSION, '5.3.4', '>=') && function_exists('openssl_random_pseudo_bytes'); - } - - // openssl_random_pseudo_bytes() will find entropy in a system-dependent - // way. - if ($has_openssl) { - $bytes .= openssl_random_pseudo_bytes($missing_bytes); - } - - // Else, read directly from /dev/urandom, which is available on many *nix - // systems and is considered cryptographically secure. - elseif ($fh = @fopen('/dev/urandom', 'rb')) { - // PHP only performs buffered reads, so in reality it will always read - // at least 4096 bytes. Thus, it costs nothing extra to read and store - // that much so as to speed any additional invocations. - $bytes .= fread($fh, max(4096, $missing_bytes)); - fclose($fh); - } - - // If we couldn't get enough entropy, this simple hash-based PRNG will - // generate a good set of pseudo-random bytes on any system. - // Note that it may be important that our $random_state is passed - // through hash() prior to being rolled into $output, that the two hash() - // invocations are different, and that the extra input into the first one - - // the microtime() - is prepended rather than appended. This is to avoid - // directly leaking $random_state via the $output stream, which could - // allow for trivial prediction of further "random" numbers. - if (strlen($bytes) < $count) { - // Initialize on the first call. The contents of $_SERVER includes a mix of - // user-specific and system information that varies a little with each page. - if (!isset($random_state)) { - $random_state = print_r($_SERVER, TRUE); - if (function_exists('getmypid')) { - // Further initialize with the somewhat random PHP process ID. - $random_state .= getmypid(); - } - $bytes = ''; - } - - do { - $random_state = hash('sha256', microtime() . mt_rand() . $random_state); - $bytes .= hash('sha256', mt_rand() . $random_state, TRUE); - } - while (strlen($bytes) < $count); - } - } - $output = substr($bytes, 0, $count); - $bytes = substr($bytes, $count); - return $output; -} - -/** - * Generates a random base 64-encoded salt prefixed with settings for the hash. - * - * Proper use of salts may defeat a number of attacks, including: - * - The ability to try candidate passwords against multiple hashes at once. - * - The ability to use pre-hashed lists of candidate passwords. - * - The ability to determine whether two users have the same (or different) - * password without actually having to guess one of the passwords. - * - * @param $count_log2 - * Integer that determines the number of iterations used in the hashing - * process. A larger value is more secure, but takes more time to complete. - * - * @return - * A 12 character string containing the iteration count and a random salt. - */ -function _password_generate_salt($count_log2) { - $output = '$S$'; - // Ensure that $count_log2 is within set bounds. - $count_log2 = _password_enforce_log2_boundaries($count_log2); - // We encode the final log2 iteration count in base 64. - $itoa64 = _password_itoa64(); - $output .= $itoa64[$count_log2]; - // 6 bytes is the standard salt for a portable phpass hash. - $output .= _password_base64_encode(_random_bytes(6), 6); - return $output; -} - -/** - * Ensures that $count_log2 is within set bounds. - * - * @param $count_log2 - * Integer that determines the number of iterations used in the hashing - * process. A larger value is more secure, but takes more time to complete. - * - * @return - * Integer within set bounds that is closest to $count_log2. - */ -function _password_enforce_log2_boundaries($count_log2) { - if ($count_log2 < MIN_HASH_COUNT) { - return MIN_HASH_COUNT; - } - elseif ($count_log2 > MAX_HASH_COUNT) { - return MAX_HASH_COUNT; - } - - return (int) $count_log2; -} - -/** - * Hash a password using a secure stretched hash. - * - * By using a salt and repeated hashing the password is "stretched". Its - * security is increased because it becomes much more computationally costly - * for an attacker to try to break the hash by brute-force computation of the - * hashes of a large number of plain-text words or strings to find a match. - * - * @param $algo - * The string name of a hashing algorithm usable by hash(), like 'sha256'. - * @param $password - * Plain-text password up to 512 bytes (128 to 512 UTF-8 characters) to hash. - * @param $setting - * An existing hash or the output of _password_generate_salt(). Must be - * at least 12 characters (the settings and salt). - * - * @return - * A string containing the hashed password (and salt) or FALSE on failure. - * The return string will be truncated at DRUPAL_HASH_LENGTH characters max. - */ -function _password_crypt($algo, $password, $setting) { - // Prevent DoS attacks by refusing to hash large passwords. - if (strlen($password) > 512) { - return FALSE; - } - // The first 12 characters of an existing hash are its setting string. - $setting = substr($setting, 0, 12); - - if ($setting[0] != '$' || $setting[2] != '$') { - return FALSE; - } - $count_log2 = _password_get_count_log2($setting); - // Hashes may be imported from elsewhere, so we allow != DRUPAL_HASH_COUNT - if ($count_log2 < MIN_HASH_COUNT || $count_log2 > MAX_HASH_COUNT) { - return FALSE; - } - $salt = substr($setting, 4, 8); - // Hashes must have an 8 character salt. - if (strlen($salt) != 8) { - return FALSE; - } - - // Convert the base 2 logarithm into an integer. - $count = 1 << $count_log2; - - // We rely on the hash() function being available in PHP 5.2+. - $hash = hash($algo, $salt . $password, TRUE); - do { - $hash = hash($algo, $hash . $password, TRUE); - } while (--$count); - - $len = strlen($hash); - $output = $setting . _password_base64_encode($hash, $len); - // _password_base64_encode() of a 16 byte MD5 will always be 22 characters. - // _password_base64_encode() of a 64 byte sha512 will always be 86 characters. - $expected = 12 + ceil((8 * $len) / 6); - return (strlen($output) == $expected) ? substr($output, 0, HASH_LENGTH) : FALSE; -} - -/** - * Parse the log2 iteration count from a stored hash or setting string. - */ -function _password_get_count_log2($setting) { - $itoa64 = _password_itoa64(); - return strpos($itoa64, $setting[3]); -} - -/** - * Hash a password using a secure hash. - * - * @param $password - * A plain-text password. - * @param $count_log2 - * Optional integer to specify the iteration count. Generally used only during - * mass operations where a value less than the default is needed for speed. - * - * @return - * A string containing the hashed password (and a salt), or FALSE on failure. - */ -function user_hash_password($password, $count_log2 = 0) { - if (empty($count_log2)) { - // Use the standard iteration count. - $count_log2 = variable_get('password_count_log2', DRUPAL_HASH_COUNT); - } - return _password_crypt('sha512', $password, _password_generate_salt($count_log2)); -} - -/** - * Check whether a plain text password matches a stored hashed password. - * - * @param $password - * A plain-text password - * @param $hashpass - * - * @return - * TRUE or FALSE. - */ -function user_check_password($password, $hashpass) { - $stored_hash = $hashpass; - $type = substr($stored_hash, 0, 3); - switch ($type) { - case '$S$': - // A normal Drupal 7 password using sha512. - $hash = _password_crypt('sha512', $password, $stored_hash); - break; - case '$H$': - // phpBB3 uses "$H$" for the same thing as "$P$". - case '$P$': - // A phpass password generated using md5. This is an - // imported password or from an earlier Drupal version. - $hash = _password_crypt('md5', $password, $stored_hash); - break; - default: - return FALSE; - } - return ($hash && $stored_hash == $hash); -} \ No newline at end of file +> 6) & 0x3f]; + if ($i++ >= $count) { + break; + } + if ($i < $count) { + $value |= ord($input[$i]) << 16; + } + $output .= $itoa64[($value >> 12) & 0x3f]; + if ($i++ >= $count) { + break; + } + $output .= $itoa64[($value >> 18) & 0x3f]; + } while ($i < $count); + + return $output; +} + +/** + * Returns a string of highly randomized bytes (over the full 8-bit range). + * + * This function is better than simply calling mt_rand() or any other built-in + * PHP function because it can return a long string of bytes (compared to < 4 + * bytes normally from mt_rand()) and uses the best available pseudo-random + * source. + * + * @param $count + * The number of characters (bytes) to return in the string. + */ + +function _random_bytes($count) +{ + // $random_state does not use static as it stores random bytes. + static $random_state, $bytes, $has_openssl; + + $missing_bytes = $count - strlen($bytes); + + if ($missing_bytes > 0) { + // PHP versions prior 5.3.4 experienced openssl_random_pseudo_bytes() + // locking on Windows and rendered it unusable. + if (!isset($has_openssl)) { + $has_openssl = version_compare(PHP_VERSION, '5.3.4', + '>=') && function_exists('openssl_random_pseudo_bytes'); + } + + // openssl_random_pseudo_bytes() will find entropy in a system-dependent + // way. + if ($has_openssl) { + $bytes .= openssl_random_pseudo_bytes($missing_bytes); + } + + // Else, read directly from /dev/urandom, which is available on many *nix + // systems and is considered cryptographically secure. + elseif ($fh = @fopen('/dev/urandom', 'rb')) { + // PHP only performs buffered reads, so in reality it will always read + // at least 4096 bytes. Thus, it costs nothing extra to read and store + // that much so as to speed any additional invocations. + $bytes .= fread($fh, max(4096, $missing_bytes)); + fclose($fh); + } + + // If we couldn't get enough entropy, this simple hash-based PRNG will + // generate a good set of pseudo-random bytes on any system. + // Note that it may be important that our $random_state is passed + // through hash() prior to being rolled into $output, that the two hash() + // invocations are different, and that the extra input into the first one - + // the microtime() - is prepended rather than appended. This is to avoid + // directly leaking $random_state via the $output stream, which could + // allow for trivial prediction of further "random" numbers. + if (strlen($bytes) < $count) { + // Initialize on the first call. The contents of $_SERVER includes a mix of + // user-specific and system information that varies a little with each page. + if (!isset($random_state)) { + $random_state = print_r($_SERVER, true); + if (function_exists('getmypid')) { + // Further initialize with the somewhat random PHP process ID. + $random_state .= getmypid(); + } + $bytes = ''; + } + + do { + $random_state = hash('sha256', microtime() . mt_rand() . $random_state); + $bytes .= hash('sha256', mt_rand() . $random_state, true); + } while (strlen($bytes) < $count); + } + } + $output = substr($bytes, 0, $count); + $bytes = substr($bytes, $count); + return $output; +} + +/** + * Generates a random base 64-encoded salt prefixed with settings for the hash. + * + * Proper use of salts may defeat a number of attacks, including: + * - The ability to try candidate passwords against multiple hashes at once. + * - The ability to use pre-hashed lists of candidate passwords. + * - The ability to determine whether two users have the same (or different) + * password without actually having to guess one of the passwords. + * + * @param $count_log2 + * Integer that determines the number of iterations used in the hashing + * process. A larger value is more secure, but takes more time to complete. + * + * @return + * A 12 character string containing the iteration count and a random salt. + */ +function _password_generate_salt($count_log2) +{ + $output = '$S$'; + // Ensure that $count_log2 is within set bounds. + $count_log2 = _password_enforce_log2_boundaries($count_log2); + // We encode the final log2 iteration count in base 64. + $itoa64 = _password_itoa64(); + $output .= $itoa64[$count_log2]; + // 6 bytes is the standard salt for a portable phpass hash. + $output .= _password_base64_encode(_random_bytes(6), 6); + return $output; +} + +/** + * Ensures that $count_log2 is within set bounds. + * + * @param $count_log2 + * Integer that determines the number of iterations used in the hashing + * process. A larger value is more secure, but takes more time to complete. + * + * @return + * Integer within set bounds that is closest to $count_log2. + */ +function _password_enforce_log2_boundaries($count_log2) +{ + if ($count_log2 < MIN_HASH_COUNT) { + return MIN_HASH_COUNT; + } elseif ($count_log2 > MAX_HASH_COUNT) { + return MAX_HASH_COUNT; + } + + return (int)$count_log2; +} + +/** + * Hash a password using a secure stretched hash. + * + * By using a salt and repeated hashing the password is "stretched". Its + * security is increased because it becomes much more computationally costly + * for an attacker to try to break the hash by brute-force computation of the + * hashes of a large number of plain-text words or strings to find a match. + * + * @param $algo + * The string name of a hashing algorithm usable by hash(), like 'sha256'. + * @param $password + * Plain-text password up to 512 bytes (128 to 512 UTF-8 characters) to hash. + * @param $setting + * An existing hash or the output of _password_generate_salt(). Must be + * at least 12 characters (the settings and salt). + * + * @return + * A string containing the hashed password (and salt) or FALSE on failure. + * The return string will be truncated at DRUPAL_HASH_LENGTH characters max. + */ +function _password_crypt($algo, $password, $setting) +{ + // Prevent DoS attacks by refusing to hash large passwords. + if (strlen($password) > 512) { + return false; + } + // The first 12 characters of an existing hash are its setting string. + $setting = substr($setting, 0, 12); + + if ($setting[0] != '$' || $setting[2] != '$') { + return false; + } + $count_log2 = _password_get_count_log2($setting); + // Hashes may be imported from elsewhere, so we allow != DRUPAL_HASH_COUNT + if ($count_log2 < MIN_HASH_COUNT || $count_log2 > MAX_HASH_COUNT) { + return false; + } + $salt = substr($setting, 4, 8); + // Hashes must have an 8 character salt. + if (strlen($salt) != 8) { + return false; + } + + // Convert the base 2 logarithm into an integer. + $count = 1 << $count_log2; + + // We rely on the hash() function being available in PHP 5.2+. + $hash = hash($algo, $salt . $password, true); + do { + $hash = hash($algo, $hash . $password, true); + } while (--$count); + + $len = strlen($hash); + $output = $setting . _password_base64_encode($hash, $len); + // _password_base64_encode() of a 16 byte MD5 will always be 22 characters. + // _password_base64_encode() of a 64 byte sha512 will always be 86 characters. + $expected = 12 + ceil((8 * $len) / 6); + return (strlen($output) == $expected) ? substr($output, 0, HASH_LENGTH) : false; +} + +/** + * Parse the log2 iteration count from a stored hash or setting string. + */ +function _password_get_count_log2($setting) +{ + $itoa64 = _password_itoa64(); + return strpos($itoa64, $setting[3]); +} + +/** + * Hash a password using a secure hash. + * + * @param $password + * A plain-text password. + * @param $count_log2 + * Optional integer to specify the iteration count. Generally used only during + * mass operations where a value less than the default is needed for speed. + * + * @return + * A string containing the hashed password (and a salt), or FALSE on failure. + */ +function user_hash_password($password, $count_log2 = 0) +{ + if (empty($count_log2)) { + // Use the standard iteration count. + $count_log2 = variable_get('password_count_log2', DRUPAL_HASH_COUNT); + } + return _password_crypt('sha512', $password, _password_generate_salt($count_log2)); +} + +/** + * Check whether a plain text password matches a stored hashed password. + * + * @param $password + * A plain-text password + * @param $hashpass + * + * @return + * TRUE or FALSE. + */ +function user_check_password($password, $hashpass) +{ + $stored_hash = $hashpass; + $type = substr($stored_hash, 0, 3); + switch ($type) { + case '$S$': + // A normal Drupal 7 password using sha512. + $hash = _password_crypt('sha512', $password, $stored_hash); + break; + case '$H$': + // phpBB3 uses "$H$" for the same thing as "$P$". + case '$P$': + // A phpass password generated using md5. This is an + // imported password or from an earlier Drupal version. + $hash = _password_crypt('md5', $password, $stored_hash); + break; + default: + return false; + } + return ($hash && $stored_hash == $hash); +} diff --git a/lib/group_sql.php b/lib/group_sql.php index b0c1c06..8d06cd0 100644 --- a/lib/group_sql.php +++ b/lib/group_sql.php @@ -2,7 +2,6 @@ namespace OCA\user_sql; -use \OCA\user_sql\lib\Helper; use OCP\Util; class OC_GROUP_SQL extends \OC_Group_Backend implements \OCP\GroupInterface @@ -12,85 +11,78 @@ class OC_GROUP_SQL extends \OC_Group_Backend implements \OCP\GroupInterface public function __construct() { - $this -> helper = new \OCA\user_sql\lib\Helper(); + $this->helper = new \OCA\user_sql\lib\Helper(); $domain = \OC::$server->getRequest()->getServerHost(); - $this -> settings = $this -> helper -> loadSettingsForDomain($domain); - $this -> helper -> connectToDb($this -> settings); + $this->settings = $this->helper->loadSettingsForDomain($domain); + $this->helper->connectToDb($this->settings); return false; } - public function getUserGroups($uid) { - if(empty($this -> settings['sql_group_table'])) - { + public function getUserGroups($uid) + { + if (empty($this->settings['sql_group_table'])) { Util::writeLog('OC_USER_SQL', "Group table not configured", Util::DEBUG); return []; } - $rows = $this -> helper -> runQuery('getUserGroups', array('uid' => $uid), false, true); - if($rows === false) - { + $rows = $this->helper->runQuery('getUserGroups', array('uid' => $uid), false, true); + if ($rows === false) { Util::writeLog('OC_USER_SQL', "Found no group", Util::DEBUG); return []; } $groups = array(); - foreach($rows as $row) - { - $groups[] = $row[$this -> settings['col_group_name']]; - } + foreach ($rows as $row) { + $groups[] = $row[$this->settings['col_group_name']]; + } return $groups; } - public function getGroups($search = '', $limit = null, $offset = null) { - if(empty($this -> settings['sql_group_table'])) - { + public function getGroups($search = '', $limit = null, $offset = null) + { + if (empty($this->settings['sql_group_table'])) { return []; } - $search = "%".$search."%"; - $rows = $this -> helper -> runQuery('getGroups', array('search' => $search), false, true, array('limit' => $limit, 'offset' => $offset)); - if($rows === false) - { + $search = "%" . $search . "%"; + $rows = $this->helper->runQuery('getGroups', array('search' => $search), false, true, + array('limit' => $limit, 'offset' => $offset)); + if ($rows === false) { return []; - } + } $groups = array(); - foreach($rows as $row) - { - $groups[] = $row[$this -> settings['col_group_name']]; - } + foreach ($rows as $row) { + $groups[] = $row[$this->settings['col_group_name']]; + } return $groups; } - public function usersInGroup($gid, $search = '', $limit = null, $offset = null) { - if(empty($this -> settings['sql_group_table'])) - { + public function usersInGroup($gid, $search = '', $limit = null, $offset = null) + { + if (empty($this->settings['sql_group_table'])) { Util::writeLog('OC_USER_SQL', "Group table not configured", Util::DEBUG); return []; } - $rows = $this -> helper -> runQuery('getGroupUsers', array('gid' => $gid), false, true); - if($rows === false) - { + $rows = $this->helper->runQuery('getGroupUsers', array('gid' => $gid), false, true); + if ($rows === false) { Util::writeLog('OC_USER_SQL', "Found no users for group", Util::DEBUG); return []; } $users = array(); - foreach($rows as $row) - { - $users[] = $row[$this -> settings['col_group_username']]; - } + foreach ($rows as $row) { + $users[] = $row[$this->settings['col_group_username']]; + } return $users; } - public function countUsersInGroup($gid, $search = '') { - if(empty($this -> settings['sql_group_table'])) - { + public function countUsersInGroup($gid, $search = '') + { + if (empty($this->settings['sql_group_table'])) { return 0; } - $search = "%".$search."%"; - $count = $this -> helper -> runQuery('countUsersInGroup', array('gid' => $gid, 'search' => $search)); - if($count === false) - { + $search = "%" . $search . "%"; + $count = $this->helper->runQuery('countUsersInGroup', array('gid' => $gid, 'search' => $search)); + if ($count === false) { return 0; } else { return intval(reset($count)); } } } -?> diff --git a/lib/helper.php b/lib/helper.php index 0c0f782..b455e0a 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -1,7 +1,7 @@ @@ -22,10 +22,12 @@ */ namespace OCA\user_sql\lib; + use OCP\IConfig; use OCP\Util; -class Helper { +class Helper +{ protected $db; protected $db_conn; @@ -85,15 +87,13 @@ class Helper { { Util::writeLog('OC_USER_SQL', "Trying to load settings for domain: " . $domain, Util::DEBUG); $settings = array(); - $sql_host = \OC::$server->getConfig()->getAppValue('user_sql', 'sql_hostname_'.$domain, ''); - if($sql_host === '') - { + $sql_host = \OC::$server->getConfig()->getAppValue('user_sql', 'sql_hostname_' . $domain, ''); + if ($sql_host === '') { $domain = 'default'; } - $params = $this -> getParameterArray(); - foreach($params as $param) - { - $settings[$param] = \OC::$server->getConfig()->getAppValue('user_sql', $param.'_'.$domain, ''); + $params = $this->getParameterArray(); + foreach ($params as $param) { + $settings[$param] = \OC::$server->getConfig()->getAppValue('user_sql', $param . '_' . $domain, ''); } Util::writeLog('OC_USER_SQL', "Loaded settings for domain: " . $domain, Util::DEBUG); return $settings; @@ -111,159 +111,157 @@ class Helper { public function runQuery($type, $params, $execOnly = false, $fetchArray = false, $limits = array()) { Util::writeLog('OC_USER_SQL', "Entering runQuery for type: " . $type, Util::DEBUG); - if(!$this -> db_conn) + if (!$this->db_conn) { return false; + } - switch($type) - { + switch ($type) { case 'getHome': - $query = "SELECT ".$this->settings['col_gethome']." FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username']." = :uid"; - break; + $query = "SELECT " . $this->settings['col_gethome'] . " FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid"; + break; case 'getMail': - $query = "SELECT ".$this->settings['col_email']." FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username']." = :uid"; - break; + $query = "SELECT " . $this->settings['col_email'] . " FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid"; + break; case 'setMail': - $query = "UPDATE ".$this->settings['sql_table']." SET ".$this->settings['col_email']." = :currMail WHERE ".$this->settings['col_username']." = :uid"; - break; + $query = "UPDATE " . $this->settings['sql_table'] . " SET " . $this->settings['col_email'] . " = :currMail WHERE " . $this->settings['col_username'] . " = :uid"; + break; case 'getPass': - $query = "SELECT ".$this->settings['col_password']." FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username']." = :uid"; - if($this -> settings['col_active'] !== '') - $query .= " AND " .($this -> settings['set_active_invert'] === 'true' ? "NOT " : "" ) . $this -> settings['col_active']; - break; + $query = "SELECT " . $this->settings['col_password'] . " FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid"; + if ($this->settings['col_active'] !== '') { + $query .= " AND " . ($this->settings['set_active_invert'] === 'true' ? "NOT " : "") . $this->settings['col_active']; + } + break; case 'setPass': - $query = "UPDATE ".$this->settings['sql_table']." SET ".$this->settings['col_password']." = :enc_password WHERE ".$this->settings['col_username'] ." = :uid"; - break; + $query = "UPDATE " . $this->settings['sql_table'] . " SET " . $this->settings['col_password'] . " = :enc_password WHERE " . $this->settings['col_username'] . " = :uid"; + break; case 'getRedmineSalt': - $query = "SELECT salt FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username'] ." = :uid;"; - break; + $query = "SELECT salt FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid;"; + break; case 'countUsers': - $query = "SELECT COUNT(*) FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username'] ." LIKE :search"; - if($this -> settings['col_active'] !== '') - $query .= " AND " .($this -> settings['set_active_invert'] === 'true' ? "NOT " : "" ) . $this -> settings['col_active']; - break; + $query = "SELECT COUNT(*) FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " LIKE :search"; + if ($this->settings['col_active'] !== '') { + $query .= " AND " . ($this->settings['set_active_invert'] === 'true' ? "NOT " : "") . $this->settings['col_active']; + } + break; case 'getUsers': - $query = "SELECT ".$this->settings['col_username']." FROM ".$this->settings['sql_table']; - $query .= " WHERE ".$this->settings['col_username']." LIKE :search"; - if($this -> settings['col_active'] !== '') - $query .= " AND " .($this -> settings['set_active_invert'] === 'true' ? "NOT " : "" ) . $this -> settings['col_active']; - $query .= " ORDER BY ".$this->settings['col_username']; - break; + $query = "SELECT " . $this->settings['col_username'] . " FROM " . $this->settings['sql_table']; + $query .= " WHERE " . $this->settings['col_username'] . " LIKE :search"; + if ($this->settings['col_active'] !== '') { + $query .= " AND " . ($this->settings['set_active_invert'] === 'true' ? "NOT " : "") . $this->settings['col_active']; + } + $query .= " ORDER BY " . $this->settings['col_username']; + break; case 'userExists': - $query = "SELECT ".$this->settings['col_username']." FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username']." = :uid"; - if($this -> settings['col_active'] !== '') - $query .= " AND " .($this -> settings['set_active_invert'] === 'true' ? "NOT " : "" ) . $this -> settings['col_active']; - break; + $query = "SELECT " . $this->settings['col_username'] . " FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid"; + if ($this->settings['col_active'] !== '') { + $query .= " AND " . ($this->settings['set_active_invert'] === 'true' ? "NOT " : "") . $this->settings['col_active']; + } + break; case 'getDisplayName': - $query = "SELECT ".$this->settings['col_displayname']." FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username']." = :uid"; - if($this -> settings['col_active'] !== '') - $query .= " AND " .($this -> settings['set_active_invert'] === 'true' ? "NOT " : "" ) . $this -> settings['col_active']; - break; + $query = "SELECT " . $this->settings['col_displayname'] . " FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid"; + if ($this->settings['col_active'] !== '') { + $query .= " AND " . ($this->settings['set_active_invert'] === 'true' ? "NOT " : "") . $this->settings['col_active']; + } + break; case 'mysqlEncryptSalt': $query = "SELECT ENCRYPT(:pw, :salt);"; - break; + break; case 'mysqlEncrypt': $query = "SELECT ENCRYPT(:pw);"; - break; + break; case 'mysqlPassword': $query = "SELECT PASSWORD(:pw);"; - break; + break; case 'getUserGroups': - $query = "SELECT ".$this->settings['col_group_name']." FROM ".$this->settings['sql_group_table']." WHERE ".$this->settings['col_group_username']." = :uid"; - break; + $query = "SELECT " . $this->settings['col_group_name'] . " FROM " . $this->settings['sql_group_table'] . " WHERE " . $this->settings['col_group_username'] . " = :uid"; + break; case 'getGroups': - $query = "SELECT distinct ".$this->settings['col_group_name']." FROM ".$this->settings['sql_group_table']." WHERE ".$this->settings['col_group_name']." LIKE :search"; - break; + $query = "SELECT distinct " . $this->settings['col_group_name'] . " FROM " . $this->settings['sql_group_table'] . " WHERE " . $this->settings['col_group_name'] . " LIKE :search"; + break; case 'getGroupUsers': - $query = "SELECT distinct ".$this->settings['col_group_username']." FROM ".$this->settings['sql_group_table']." WHERE ".$this->settings['col_group_name']." = :gid"; - break; + $query = "SELECT distinct " . $this->settings['col_group_username'] . " FROM " . $this->settings['sql_group_table'] . " WHERE " . $this->settings['col_group_name'] . " = :gid"; + break; case 'countUsersInGroup': - $query = "SELECT count(".$this->settings['col_group_username'].") FROM ".$this->settings['sql_group_table']." WHERE ".$this->settings['col_group_name']." = :gid AND ".$this->settings['col_group_username']." LIKE :search"; - break; + $query = "SELECT count(" . $this->settings['col_group_username'] . ") FROM " . $this->settings['sql_group_table'] . " WHERE " . $this->settings['col_group_name'] . " = :gid AND " . $this->settings['col_group_username'] . " LIKE :search"; + break; } - if(isset($limits['limit']) && $limits['limit'] !== null) - { + if (isset($limits['limit']) && $limits['limit'] !== null) { $limit = intval($limits['limit']); - $query .= " LIMIT ".$limit; + $query .= " LIMIT " . $limit; } - if(isset($limits['offset']) && $limits['offset'] !== null) - { + if (isset($limits['offset']) && $limits['offset'] !== null) { $offset = intval($limits['offset']); - $query .= " OFFSET ".$offset; + $query .= " OFFSET " . $offset; } Util::writeLog('OC_USER_SQL', "Preparing query: $query", Util::DEBUG); - $result = $this -> db -> prepare($query); - foreach($params as $param => $value) - { - $result -> bindValue(":".$param, $value); + $result = $this->db->prepare($query); + foreach ($params as $param => $value) { + $result->bindValue(":" . $param, $value); } Util::writeLog('OC_USER_SQL', "Executing query...", Util::DEBUG); - if(!$result -> execute()) - { - $err = $result -> errorInfo(); + if (!$result->execute()) { + $err = $result->errorInfo(); Util::writeLog('OC_USER_SQL', "Query failed: " . $err[2], Util::DEBUG); return false; } - if($execOnly === true) - { + if ($execOnly === true) { return true; } Util::writeLog('OC_USER_SQL', "Fetching result...", Util::DEBUG); - if($fetchArray === true) - $row = $result -> fetchAll(); - else - $row = $result -> fetch(); + if ($fetchArray === true) { + $row = $result->fetchAll(); + } else { + $row = $result->fetch(); + } - if(!$row) - { + if (!$row) { return false; } return $row; } /** - * Connect to the database using ownCloud's DBAL + * Connect to the database using Nextcloud's DBAL * @param array $settings The settings for the connection * @return bool */ public function connectToDb($settings) { - $this -> settings = $settings; + $this->settings = $settings; $cm = new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig()); - $parameters = array('host' => $this -> settings['sql_hostname'], - 'password' => $this -> settings['sql_password'], - 'user' => $this -> settings['sql_username'], - 'dbname' => $this -> settings['sql_database'], - 'tablePrefix' => '' - ); - try - { - $this -> db = $cm -> getConnection($this -> settings['sql_driver'], $parameters); - $this -> db -> query("SET NAMES 'UTF8'"); - $this -> db_conn = true; + $parameters = array( + 'host' => $this->settings['sql_hostname'], + 'password' => $this->settings['sql_password'], + 'user' => $this->settings['sql_username'], + 'dbname' => $this->settings['sql_database'], + 'tablePrefix' => '' + ); + try { + $this->db = $cm->getConnection($this->settings['sql_driver'], $parameters); + $this->db->query("SET NAMES 'UTF8'"); + $this->db_conn = true; return true; - } - catch (\Exception $e) - { - Util::writeLog('OC_USER_SQL', 'Failed to connect to the database: ' . $e -> getMessage(), Util::ERROR); - $this -> db_conn = false; + } catch (\Exception $e) { + Util::writeLog('OC_USER_SQL', 'Failed to connect to the database: ' . $e->getMessage(), Util::ERROR); + $this->db_conn = false; return false; } } @@ -275,24 +273,24 @@ class Helper { * @param string $table The table name to check * @param array $cols The columns to check * @param array True if found, otherwise false + * @return bool|string */ public function verifyColumns($parameters, $sql_driver, $table, $cols) { $columns = $this->getColumns($parameters, $sql_driver, $table); $res = true; $err = ''; - foreach($cols as $col) - { - if(!in_array($col, $columns, true)) - { + foreach ($cols as $col) { + if (!in_array($col, $columns, true)) { $res = false; - $err .= $col.' '; + $err .= $col . ' '; } } - if($res) + if ($res) { return true; - else + } else { return $err; + } } /** @@ -301,6 +299,7 @@ class Helper { * @param string $sql_driver The SQL driver to use * @param string $table The table name to check * @param array True if found, otherwise false + * @return bool */ public function verifyTable($parameters, $sql_driver, $table) { @@ -320,8 +319,8 @@ class Helper { { $cm = new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig()); try { - $conn = $cm -> getConnection($sql_driver, $parameters); - $platform = $conn -> getDatabasePlatform(); + $conn = $cm->getConnection($sql_driver, $parameters); + $platform = $conn->getDatabasePlatform(); $queryTables = $platform->getListTablesSQL(); $queryViews = $platform->getListViewsSQL($parameters['dbname']); @@ -339,9 +338,7 @@ class Helper { $ret[] = $name; } return $ret; - } - catch(\Exception $e) - { + } catch (\Exception $e) { return array(); } } @@ -404,13 +401,12 @@ class Helper { { $cm = new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig()); try { - $conn = $cm -> getConnection($sql_driver, $parameters); - $platform = $conn -> getDatabasePlatform(); - $query = $platform -> getListTableColumnsSQL($table); - $result = $conn -> executeQuery($query); + $conn = $cm->getConnection($sql_driver, $parameters); + $platform = $conn->getDatabasePlatform(); + $query = $platform->getListTableColumnsSQL($table); + $result = $conn->executeQuery($query); $ret = array(); - while($row = $result -> fetch()) - { + while ($row = $result->fetch()) { switch ($sql_driver) { case 'mysql': $name = $row['Field']; @@ -424,12 +420,8 @@ class Helper { $ret[] = $name; } return $ret; - } - catch(\Exception $e) - { + } catch (\Exception $e) { return array(); } } - - } diff --git a/lib/user_sql.php b/lib/user_sql.php index 936dfbb..b696027 100644 --- a/lib/user_sql.php +++ b/lib/user_sql.php @@ -1,7 +1,7 @@ @@ -28,30 +28,31 @@ */ namespace OCA\user_sql; + use OC\User\Backend; -use \OCA\user_sql\lib\Helper; use OCP\IConfig; use OCP\IUser; use OCP\IUserSession; -use OCP\Notification\IManager as INotificationManager; use OCP\Util; -abstract class BackendUtility { +abstract class BackendUtility +{ protected $access; /** * constructor, make sure the subclasses call this one! * @param Access $access an instance of Access for LDAP interaction */ - public function __construct(Access $access) { + public function __construct(Access $access) + { $this->access = $access; } } class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, - \OCP\UserInterface + \OCP\UserInterface { protected $cache; protected $settings; @@ -66,26 +67,25 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function __construct() { $memcache = \OC::$server->getMemCacheFactory(); - if ( $memcache -> isAvailable()) - { - $this -> cache = $memcache -> create(); + if ($memcache->isAvailable()) { + $this->cache = $memcache->create(); } - $this -> helper = new \OCA\user_sql\lib\Helper(); + $this->helper = new \OCA\user_sql\lib\Helper(); $domain = \OC::$server->getRequest()->getServerHost(); - $this -> settings = $this -> helper -> loadSettingsForDomain($domain); - $this -> ocConfig = \OC::$server->getConfig(); - $this -> helper -> connectToDb($this -> settings); - $this -> session_cache_name = 'USER_SQL_CACHE'; + $this->settings = $this->helper->loadSettingsForDomain($domain); + $this->ocConfig = \OC::$server->getConfig(); + $this->helper->connectToDb($this->settings); + $this->session_cache_name = 'USER_SQL_CACHE'; return false; } /** - * Sync the user's E-Mail address with the address stored by ownCloud. + * Sync the user's E-Mail address with the address stored by Nextcloud. * We have three (four) sync modes: * - none: Does nothing - * - initial: Do the sync only once from SQL -> ownCloud - * - forcesql: The SQL database always wins and sync to ownCloud - * - forceoc: ownCloud always wins and syncs to SQL + * - initial: Do the sync only once from SQL -> Nextcloud + * - forcesql: The SQL database always wins and sync to Nextcloud + * - forceoc: Nextcloud always wins and syncs to SQL * * @param string $uid The user's ID to sync * @return bool Success or Fail @@ -93,56 +93,57 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, private function doEmailSync($uid) { Util::writeLog('OC_USER_SQL', "Entering doEmailSync for UID: $uid", - Util::DEBUG); - if($this -> settings['col_email'] === '') - return false; - - if($this -> settings['set_mail_sync_mode'] === 'none') - return false; - - $ocUid = $uid; - $uid = $this -> doUserDomainMapping($uid); - - $row = $this -> helper -> runQuery('getMail', array('uid' => $uid)); - if($row === false) - { + Util::DEBUG); + if ($this->settings['col_email'] === '') { return false; } - $newMail = $row[$this -> settings['col_email']]; - $currMail = $this->ocConfig->getUserValue( $ocUid, - 'settings', - 'email', ''); + if ($this->settings['set_mail_sync_mode'] === 'none') { + return false; + } - switch($this -> settings['set_mail_sync_mode']) - { + $ocUid = $uid; + $uid = $this->doUserDomainMapping($uid); + + $row = $this->helper->runQuery('getMail', array('uid' => $uid)); + if ($row === false) { + return false; + } + $newMail = $row[$this->settings['col_email']]; + + $currMail = $this->ocConfig->getUserValue($ocUid, + 'settings', + 'email', ''); + + switch ($this->settings['set_mail_sync_mode']) { case 'initial': - if($currMail === '') - $this->ocConfig->setUserValue( $ocUid, - 'settings', - 'email', - $newMail); + if ($currMail === '') { + $this->ocConfig->setUserValue($ocUid, + 'settings', + 'email', + $newMail); + } break; case 'forcesql': //if($currMail !== $newMail) - $this->ocConfig->setUserValue( $ocUid, - 'settings', - 'email', - $newMail); + $this->ocConfig->setUserValue($ocUid, + 'settings', + 'email', + $newMail); break; case 'forceoc': - if(($currMail !== '') && ($currMail !== $newMail)) - { - $row = $this -> helper -> runQuery('setMail', - array('uid' => $uid, - 'currMail' => $currMail) - , true); + if (($currMail !== '') && ($currMail !== $newMail)) { + $row = $this->helper->runQuery('setMail', + array( + 'uid' => $uid, + 'currMail' => $currMail + ) + , true); - if($row === false) - { + if ($row === false) { Util::writeLog('OC_USER_SQL', - "Could not update E-Mail address in SQL database!", - Util::ERROR); + "Could not update E-Mail address in SQL database!", + Util::ERROR); } } break; @@ -162,19 +163,17 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, { $uid = trim($uid); - if($this -> settings['set_default_domain'] !== '') - { - Util::writeLog('OC_USER_SQL', "Append default domain: ". - $this -> settings['set_default_domain'], Util::DEBUG); - if(strpos($uid, '@') === false) - { - $uid .= "@" . $this -> settings['set_default_domain']; + if ($this->settings['set_default_domain'] !== '') { + Util::writeLog('OC_USER_SQL', "Append default domain: " . + $this->settings['set_default_domain'], Util::DEBUG); + if (strpos($uid, '@') === false) { + $uid .= "@" . $this->settings['set_default_domain']; } } $uid = strtolower($uid); Util::writeLog('OC_USER_SQL', 'Returning mapped UID: ' . $uid, - Util::DEBUG); + Util::DEBUG); return $uid; } @@ -186,12 +185,12 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function implementsActions($actions) { return (bool)((Backend::CHECK_PASSWORD - | Backend::GET_DISPLAYNAME - | Backend::COUNT_USERS - | ($this -> settings['set_allow_pwchange'] === 'true' ? - Backend::SET_PASSWORD : 0) - | ($this -> settings['set_enable_gethome'] === 'true' ? - Backend::GET_HOME : 0) + | Backend::GET_DISPLAYNAME + | Backend::COUNT_USERS + | ($this->settings['set_allow_pwchange'] === 'true' ? + Backend::SET_PASSWORD : 0) + | ($this->settings['set_enable_gethome'] === 'true' ? + Backend::GET_HOME : 0) ) & $actions); } @@ -212,47 +211,46 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function getHome($uid) { Util::writeLog('OC_USER_SQL', "Entering getHome for UID: $uid", - Util::DEBUG); + Util::DEBUG); - if($this -> settings['set_enable_gethome'] !== 'true') + if ($this->settings['set_enable_gethome'] !== 'true') { return false; + } - $uidMapped = $this -> doUserDomainMapping($uid); + $uidMapped = $this->doUserDomainMapping($uid); $home = false; - switch($this->settings['set_gethome_mode']) - { + switch ($this->settings['set_gethome_mode']) { case 'query': Util::writeLog('OC_USER_SQL', - "getHome with Query selected, running Query...", - Util::DEBUG); - $row = $this -> helper -> runQuery('getHome', - array('uid' => $uidMapped)); - if($row === false) - { + "getHome with Query selected, running Query...", + Util::DEBUG); + $row = $this->helper->runQuery('getHome', + array('uid' => $uidMapped)); + if ($row === false) { Util::writeLog('OC_USER_SQL', - "Got no row, return false", - Util::DEBUG); + "Got no row, return false", + Util::DEBUG); return false; } - $home = $row[$this -> settings['col_gethome']]; - break; + $home = $row[$this->settings['col_gethome']]; + break; case 'static': Util::writeLog('OC_USER_SQL', - "getHome with static selected", - Util::DEBUG); - $home = $this -> settings['set_gethome']; + "getHome with static selected", + Util::DEBUG); + $home = $this->settings['set_gethome']; $home = str_replace('%ud', $uidMapped, $home); $home = str_replace('%u', $uid, $home); $home = str_replace('%d', - $this -> settings['set_default_domain'], - $home); - break; + $this->settings['set_default_domain'], + $home); + break; } Util::writeLog('OC_USER_SQL', - "Returning getHome for UID: $uid with Home $home", - Util::DEBUG); + "Returning getHome for UID: $uid with Home $home", + Util::DEBUG); return $home; } @@ -264,8 +262,8 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, { // Can't create user Util::writeLog('OC_USER_SQL', - 'Not possible to create local users from web'. - ' frontend using SQL user backend', Util::ERROR); + 'Not possible to create local users from web' . + ' frontend using SQL user backend', Util::ERROR); return false; } @@ -277,7 +275,7 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function deleteUser($uid) { // Can't delete user - Util::writeLog('OC_USER_SQL', 'Not possible to delete local users'. + Util::writeLog('OC_USER_SQL', 'Not possible to delete local users' . ' from web frontend using SQL user backend', Util::ERROR); return false; } @@ -286,7 +284,7 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, * Set (change) a user password * This can be enabled/disabled in the settings (set_allow_pwchange) * - * @param string $uid The user ID + * @param string $uid The user ID * @param string $password The user's new password * @return bool The return status */ @@ -295,109 +293,87 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, // Update the user's password - this might affect other services, that // use the same database, as well Util::writeLog('OC_USER_SQL', "Entering setPassword for UID: $uid", - Util::DEBUG); + Util::DEBUG); - if($this -> settings['set_allow_pwchange'] !== 'true') - return false; - - $uid = $this -> doUserDomainMapping($uid); - - $row = $this -> helper -> runQuery('getPass', array('uid' => $uid)); - if($row === false) - { + if ($this->settings['set_allow_pwchange'] !== 'true') { return false; } - $old_password = $row[$this -> settings['col_password']]; + + $uid = $this->doUserDomainMapping($uid); + + $row = $this->helper->runQuery('getPass', array('uid' => $uid)); + if ($row === false) { + return false; + } + $old_password = $row[$this->settings['col_password']]; // Added and disabled updating passwords for Drupal 7 WD 2018-01-04 - if($this -> settings['set_crypt_type'] === 'drupal') - { + if ($this->settings['set_crypt_type'] === 'drupal') { return false; - } - elseif($this -> settings['set_crypt_type'] === 'joomla2') - { - if(!class_exists('\PasswordHash')) + } elseif ($this->settings['set_crypt_type'] === 'joomla2') { + if (!class_exists('\PasswordHash')) { require_once('PasswordHash.php'); + } $hasher = new \PasswordHash(10, true); - $enc_password = $hasher -> HashPassword($password); + $enc_password = $hasher->HashPassword($password); } // Redmine stores the salt separatedly, this doesn't play nice with // the way we check passwords - elseif($this -> settings['set_crypt_type'] === 'redmine') - { - $salt = $this -> helper -> runQuery('getRedmineSalt', - array('uid' => $uid)); - if(!$salt) + elseif ($this->settings['set_crypt_type'] === 'redmine') { + $salt = $this->helper->runQuery('getRedmineSalt', + array('uid' => $uid)); + if (!$salt) { return false; - $enc_password = sha1($salt['salt'].sha1($password)); + } + $enc_password = sha1($salt['salt'] . sha1($password)); - } - elseif($this -> settings['set_crypt_type'] === 'sha1') - { + } elseif ($this->settings['set_crypt_type'] === 'sha1') { $enc_password = sha1($password); - } - elseif($this -> settings['set_crypt_type'] === 'system') - { - $prefix=substr($old_password,0,2); - if ($prefix==="$2") + } elseif ($this->settings['set_crypt_type'] === 'system') { + $prefix = substr($old_password, 0, 2); + if ($prefix === "$2") { + $enc_password = $this->pw_hash($password); + } else { + if (($prefix === "$1") or ($prefix[0] != "$")) //old md5 or DES { - $enc_password = $this->pw_hash($password); + //Update encryption algorithm + $prefix = "$6"; //change to sha512 } - else - { - if (($prefix==="$1") or ($prefix[0] != "$")) //old md5 or DES - { - //Update encryption algorithm - $prefix="$6"; //change to sha512 - } - $newsalt=$this->create_systemsalt(); - $enc_password=crypt($password,$prefix ."$" . $newsalt); + $newsalt = $this->create_systemsalt(); + $enc_password = crypt($password, $prefix . "$" . $newsalt); } + } elseif ($this->settings['set_crypt_type'] === 'password_hash') { + $enc_password = $this->pw_hash($password); + } elseif ($this->settings['set_crypt_type'] === 'courier_md5') { + $enc_password = '{MD5}' . OC_USER_SQL::hex_to_base64(md5($password)); + } elseif ($this->settings['set_crypt_type'] === 'courier_md5raw') { + $enc_password = '{MD5RAW}' . md5($password); + } elseif ($this->settings['set_crypt_type'] === 'courier_sha1') { + $enc_password = '{SHA}' . OC_USER_SQL::hex_to_base64(sha1($password)); + } elseif ($this->settings['set_crypt_type'] === 'courier_sha256') { + $enc_password = '{SHA256}' . OC_USER_SQL::hex_to_base64(hash('sha256', $password, false)); + } else { + $enc_password = $this->pacrypt($password, $old_password); } - elseif($this -> settings['set_crypt_type'] === 'password_hash') - { - $enc_password = $this->pw_hash($password); - } - elseif($this -> settings['set_crypt_type'] === 'courier_md5') - { - $enc_password = '{MD5}'.OC_USER_SQL::hex_to_base64(md5($password)); - } - elseif($this -> settings['set_crypt_type'] === 'courier_md5raw') - { - $enc_password = '{MD5RAW}'.md5($password); - } - elseif($this -> settings['set_crypt_type'] === 'courier_sha1') - { - $enc_password = '{SHA}'.OC_USER_SQL::hex_to_base64(sha1($password)); - } - elseif($this -> settings['set_crypt_type'] === 'courier_sha256') - { - $enc_password = '{SHA256}'.OC_USER_SQL::hex_to_base64(hash('sha256', $password, false)); - } - else - { - $enc_password = $this -> pacrypt($password, $old_password); - } - $res = $this -> helper -> runQuery('setPass', - array('uid' => $uid, 'enc_password' => $enc_password), - true); - if($res === false) - { + $res = $this->helper->runQuery('setPass', + array('uid' => $uid, 'enc_password' => $enc_password), + true); + if ($res === false) { Util::writeLog('OC_USER_SQL', "Could not update password!", - Util::ERROR); + Util::ERROR); return false; } Util::writeLog('OC_USER_SQL', - "Updated password successfully, return true", - Util::DEBUG); + "Updated password successfully, return true", + Util::DEBUG); return true; } /** * Check if the password is correct - * @param string $uid The username + * @param string $uid The username * @param string $password The password * @return bool true/false * @@ -406,94 +382,75 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function checkPassword($uid, $password) { Util::writeLog('OC_USER_SQL', - "Entering checkPassword() for UID: $uid", - Util::DEBUG); + "Entering checkPassword() for UID: $uid", + Util::DEBUG); - $uid = $this -> doUserDomainMapping($uid); + $uid = $this->doUserDomainMapping($uid); - $row = $this -> helper -> runQuery('getPass', array('uid' => $uid)); - if($row === false) - { - Util::writeLog('OC_USER_SQL', "Got no row, return false", Util::DEBUG); - return false; - } - $db_pass = $row[$this -> settings['col_password']]; + $row = $this->helper->runQuery('getPass', array('uid' => $uid)); + if ($row === false) { + Util::writeLog('OC_USER_SQL', "Got no row, return false", Util::DEBUG); + return false; + } + $db_pass = $row[$this->settings['col_password']]; Util::writeLog('OC_USER_SQL', "Encrypting and checking password", - Util::DEBUG); + Util::DEBUG); // Added handling for Drupal 7 passwords WD 2018-01-04 - if($this -> settings['set_crypt_type'] === 'drupal') - { - if(!function_exists('user_check_password')) + if ($this->settings['set_crypt_type'] === 'drupal') { + if (!function_exists('user_check_password')) { require_once('drupal.php'); + } $ret = user_check_password($password, $db_pass); } // Joomla 2.5.18 switched to phPass, which doesn't play nice with the // way we check passwords - elseif($this -> settings['set_crypt_type'] === 'joomla2') - { - if(!class_exists('\PasswordHash')) + elseif ($this->settings['set_crypt_type'] === 'joomla2') { + if (!class_exists('\PasswordHash')) { require_once('PasswordHash.php'); + } $hasher = new \PasswordHash(10, true); - $ret = $hasher -> CheckPassword($password, $db_pass); - } - elseif($this -> settings['set_crypt_type'] === 'password_hash') - { - $ret = password_verify($password,$db_pass); + $ret = $hasher->CheckPassword($password, $db_pass); + } elseif ($this->settings['set_crypt_type'] === 'password_hash') { + $ret = password_verify($password, $db_pass); } // Redmine stores the salt separatedly, this doesn't play nice with the // way we check passwords - elseif($this -> settings['set_crypt_type'] === 'redmine') - { - $salt = $this -> helper -> runQuery('getRedmineSalt', - array('uid' => $uid)); - if(!$salt) + elseif ($this->settings['set_crypt_type'] === 'redmine') { + $salt = $this->helper->runQuery('getRedmineSalt', + array('uid' => $uid)); + if (!$salt) { return false; - $ret = sha1($salt['salt'].sha1($password)) === $db_pass; + } + $ret = sha1($salt['salt'] . sha1($password)) === $db_pass; + } elseif ($this->settings['set_crypt_type'] == 'sha1') { + $ret = $this->hash_equals(sha1($password), $db_pass); + } elseif ($this->settings['set_crypt_type'] === 'courier_md5') { + $ret = '{MD5}' . OC_USER_SQL::hex_to_base64(md5($password)) === $db_pass; + } elseif ($this->settings['set_crypt_type'] === 'courier_md5raw') { + $ret = '{MD5RAW}' . md5($password) === $db_pass; + } elseif ($this->settings['set_crypt_type'] === 'courier_sha1') { + $ret = '{SHA}' . OC_USER_SQL::hex_to_base64(sha1($password)) === $db_pass; + } elseif ($this->settings['set_crypt_type'] === 'courier_sha256') { + $ret = '{SHA256}' . OC_USER_SQL::hex_to_base64(hash('sha256', $password, false)) === $db_pass; + } else { + // $ret = $this -> pacrypt($password, $db_pass) === $db_pass; + $ret = $this->hash_equals($this->pacrypt($password, $db_pass), + $db_pass); } - - elseif($this -> settings['set_crypt_type'] == 'sha1') - { - $ret = $this->hash_equals(sha1($password) , $db_pass); - } - elseif($this -> settings['set_crypt_type'] === 'courier_md5') - { - $ret = '{MD5}'.OC_USER_SQL::hex_to_base64(md5($password)) === $db_pass; - } - elseif($this -> settings['set_crypt_type'] === 'courier_md5raw') - { - $ret = '{MD5RAW}'.md5($password) === $db_pass; - } - elseif($this -> settings['set_crypt_type'] === 'courier_sha1') - { - $ret = '{SHA}'.OC_USER_SQL::hex_to_base64(sha1($password)) === $db_pass; - } - elseif($this -> settings['set_crypt_type'] === 'courier_sha256') - { - $ret = '{SHA256}'.OC_USER_SQL::hex_to_base64(hash('sha256', $password, false)) === $db_pass; - } else - - { - // $ret = $this -> pacrypt($password, $db_pass) === $db_pass; - $ret = $this->hash_equals($this -> pacrypt($password, $db_pass), - $db_pass); - } - if($ret) - { + if ($ret) { Util::writeLog('OC_USER_SQL', - "Passwords matching, return true", - Util::DEBUG); - if($this -> settings['set_strip_domain'] === 'true') - { + "Passwords matching, return true", + Util::DEBUG); + if ($this->settings['set_strip_domain'] === 'true') { $uid = explode("@", $uid); $uid = $uid[0]; } return $uid; - } else - { + } else { Util::writeLog('OC_USER_SQL', - "Passwords do not match, return false", - Util::DEBUG); + "Passwords do not match, return false", + Util::DEBUG); return false; } } @@ -505,68 +462,64 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function countUsers() { Util::writeLog('OC_USER_SQL', "Entering countUsers()", - Util::DEBUG); + Util::DEBUG); - $search = "%".$this -> doUserDomainMapping(""); - $userCount = $this -> helper -> runQuery('countUsers', - array('search' => $search)); - if($userCount === false) - { + $search = "%" . $this->doUserDomainMapping(""); + $userCount = $this->helper->runQuery('countUsers', + array('search' => $search)); + if ($userCount === false) { $userCount = 0; - } - else { + } else { $userCount = reset($userCount); } - Util::writeLog('OC_USER_SQL', "Return usercount: ".$userCount, - Util::DEBUG); + Util::writeLog('OC_USER_SQL', "Return usercount: " . $userCount, + Util::DEBUG); return $userCount; } /** * Get a list of all users * @param string $search The search term (can be empty) - * @param int $limit The search limit (can be null) - * @param int $offset The search offset (can be null) + * @param int $limit The search limit (can be null) + * @param int $offset The search offset (can be null) * @return array with all uids */ public function getUsers($search = '', $limit = null, $offset = null) { Util::writeLog('OC_USER_SQL', - "Entering getUsers() with Search: $search, ". - "Limit: $limit, Offset: $offset", Util::DEBUG); + "Entering getUsers() with Search: $search, " . + "Limit: $limit, Offset: $offset", Util::DEBUG); $users = array(); - if($search !== '') - { - $search = "%".$this -> doUserDomainMapping($search."%")."%"; - } - else - { - $search = "%".$this -> doUserDomainMapping("")."%"; + if ($search !== '') { + $search = "%" . $this->doUserDomainMapping($search . "%") . "%"; + } else { + $search = "%" . $this->doUserDomainMapping("") . "%"; } - $rows = $this -> helper -> runQuery('getUsers', - array('search' => $search), - false, - true, - array('limit' => $limit, - 'offset' => $offset)); - if($rows === false) + $rows = $this->helper->runQuery('getUsers', + array('search' => $search), + false, + true, + array( + 'limit' => $limit, + 'offset' => $offset + )); + if ($rows === false) { return array(); + } - foreach($rows as $row) - { - $uid = $row[$this -> settings['col_username']]; - if($this -> settings['set_strip_domain'] === 'true') - { + foreach ($rows as $row) { + $uid = $row[$this->settings['col_username']]; + if ($this->settings['set_strip_domain'] === 'true') { $uid = explode("@", $uid); $uid = $uid[0]; } $users[] = strtolower($uid); } Util::writeLog('OC_USER_SQL', "Return list of results", - Util::DEBUG); + Util::DEBUG); return $users; } @@ -579,36 +532,34 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, { $cacheKey = 'sql_user_exists_' . $uid; - $cacheVal = $this -> getCache ($cacheKey); + $cacheVal = $this->getCache($cacheKey); Util::writeLog('OC_USER_SQL', - "userExists() for UID: $uid cacheVal: $cacheVal", - Util::DEBUG); - if(!is_null($cacheVal)) + "userExists() for UID: $uid cacheVal: $cacheVal", + Util::DEBUG); + if (!is_null($cacheVal)) { return (bool)$cacheVal; + } Util::writeLog('OC_USER_SQL', - "Entering userExists() for UID: $uid", - Util::DEBUG); + "Entering userExists() for UID: $uid", + Util::DEBUG); // Only if the domain is removed for internal user handling, // we should add the domain back when checking existance - if($this -> settings['set_strip_domain'] === 'true') - { - $uid = $this -> doUserDomainMapping($uid); + if ($this->settings['set_strip_domain'] === 'true') { + $uid = $this->doUserDomainMapping($uid); } - $exists = (bool)$this -> helper -> runQuery('userExists', - array('uid' => $uid));; - $this -> setCache ($cacheKey, $exists, 60); + $exists = (bool)$this->helper->runQuery('userExists', + array('uid' => $uid));; + $this->setCache($cacheKey, $exists, 60); - if(!$exists) - { + if (!$exists) { Util::writeLog('OC_USER_SQL', - "Empty row, user does not exists, return false", - Util::DEBUG); + "Empty row, user does not exists, return false", + Util::DEBUG); return false; - } else - { + } else { Util::writeLog('OC_USER_SQL', "User exists, return true", Util::DEBUG); return true; @@ -624,45 +575,41 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function getDisplayName($uid) { Util::writeLog('OC_USER_SQL', - "Entering getDisplayName() for UID: $uid", - Util::DEBUG); + "Entering getDisplayName() for UID: $uid", + Util::DEBUG); - $this -> doEmailSync($uid); - $uid = $this -> doUserDomainMapping($uid); + $this->doEmailSync($uid); + $uid = $this->doUserDomainMapping($uid); - if(!$this -> userExists($uid)) - { + if (!$this->userExists($uid)) { return false; } - $row = $this -> helper -> runQuery('getDisplayName', - array('uid' => $uid)); + $row = $this->helper->runQuery('getDisplayName', + array('uid' => $uid)); - if(!$row) - { + if (!$row) { Util::writeLog('OC_USER_SQL', - "Empty row, user has no display name or ". - "does not exist, return false", - Util::DEBUG); + "Empty row, user has no display name or " . + "does not exist, return false", + Util::DEBUG); return false; - } else - { + } else { Util::writeLog('OC_USER_SQL', - "User exists, return true", - Util::DEBUG); - $displayName = $row[$this -> settings['col_displayname']]; - return $displayName; ; + "User exists, return true", + Util::DEBUG); + $displayName = $row[$this->settings['col_displayname']]; + return $displayName;; } return false; } public function getDisplayNames($search = '', $limit = null, $offset = null) { - $uids = $this -> getUsers($search, $limit, $offset); + $uids = $this->getUsers($search, $limit, $offset); $displayNames = array(); - foreach($uids as $uid) - { - $displayNames[$uid] = $this -> getDisplayName($uid); + foreach ($uids as $uid) { + $displayNames[$uid] = $this->getDisplayName($uid); } return $displayNames; } @@ -686,109 +633,90 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, * salt used - hence * the second parameter ($pw_db), which is the existing hash from the DB. * - * @param string $pw cleartext password - * @param string $pw_db encrypted password from database + * @param string $pw cleartext password + * @param string $pw_db encrypted password from database * @return string encrypted password. */ private function pacrypt($pw, $pw_db = "") { Util::writeLog('OC_USER_SQL', "Entering private pacrypt()", - Util::DEBUG); + Util::DEBUG); $pw = stripslashes($pw); $password = ""; $salt = ""; - if($this -> settings['set_crypt_type'] === 'md5crypt') - { + if ($this->settings['set_crypt_type'] === 'md5crypt') { $split_salt = preg_split('/\$/', $pw_db); - if(isset($split_salt[2])) - { + if (isset($split_salt[2])) { $salt = $split_salt[2]; } - $password = $this -> md5crypt($pw, $salt); - } elseif($this -> settings['set_crypt_type'] === 'md5') - { + $password = $this->md5crypt($pw, $salt); + } elseif ($this->settings['set_crypt_type'] === 'md5') { $password = md5($pw); - } elseif($this -> settings['set_crypt_type'] === 'system') - { + } elseif ($this->settings['set_crypt_type'] === 'system') { // We never generate salts, as user creation is not allowed here $password = crypt($pw, $pw_db); - } elseif($this -> settings['set_crypt_type'] === 'cleartext') - { + } elseif ($this->settings['set_crypt_type'] === 'cleartext') { $password = $pw; } // See // https://sourceforge.net/tracker/?func=detail&atid=937966&aid=1793352&group_id=191583 // this is apparently useful for pam_mysql etc. - elseif($this -> settings['set_crypt_type'] === 'mysql_encrypt') - { - if($pw_db !== "") - { + elseif ($this->settings['set_crypt_type'] === 'mysql_encrypt') { + if ($pw_db !== "") { $salt = substr($pw_db, 0, 2); - $row = $this -> helper -> runQuery('mysqlEncryptSalt', - array('pw' => $pw, 'salt' => $salt)); - } else - { - $row = $this -> helper -> runQuery('mysqlEncrypt', - array('pw' => $pw)); + $row = $this->helper->runQuery('mysqlEncryptSalt', + array('pw' => $pw, 'salt' => $salt)); + } else { + $row = $this->helper->runQuery('mysqlEncrypt', + array('pw' => $pw)); } - if($row === false) - { + if ($row === false) { return false; } $password = $row[0]; - } elseif($this -> settings['set_crypt_type'] === 'mysql_password') - { - $row = $this -> helper -> runQuery('mysqlPassword', - array('pw' => $pw)); + } elseif ($this->settings['set_crypt_type'] === 'mysql_password') { + $row = $this->helper->runQuery('mysqlPassword', + array('pw' => $pw)); - if($row === false) - { + if ($row === false) { return false; } $password = $row[0]; - } - - // The following is by Frédéric France - elseif($this -> settings['set_crypt_type'] === 'joomla') - { + } // The following is by Frédéric France + elseif ($this->settings['set_crypt_type'] === 'joomla') { $split_salt = preg_split('/:/', $pw_db); - if(isset($split_salt[1])) - { + if (isset($split_salt[1])) { $salt = $split_salt[1]; } $password = ($salt) ? md5($pw . $salt) : md5($pw); $password .= ':' . $salt; - } - - elseif($this-> settings['set_crypt_type'] === 'ssha256') - { + } elseif ($this->settings['set_crypt_type'] === 'ssha256') { $salted_password = base64_decode( - preg_replace('/{SSHA256}/i','',$pw_db)); - $salt = substr($salted_password,-(strlen($salted_password)-32)); - $password = $this->ssha256($pw,$salt); - } else - { + preg_replace('/{SSHA256}/i', '', $pw_db)); + $salt = substr($salted_password, -(strlen($salted_password) - 32)); + $password = $this->ssha256($pw, $salt); + } else { Util::writeLog('OC_USER_SQL', - "unknown/invalid crypt_type settings: ". - $this->settings['set_crypt_type'], - Util::ERROR); + "unknown/invalid crypt_type settings: " . + $this->settings['set_crypt_type'], + Util::ERROR); die('unknown/invalid Encryption type setting: ' . - $this -> settings['set_crypt_type']); + $this->settings['set_crypt_type']); } Util::writeLog('OC_USER_SQL', "pacrypt() done, return", - Util::DEBUG); + Util::DEBUG); return $password; } /** * md5crypt * Creates MD5 encrypted password - * @param string $pw The password to encrypt - * @param string $salt The salt to use + * @param string $pw The password to encrypt + * @param string $salt The salt to use * @param string $magic ? * @return string The encrypted password */ @@ -797,75 +725,72 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, { $MAGIC = "$1$"; - if($magic === "") + if ($magic === "") { $magic = $MAGIC; - if($salt === "") - $salt = $this -> create_md5salt(); + } + if ($salt === "") { + $salt = $this->create_md5salt(); + } $slist = explode("$", $salt); - if($slist[0] === "1") + if ($slist[0] === "1") { $salt = $slist[1]; + } $salt = substr($salt, 0, 8); $ctx = $pw . $magic . $salt; - $final = $this -> pahex2bin(md5($pw . $salt . $pw)); + $final = $this->pahex2bin(md5($pw . $salt . $pw)); - for($i = strlen($pw); $i > 0; $i -= 16) - { - if($i > 16) - { + for ($i = strlen($pw); $i > 0; $i -= 16) { + if ($i > 16) { $ctx .= substr($final, 0, 16); - } else - { + } else { $ctx .= substr($final, 0, $i); } } $i = strlen($pw); - while($i > 0) - { - if($i & 1) + while ($i > 0) { + if ($i & 1) { $ctx .= chr(0); - else + } else { $ctx .= $pw[0]; - $i = $i>>1; + } + $i = $i >> 1; } - $final = $this -> pahex2bin(md5($ctx)); + $final = $this->pahex2bin(md5($ctx)); - for($i = 0; $i < 1000; $i++) - { + for ($i = 0; $i < 1000; $i++) { $ctx1 = ""; - if($i & 1) - { + if ($i & 1) { $ctx1 .= $pw; - } else - { + } else { $ctx1 .= substr($final, 0, 16); } - if($i % 3) + if ($i % 3) { $ctx1 .= $salt; - if($i % 7) - $ctx1 .= $pw; - if($i & 1) - { - $ctx1 .= substr($final, 0, 16); - } else - { + } + if ($i % 7) { $ctx1 .= $pw; } - $final = $this -> pahex2bin(md5($ctx1)); + if ($i & 1) { + $ctx1 .= substr($final, 0, 16); + } else { + $ctx1 .= $pw; + } + $final = $this->pahex2bin(md5($ctx1)); } $passwd = ""; - $passwd .= $this -> to64(((ord($final[0])<<16) | - (ord($final[6])<<8) | (ord($final[12]))), 4); - $passwd .= $this -> to64(((ord($final[1])<<16) | - (ord($final[7])<<8) | (ord($final[13]))), 4); - $passwd .= $this -> to64(((ord($final[2])<<16) | - (ord($final[8])<<8) | (ord($final[14]))), 4); - $passwd .= $this -> to64(((ord($final[3])<<16) | - (ord($final[9])<<8) | (ord($final[15]))), 4); - $passwd .= $this -> to64(((ord($final[4])<<16) | - (ord($final[10])<<8) | (ord($final[5]))), 4); - $passwd .= $this -> to64(ord($final[11]), 2); + $passwd .= $this->to64(((ord($final[0]) << 16) | + (ord($final[6]) << 8) | (ord($final[12]))), 4); + $passwd .= $this->to64(((ord($final[1]) << 16) | + (ord($final[7]) << 8) | (ord($final[13]))), 4); + $passwd .= $this->to64(((ord($final[2]) << 16) | + (ord($final[8]) << 8) | (ord($final[14]))), 4); + $passwd .= $this->to64(((ord($final[3]) << 16) | + (ord($final[9]) << 8) | (ord($final[15]))), 4); + $passwd .= $this->to64(((ord($final[4]) << 16) | + (ord($final[10]) << 8) | (ord($final[5]))), 4); + $passwd .= $this->to64(ord($final[11]), 2); return "$magic$salt\$$passwd"; } @@ -875,20 +800,20 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, */ private function create_md5salt() { - srand((double) microtime() * 1000000); + srand((double)microtime() * 1000000); $salt = substr(md5(rand(0, 9999999)), 0, 8); return $salt; } /** * Encrypt using SSHA256 algorithm - * @param string $pw The password + * @param string $pw The password * @param string $salt The salt to use * @return string The hashed password, prefixed by {SSHA256} */ private function ssha256($pw, $salt) { - return '{SSHA256}'.base64_encode(hash('sha256',$pw.$salt,true).$salt); + return '{SSHA256}' . base64_encode(hash('sha256', $pw . $salt, true) . $salt); } /** @@ -898,15 +823,12 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, */ private function pahex2bin($str) { - if(function_exists('hex2bin')) - { + if (function_exists('hex2bin')) { return hex2bin($str); - } else - { + } else { $len = strlen($str); $nstr = ""; - for($i = 0; $i < $len; $i += 2) - { + for ($i = 0; $i < $len; $i += 2) { $num = sscanf(substr($str, $i, 2), "%x"); $nstr .= chr($num[0]); } @@ -919,36 +841,33 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, */ private function to64($v, $n) { - $ITOA64 = - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + $ITOA64 = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; $ret = ""; - while(($n - 1) >= 0) - { + while (($n - 1) >= 0) { $n--; $ret .= $ITOA64[$v & 0x3f]; - $v = $v>>6; + $v = $v >> 6; } return $ret; } /** * Store a value in memcache or the session, if no memcache is available - * @param string $key The key + * @param string $key The key * @param mixed $value The value to store * @param int $ttl (optional) defaults to 3600 seconds. */ - private function setCache($key, $value, $ttl=3600) + private function setCache($key, $value, $ttl = 3600) { - if ($this -> cache === NULL) - { - $_SESSION[$this -> session_cache_name][$key] = array( + if ($this->cache === null) { + $_SESSION[$this->session_cache_name][$key] = array( 'value' => $value, 'time' => time(), 'ttl' => $ttl, ); - } else - { - $this -> cache -> set($key,$value,$ttl); + } else { + $this->cache->set($key, $value, $ttl); } } @@ -960,26 +879,22 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, */ private function getCache($key) { - $retVal = NULL; - if ($this -> cache === NULL) - { - if (isset($_SESSION[$this -> session_cache_name], - $_SESSION[$this -> session_cache_name][$key])) - { - $value = $_SESSION[$this -> session_cache_name][$key]; - if (time() < $value['time'] + $value['ttl']) - { + $retVal = null; + if ($this->cache === null) { + if (isset($_SESSION[$this->session_cache_name], + $_SESSION[$this->session_cache_name][$key])) { + $value = $_SESSION[$this->session_cache_name][$key]; + if (time() < $value['time'] + $value['ttl']) { $retVal = $value['value']; } } - } else - { - $retVal = $this -> cache -> get ($key); + } else { + $retVal = $this->cache->get($key); } return $retVal; } - private function create_systemsalt($length=20) + private function create_systemsalt($length = 20) { $fp = fopen('/dev/urandom', 'r'); $randomString = fread($fp, $length); @@ -991,31 +906,32 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, private function pw_hash($password) { $options = [ - 'cost' => 10, - ]; + 'cost' => 10, + ]; return password_hash($password, PASSWORD_BCRYPT, $options); } - function hash_equals( $a, $b ) { - $a_length = strlen( $a ); + function hash_equals($a, $b) + { + $a_length = strlen($a); - if ( $a_length !== strlen( $b ) ) { + if ($a_length !== strlen($b)) { return false; - } - $result = 0; + } + $result = 0; // Do not attempt to "optimize" this. - for ( $i = 0; $i < $a_length; $i++ ) { - $result |= ord( $a[ $i ] ) ^ ord( $b[ $i ] ); + for ($i = 0; $i < $a_length; $i++) { + $result |= ord($a[$i]) ^ ord($b[$i]); } - //Hide the length of the string - $additional_length=200-($a_length % 200); - $tmp=0; - $c="abCD"; - for ( $i = 0; $i < $additional_length; $i++ ) { - $tmp |= ord( $c[ 0 ] ) ^ ord( $c[ 0 ] ); + //Hide the length of the string + $additional_length = 200 - ($a_length % 200); + $tmp = 0; + $c = "abCD"; + for ($i = 0; $i < $additional_length; $i++) { + $tmp |= ord($c[0]) ^ ord($c[0]); } return $result === 0; @@ -1024,11 +940,9 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, private static function hex_to_base64($hex) { $hex_chr = ''; - foreach(str_split($hex, 2) as $hexpair) - { + foreach (str_split($hex, 2) as $hexpair) { $hex_chr .= chr(hexdec($hexpair)); } return base64_encode($hex_chr); } - } diff --git a/templates/admin.php b/templates/admin.php index 4820559..5ff8a8e 100644 --- a/templates/admin.php +++ b/templates/admin.php @@ -1,181 +1,273 @@ t('SQL User Backend')); ?> - + - - t('Settings for Domain')) ?> - - - - - - - t('Connection Settings')); ?> - t('Column Settings')); ?> - t('E-Mail Settings')); ?> - t('Domain Settings')); ?> - t('getHome Settings')); ?> - t('Groups Settings')); ?> - + + t('Settings for Domain')) ?> + + + + + + + t('Connection Settings')); ?> + t('Column Settings')); ?> + t('E-Mail Settings')); ?> + t('Domain Settings')); ?> + t('getHome Settings')); ?> + t('Groups Settings')); ?> + - - t('SQL Driver')); ?> - 'MySQL', 'pgsql' => 'PostgreSQL'); ?> - - + t('SQL Driver')); ?> + 'MySQL', 'pgsql' => 'PostgreSQL'); ?> + + $name): //echo $_['sql_driver']; - if($_['sql_driver'] === $driver): ?> + if ($_['sql_driver'] === $driver): ?> - - + ?> + + - t('Host')); ?> + t('Host')); ?> + - t('Database')); ?> + t('Database')); ?> + - t('Username')); ?> + t('Username')); ?> + - t('Password')); ?> + t('Password')); ?> + - + - - - t('Table')); ?> + + + t('Table')); ?> + - t('Username Column')); ?> + t('Username Column')); ?> + - t('Password Column')); ?> + t('Password Column')); ?> + - t('Allow password changing (read README!)')); ?>> - t('Allow changing passwords. Imposes a security risk if password salts are not recreated.')); ?> - t('Only the encryption types "System","password_hash" and "Joomla2" are safe.')); ?> + + t('Allow password changing (read README!)')); ?>> + t('Allow changing passwords. Imposes a security risk if password salts are not recreated.')); ?> + + t('Only the encryption types "System","password_hash" and "Joomla2" are safe.')); ?> - t('Real Name Column')); ?> + t('Real Name Column')); ?> + - t('Encryption Type')); ?> - 'Drupal 7', 'md5' => 'MD5', 'md5crypt' => 'MD5 Crypt', 'cleartext' => 'Cleartext', 'mysql_encrypt' => 'mySQL ENCRYPT()', 'system' => 'System (crypt)', 'password_hash' => 'password_hash','mysql_password' => 'mySQL PASSWORD()', 'joomla' => 'Joomla MD5 Encryption', 'joomla2' => 'Joomla > 2.5.18 phpass', 'ssha256' => 'Salted SSHA256', 'redmine' => 'Redmine', 'sha1' => 'SHA1', 'courier_md5' => 'Courier base64-encoded MD5', 'courier_md5raw' => 'Courier hexadecimal MD5', 'courier_sha1' => 'Courier base64-encoded SHA1', 'courier_sha256' => 'Courier base64-encoded SHA256'); ?> - - t('Encryption Type')); ?> + 'Drupal 7', + 'md5' => 'MD5', + 'md5crypt' => 'MD5 Crypt', + 'cleartext' => 'Cleartext', + 'mysql_encrypt' => 'mySQL ENCRYPT()', + 'system' => 'System (crypt)', + 'password_hash' => 'password_hash', + 'mysql_password' => 'mySQL PASSWORD()', + 'joomla' => 'Joomla MD5 Encryption', + 'joomla2' => 'Joomla > 2.5.18 phpass', + 'ssha256' => 'Salted SSHA256', + 'redmine' => 'Redmine', + 'sha1' => 'SHA1', + 'courier_md5' => 'Courier base64-encoded MD5', + 'courier_md5raw' => 'Courier hexadecimal MD5', + 'courier_sha1' => 'Courier base64-encoded SHA1', + 'courier_sha256' => 'Courier base64-encoded SHA256' + ); ?> + + $name): //echo $_['set_crypt_type']; - if($_['set_crypt_type'] === $driver): ?> + if ($_['set_crypt_type'] === $driver): ?> - - + ?> + + - t('User Active Column')); ?> + t('User Active Column')); ?> + - t('Invert Active Value')); ?> /> - t("Invert the logic of the active column (for blocked users in the SQL DB)")); ?> + t('Invert Active Value')); ?> /> + t("Invert the logic of the active column (for blocked users in the SQL DB)")); ?> + - + - + - t('E-Mail Column')); ?> + t('E-Mail Column')); ?> + - t('E-Mail address sync mode')); ?> - 'No Synchronisation', 'initial' => 'Synchronise only once', 'forceoc' => 'Nextcloud always wins', 'forcesql' => 'SQL always wins'); ?> - - $name): - //echo $_['set_mail_sync_mode']; - if($_['set_mail_sync_mode'] === $mode): ?> - - - - - - + t('E-Mail address sync mode')); ?> + 'No Synchronisation', + 'initial' => 'Synchronise only once', + 'forceoc' => 'Nextcloud always wins', + 'forcesql' => 'SQL always wins' + ); ?> + + $name): + //echo $_['set_mail_sync_mode']; + if ($_['set_mail_sync_mode'] === $mode): ?> + + + + + + - + - + - t('Append Default Domain')); ?> - t('Append this string, e.g. a domain name, to each user name. The @-sign is automatically inserted.')); ?> - + t('Append Default Domain')); ?> + t('Append this string, e.g. a domain name, to each user name. The @-sign is automatically inserted.')); ?> + - t('Strip Domain Part from Username')); ?> /> - t("Strip Domain Part including @-sign from Username when logging in and retrieving username lists")); ?> + t('Strip Domain Part from Username')); ?> /> + t("Strip Domain Part including @-sign from Username when logging in and retrieving username lists")); ?> + - + - - t('Enable support for getHome()')); ?>/> + + t('Enable support for getHome()')); ?>/> - t('Method for getHome')); ?> - 'SQL Column', 'static' => 'Static (with Variables)'); ?> - - $name): - //echo $_['set_mail_sync_mode']; - if($_['set_gethome_mode'] === $mode): ?> - - - - - - + t('Method for getHome')); ?> + 'SQL Column', 'static' => 'Static (with Variables)'); ?> + + $name): + //echo $_['set_mail_sync_mode']; + if ($_['set_gethome_mode'] === $mode): ?> + + + + + + - t('Home Column')); ?> + t('Home Column')); ?> + - t('Home Dir')); ?> - t('You can use the placeholders %%u to specify the user ID (before appending the default domain), %%ud to specify the user ID (after appending the default domain) and %%d to specify the default domain')); ?> + t('Home Dir')); ?> + t('You can use the placeholders %%u to specify the user ID (before appending the default domain), %%ud to specify the user ID (after appending the default domain) and %%d to specify the default domain')); ?> + - - - t('Table')); ?> + + + t('Table')); ?> + - t('Username Column')); ?> + t('Username Column')); ?> + - t('Group Name Column')); ?> + t('Group Name Column')); ?> + - + - - - - t('Saving...')); ?> - t('Loading...')); ?> - t('Verifying...')); ?> - - - - + + + + t('Saving...')); ?> + t('Loading...')); ?> + t('Verifying...')); ?> + + + +
t('SQL Driver')); ?> - 'MySQL', 'pgsql' => 'PostgreSQL'); ?> - - + t('SQL Driver')); ?> + 'MySQL', 'pgsql' => 'PostgreSQL'); ?> + + $name): //echo $_['sql_driver']; - if($_['sql_driver'] === $driver): ?> + if ($_['sql_driver'] === $driver): ?> - - + ?> + +
t('SQL Driver')); ?> + 'MySQL', 'pgsql' => 'PostgreSQL'); ?> + + $name): //echo $_['sql_driver']; - if($_['sql_driver'] === $driver): ?> + if ($_['sql_driver'] === $driver): ?> - -
t('Host')); ?>
t('Host')); ?> +
t('Database')); ?>
t('Database')); ?> +
t('Username')); ?>
t('Username')); ?> +
t('Password')); ?>
t('Password')); ?> +
t('Table')); ?>
t('Table')); ?> +
t('Username Column')); ?>
t('Username Column')); ?> +
t('Password Column')); ?>
t('Password Column')); ?> +
t('Allow password changing (read README!)')); ?>> - t('Allow changing passwords. Imposes a security risk if password salts are not recreated.')); ?>
+ t('Allow password changing (read README!)')); ?>> + t('Allow changing passwords. Imposes a security risk if password salts are not recreated.')); ?> +
t('Real Name Column')); ?>
t('Real Name Column')); ?> +
t('Encryption Type')); ?> - 'Drupal 7', 'md5' => 'MD5', 'md5crypt' => 'MD5 Crypt', 'cleartext' => 'Cleartext', 'mysql_encrypt' => 'mySQL ENCRYPT()', 'system' => 'System (crypt)', 'password_hash' => 'password_hash','mysql_password' => 'mySQL PASSWORD()', 'joomla' => 'Joomla MD5 Encryption', 'joomla2' => 'Joomla > 2.5.18 phpass', 'ssha256' => 'Salted SSHA256', 'redmine' => 'Redmine', 'sha1' => 'SHA1', 'courier_md5' => 'Courier base64-encoded MD5', 'courier_md5raw' => 'Courier hexadecimal MD5', 'courier_sha1' => 'Courier base64-encoded SHA1', 'courier_sha256' => 'Courier base64-encoded SHA256'); ?> - - t('Encryption Type')); ?> + 'Drupal 7', + 'md5' => 'MD5', + 'md5crypt' => 'MD5 Crypt', + 'cleartext' => 'Cleartext', + 'mysql_encrypt' => 'mySQL ENCRYPT()', + 'system' => 'System (crypt)', + 'password_hash' => 'password_hash', + 'mysql_password' => 'mySQL PASSWORD()', + 'joomla' => 'Joomla MD5 Encryption', + 'joomla2' => 'Joomla > 2.5.18 phpass', + 'ssha256' => 'Salted SSHA256', + 'redmine' => 'Redmine', + 'sha1' => 'SHA1', + 'courier_md5' => 'Courier base64-encoded MD5', + 'courier_md5raw' => 'Courier hexadecimal MD5', + 'courier_sha1' => 'Courier base64-encoded SHA1', + 'courier_sha256' => 'Courier base64-encoded SHA256' + ); ?> + + $name): //echo $_['set_crypt_type']; - if($_['set_crypt_type'] === $driver): ?> + if ($_['set_crypt_type'] === $driver): ?> - -
t('User Active Column')); ?>
t('User Active Column')); ?> +
t('Invert Active Value')); ?> /> - t("Invert the logic of the active column (for blocked users in the SQL DB)")); ?>
t('Invert Active Value')); ?> /> + t("Invert the logic of the active column (for blocked users in the SQL DB)")); ?> +
t('E-Mail Column')); ?>
t('E-Mail Column')); ?> +
t('E-Mail address sync mode')); ?> - 'No Synchronisation', 'initial' => 'Synchronise only once', 'forceoc' => 'Nextcloud always wins', 'forcesql' => 'SQL always wins'); ?> - - $name): - //echo $_['set_mail_sync_mode']; - if($_['set_mail_sync_mode'] === $mode): ?> - - - - - -
t('E-Mail address sync mode')); ?> + 'No Synchronisation', + 'initial' => 'Synchronise only once', + 'forceoc' => 'Nextcloud always wins', + 'forcesql' => 'SQL always wins' + ); ?> + + $name): + //echo $_['set_mail_sync_mode']; + if ($_['set_mail_sync_mode'] === $mode): ?> + + + + + +
t('Append Default Domain')); ?> - t('Append this string, e.g. a domain name, to each user name. The @-sign is automatically inserted.')); ?> -
t('Append Default Domain')); ?> + t('Append this string, e.g. a domain name, to each user name. The @-sign is automatically inserted.')); ?> +
t('Strip Domain Part from Username')); ?> /> - t("Strip Domain Part including @-sign from Username when logging in and retrieving username lists")); ?>
t('Strip Domain Part from Username')); ?> /> + t("Strip Domain Part including @-sign from Username when logging in and retrieving username lists")); ?> +
t('Enable support for getHome()')); ?>/>
t('Method for getHome')); ?> - 'SQL Column', 'static' => 'Static (with Variables)'); ?> - - $name): - //echo $_['set_mail_sync_mode']; - if($_['set_gethome_mode'] === $mode): ?> - - - - - -
t('Method for getHome')); ?> + 'SQL Column', 'static' => 'Static (with Variables)'); ?> + + $name): + //echo $_['set_mail_sync_mode']; + if ($_['set_gethome_mode'] === $mode): ?> + + + + + +
t('Home Column')); ?>
t('Home Column')); ?> +
t('Home Dir')); ?> - t('You can use the placeholders %%u to specify the user ID (before appending the default domain), %%ud to specify the user ID (after appending the default domain) and %%d to specify the default domain')); ?>
t('Home Dir')); ?> + t('You can use the placeholders %%u to specify the user ID (before appending the default domain), %%ud to specify the user ID (after appending the default domain) and %%d to specify the default domain')); ?> +
t('Group Name Column')); ?>
t('Group Name Column')); ?> +