Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F1820913
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Size
72 KB
Subscribers
None
View Options
diff --git a/ajax/settings.php b/ajax/settings.php
--- a/ajax/settings.php
+++ b/ajax/settings.php
@@ -1,229 +1,237 @@
<?php
/**
* ownCloud - user_sql
*
* @author Andreas Böhler and contributors
* @copyright 2012-2015 Andreas Böhler <dev (at) aboehler (dot) at>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
/**
* 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
// Check if we are a user
\OCP\User::checkAdminUser();
\OCP\JSON::checkAppEnabled('user_sql');
// CSRF checks
\OCP\JSON::callCheck();
$helper = new \OCA\user_sql\lib\Helper;
$l = \OC::$server->getL10N('user_sql');
$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']))
{
$domain = $_POST['domain'];
switch($_POST['function'])
{
// Save the settings for the given domain to the database
case 'saveSettings':
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');
}
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');
+ }
}
}
$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, '');
}
$response->setData(array('status' => 'success',
'settings' => $retArr));
break;
// Try to verify the database connection settings
case 'verifySettings':
$cm = new \OC\DB\ConnectionFactory();
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'))));
break;
}
$parameters = array('host' => $_POST['sql_hostname'],
'password' => $_POST['sql_password'],
'user' => $_POST['sql_username'],
'dbname' => $_POST['sql_database'],
'tablePrefix' => ''
);
try {
$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())));
}
break;
// Get the autocompletion values for a column
case 'getColumnAutocomplete':
$cm = new \OC\DB\ConnectionFactory();
$search = $_POST['request'];
$table = $_POST['sql_table'];
$parameters = array('host' => $_POST['sql_hostname'],
'password' => $_POST['sql_password'],
'user' => $_POST['sql_username'],
'dbname' => $_POST['sql_database'],
'tablePrefix' => ''
);
try {
$conn = $cm -> getConnection($_POST['sql_driver'], $parameters);
$platform = $conn -> getDatabasePlatform();
$query = $platform -> getListTableColumnsSQL($table);
$result = $conn -> executeQuery($query);
$ret = array();
while($row = $result -> fetch())
{
$name = $row['Field'];
if(($search === '') || ($search === 'search') || (strpos($name, $search) === 0))
{
$ret[] = array('label' => $name,
'value' => $name);
}
}
$response -> setData($ret);
}
catch(\Exception $e)
{
$response->setData(array());
}
break;
// Get the autocompletion values for a table
case 'getTableAutocomplete':
$cm = new \OC\DB\ConnectionFactory();
$search = $_POST['request'];
$parameters = array('host' => $_POST['sql_hostname'],
'password' => $_POST['sql_password'],
'user' => $_POST['sql_username'],
'dbname' => $_POST['sql_database'],
'tablePrefix' => ''
);
try {
$conn = $cm -> getConnection($_POST['sql_driver'], $parameters);
$platform = $conn -> getDatabasePlatform();
$query = $platform -> getListTablesSQL();
$result = $conn -> executeQuery($query);
$ret = array();
while($row = $result -> fetch())
{
$name = $row['Tables_in_'.$_POST['sql_database']];
if(($search === '') || ($search === 'search') || (strpos($name, $search) === 0))
{
$ret[] = array('label' => $name,
'value' => $name);
}
}
$response -> setData($ret);
}
catch(\Exception $e)
{
$response->setData(array());
}
break;
}
} 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.'))));
}
// Return the JSON array
echo $response->render();
diff --git a/appinfo/app.php b/appinfo/app.php
--- a/appinfo/app.php
+++ b/appinfo/app.php
@@ -1,42 +1,32 @@
<?php
/**
* ownCloud - user_sql
*
* @author Andreas Böhler
* @copyright 2012-2015 Andreas Böhler <dev (at) aboehler (dot) at>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
require_once('apps/user_sql/user_sql.php');
\OCP\App::registerAdmin('user_sql','settings');
$backend = new \OCA\user_sql\OC_USER_SQL;
// register user backend
OC_User::registerBackend($backend);
OC_User::useBackend($backend);
-
-// add settings page to navigation
-$entry = array(
- 'id' => "user_sql_settings",
- 'order'=>1,
- 'href' => OC_Helper::linkTo( "user_sql", "settings.php" ),
- 'name' => 'SQL'
-);
-
-
diff --git a/appinfo/info.xml b/appinfo/info.xml
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -1,16 +1,16 @@
<?xml version="1.0"?>
<info>
<id>user_sql</id>
<name>SQL user backend</name>
<description>Authenticate Users by SQL</description>
<licence>AGPL</licence>
<author>Andreas Boehler <dev (at) aboehler
(dot) at ></author>
- <version>2.0</version>
+ <version>2.1</version>
<requiremin>8.1</requiremin>
<shipped>false</shipped>
<namespace>user_sql</namespace>
<types>
<authentication/>
</types>
</info>
diff --git a/css/settings.css b/css/settings.css
--- a/css/settings.css
+++ b/css/settings.css
@@ -1,14 +1,24 @@
.statusmessage {
background-color: #DDDDFF;
}
.errormessage {
background-color: #FFDDDD;
}
.successmessage {
background-color: #DDFFDD;
}
.statusmessage,.errormessage,.successmessage{
display:none;
padding: 1px;
}
+#sql-1 p label:first-child,
+#sql-2 p label:first-child,
+#sql-3 p label:first-child,
+#sql-4 p label:first-child,
+#sql-5 p label:first-child {
+ display: inline-block;
+ text-align: right;
+ width: 300px;
+ padding-right: 10px;
+}
diff --git a/js/settings.js b/js/settings.js
--- a/js/settings.js
+++ b/js/settings.js
@@ -1,266 +1,313 @@
// settings.js of user_sql
// declare namespace
var user_sql = user_sql ||
{
};
/**
* init admin settings view
*/
user_sql.adminSettingsUI = function()
{
if($('#sql').length > 0)
{
// enable tabs on settings page
$('#sql').tabs();
// Attach auto-completion to all column fields
- $('#col_username, #col_password, #col_displayname, #col_active, #col_email').autocomplete({
+ $('#col_username, #col_password, #col_displayname, #col_active, #col_email, #col_gethome').autocomplete({
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() {
$(this).attr('state', 'open');
},
close: function() {
$(this).attr('state', 'closed');
}
}).focus(function() {
if($(this).attr('state') != 'open')
{
$(this).autocomplete("search");
}
});
// Attach auto-completion to all table fields
$('#sql_table').autocomplete({
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() {
$(this).attr('state', 'open');
},
close: function() {
$(this).attr('state', 'closed');
}
}).focus(function() {
if($(this).attr('state') != 'open')
{
$(this).autocomplete("search");
}
});
// Verify the SQL database settings
$('#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
});
$('#sql_verify_message').show();
$('#sql_success_message').hide();
$('#sql_error_message').hide();
$('#sql_update_message').hide();
// Ajax foobar
$.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function(data)
{
$('#sql_verify_message').hide();
if(data.status == 'success')
{
$('#sql_success_message').html(data.data.message);
$('#sql_success_message').show();
window.setTimeout(function()
{
$('#sql_success_message').hide();
}, 10000);
} 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)
{
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
});
$('#sql_update_message').show();
$('#sql_success_message').hide();
$('#sql_verify_message').hide();
$('#sql_error_message').hide();
// Ajax foobar
$.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function(data)
{
$('#sql_update_message').hide();
if(data.status == 'success')
{
$('#sql_success_message').html(data.data.message);
$('#sql_success_message').show();
window.setTimeout(function()
{
$('#sql_success_message').hide();
}, 10000);
} else
{
$('#sql_error_message').html(data.data.message);
$('#sql_error_message').show();
}
}, 'json');
return false;
});
// Attach event handler to the domain chooser
$('#sql_domain_chooser').change(function() {
user_sql.loadDomainSettings($('#sql_domain_chooser option:selected').val());
});
+
+ $('#set_gethome_mode').change(function() {
+ user_sql.setGethomeMode();
+ });
+
+ $('#set_enable_gethome').change(function() {
+ user_sql.setGethomeMode();
+ });
+ }
+};
+
+user_sql.setGethomeMode = function()
+{
+ var enabled = $('#set_enable_gethome').prop('checked');
+ if(enabled)
+ {
+ $('#set_gethome_mode').prop('disabled', false);
+ var val = $('#set_gethome_mode option:selected').val();
+ if(val === 'query')
+ {
+ $('#set_gethome').prop('disabled', true);
+ $('#col_gethome').prop('disabled', false);
+ }
+ else if(val === 'static')
+ {
+ $('#set_gethome').prop('disabled', false);
+ $('#col_gethome').prop('disabled', true);
+ }
+ else
+ {
+ $('#set_gethome').prop('disabled', true);
+ $('#col_gethome').prop('disabled', true);
+ }
+ }
+ else
+ {
+ $('#set_gethome_mode').prop('disabled', true);
+ $('#set_gethome').prop('disabled', true);
+ $('#col_gethome').prop('disabled', true);
}
};
/**
* Load the settings for the selected domain
* @param string domain The domain to load
*/
user_sql.loadDomainSettings = function(domain)
{
$('#sql_success_message').hide();
$('#sql_error_message').hide();
$('#sql_verify_message').hide();
$('#sql_loading_message').show();
var post = [
{
name: 'appname',
value: 'user_sql'
},
{
name: 'function',
value: 'loadSettingsForDomain'
},
{
name: 'domain',
value: domain
}
];
$.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')
$('#' + key).prop('checked', true);
else
$('#' + key).prop('checked', false);
}
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')
$('#' + key).prop('checked', true);
else
$('#' + key).prop('checked', false);
}
+ else if(key == 'set_allow_gethome')
+ {
+ if(data.settings[key] == 'true')
+ $('#' + key).prop('checked', true);
+ else
+ $('#' + key).prop('checked', false);
+ }
else
{
$('#' + key).val(data.settings[key]);
}
}
}
else
{
$('#sql_error_message').html(data.data.message);
$('#sql_error_message').show();
}
}, 'json'
);
};
// Run our JS if the SQL settings are present
$(document).ready(function()
{
if($('#sql'))
{
user_sql.adminSettingsUI();
user_sql.loadDomainSettings($('#sql_domain_chooser option:selected').val());
+ user_sql.setGethomeMode();
}
});
diff --git a/lib/helper.php b/lib/helper.php
--- a/lib/helper.php
+++ b/lib/helper.php
@@ -1,244 +1,251 @@
<?php
/**
* ownCloud - user_sql
*
* @author Andreas Böhler and contributors
* @copyright 2012-2015 Andreas Böhler <dev (at) aboehler (dot) at>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\user_sql\lib;
class Helper {
protected $db;
protected $db_conn;
protected $settings;
/**
* The default constructor initializes some parameters
*/
public function __construct()
{
$this->db_conn = false;
}
/**
* Return an array with all supported parameters
* @return array Containing strings of the parameters
*/
public function getParameterArray()
{
$params = array(
'sql_hostname',
'sql_username',
'sql_password',
'sql_database',
'sql_table',
'sql_driver',
'col_username',
'col_password',
'col_active',
'col_displayname',
'col_email',
+ 'col_gethome',
'set_active_invert',
'set_allow_pwchange',
'set_default_domain',
'set_strip_domain',
'set_crypt_type',
- 'set_mail_sync_mode'
+ 'set_mail_sync_mode',
+ 'set_enable_gethome',
+ 'set_gethome_mode',
+ 'set_gethome'
);
return $params;
}
/**
* Load the settings for a given domain. If the domain is not found,
* the settings for 'default' are returned instead.
* @param string $domain The domain name
* @return array of settings
*/
public function loadSettingsForDomain($domain)
{
\OCP\Util::writeLog('OC_USER_SQL', "Trying to load settings for domain: " . $domain, \OCP\Util::DEBUG);
$settings = array();
$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, '');
}
\OCP\Util::writeLog('OC_USER_SQL', "Loaded settings for domain: " . $domain, \OCP\Util::DEBUG);
return $settings;
}
/**
* Run a given query type and return the results
* @param string $type The type of query to run
* @param array $params The parameter array of the query (i.e. the values to bind as key-value pairs)
* @param bool $execOnly Only execute the query, but don't fetch the results (optional, default = false)
* @param bool $fetchArray Fetch an array instead of a single row (optional, default=false)
* @param array $limits use the given limits for the query (optional, default = empty)
* @return mixed
*/
public function runQuery($type, $params, $execOnly = false, $fetchArray = false, $limits = array())
{
\OCP\Util::writeLog('OC_USER_SQL', "Entering runQuery for type: " . $type, \OCP\Util::DEBUG);
if(!$this -> db_conn)
return false;
switch($type)
{
+ case 'getHome':
+ $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;
case 'setMail':
$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;
case 'setPass':
$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;
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;
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;
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;
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;
case 'mysqlEncryptSalt':
$query = "SELECT ENCRYPT(:pw, :salt);";
break;
case 'mysqlEncrypt':
$query = "SELECT ENCRYPT(:pw);";
break;
case 'mysqlPassword':
$query = "SELECT PASSWORD(:pw);";
break;
}
if(isset($limits['limit']) && $limits['limit'] !== null)
{
$limit = intval($limits['limit']);
$query .= " LIMIT ".$limit;
}
if(isset($limits['offset']) && $limits['offset'] !== null)
{
$offset = intval($limits['offset']);
$query .= " OFFSET ".$offset;
}
\OCP\Util::writeLog('OC_USER_SQL', "Preparing query: $query", \OCP\Util::DEBUG);
$result = $this -> db -> prepare($query);
foreach($params as $param => $value)
{
$result -> bindValue(":".$param, $value);
}
\OCP\Util::writeLog('OC_USER_SQL', "Executing query...", \OCP\Util::DEBUG);
if(!$result -> execute())
{
$err = $result -> errorInfo();
\OCP\Util::writeLog('OC_USER_SQL', "Query failed: " . $err[2], \OCP\Util::DEBUG);
return false;
}
if($execOnly === true)
{
return true;
}
\OCP\Util::writeLog('OC_USER_SQL', "Fetching result...", \OCP\Util::DEBUG);
if($fetchArray === true)
$row = $result -> fetchAll();
else
$row = $result -> fetch();
if(!$row)
{
return false;
}
return $row;
}
/**
* Connect to the database using ownCloud's DBAL
* @param array $settings The settings for the connection
* @return bool
*/
public function connectToDb($settings)
{
$this -> settings = $settings;
$cm = new \OC\DB\ConnectionFactory();
$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)
{
\OCP\Util::writeLog('OC_USER_SQL', 'Failed to connect to the database: ' . $e -> getMessage(), \OCP\Util::ERROR);
$this -> db_conn = false;
return false;
}
}
}
diff --git a/templates/settings.php b/templates/settings.php
--- a/templates/settings.php
+++ b/templates/settings.php
@@ -1,110 +1,168 @@
<?php $ocVersion = $_['ocVersion'];
$cfgClass = $ocVersion >= 7 ? 'section' : 'personalblock';
?>
<div class="<?php p($cfgClass); ?>">
<h2><?php p($l->t('SQL')); ?></h2>
<form id="sqlForm" action="#" method="post" class="<?php p($cfgClass); ?>">
<div id="sql" class="<?php p($cfgClass); ?>">
<label for="sql_domain_chooser"><?php p($l -> t('Settings for Domain')) ?></label>
<select id="sql_domain_chooser" name="sql_domain_chooser">
<?php foreach ($_['allowed_domains'] as $domain): ?>
<option value="<?php p($domain); ?>"><?php p($domain); ?></option>
<?php endforeach ?>
</select>
<ul>
<li><a id="sqlBasicSettings" href="#sql-1"><?php p($l -> t('Connection Settings')); ?></a></li>
- <li><a id="sqlAdvSettings" href="#sql-2"><?php p($l -> t('Advanced Settings')); ?></a></li>
+ <li><a id="sqlColSettings" href="#sql-2"><?php p($l -> t('Column Settings')); ?></a></li>
+ <li><a id="sqlEmailSettings" href="#sql-3"><?php p($l -> t('E-Mail Settings')); ?></a></li>
+ <li><a id="sqlDomainSettings" href="#sql-4"><?php p($l -> t('Domain Settings')); ?></a></li>
+ <li><a id="sqlGethomeSettings" href="#sql-5"><?php p($l -> t('getHome Settings')); ?></a></li>
</ul>
<fieldset id="sql-1">
- <table>
- <tr><td><label for="sql_driver"><?php p($l -> t('SQL Driver')); ?></label></td>
+ <p><label for="sql_driver"><?php p($l -> t('SQL Driver')); ?></label>
<?php $db_driver = array('mysql' => 'MySQL', 'pgsql' => 'PostgreSQL'); ?>
- <td><select id="sql_driver" name="sql_driver">
+ <select id="sql_driver" name="sql_driver">
<?php
foreach ($db_driver as $driver => $name):
//echo $_['sql_driver'];
if($_['sql_driver'] === $driver): ?>
<option selected="selected" value="<?php p($driver); ?>"><?php p($name); ?></option>
<?php else: ?>
<option value="<?php p($driver); ?>"><?php p($name); ?></option>
<?php endif;
endforeach;
?>
- </select></td>
- </tr>
+ </select>
+ </p>
- <tr><td><label for="sql_hostname"><?php p($l -> t('Host')); ?></label></td><td><input type="text" id="sql_hostname" name="sql_hostname" value="<?php p($_['sql_hostname']); ?>"></td></tr>
- <tr><td><label for="sql_username"><?php p($l -> t('Username')); ?></label></td><td><input type="text" id="sql_username" name="sql_username" value="<?php p($_['sql_username']); ?>" /></td></tr>
- <tr><td><label for="sql_database"><?php p($l -> t('Database')); ?></label></td><td><input type="text" id="sql_database" name="sql_database" value="<?php p($_['sql_database']); ?>" /></td></tr>
- <tr><td><label for="sql_password"><?php p($l -> t('Password')); ?></label></td><td><input type="password" id="sql_password" name="sql_password" value="<?php p($_['sql_password']); ?>" /></td></tr>
- <tr><td></td><td><input type="submit" id="sqlVerify" value="<?php p($l -> t('Verify Settings')); ?>"></td></tr>
- </table>
+ <p><label for="sql_hostname"><?php p($l -> t('Host')); ?></label><input type="text" id="sql_hostname" name="sql_hostname" value="<?php p($_['sql_hostname']); ?>"></p>
+
+ <p><label for="sql_username"><?php p($l -> t('Username')); ?></label><input type="text" id="sql_username" name="sql_username" value="<?php p($_['sql_username']); ?>" /></p>
+
+ <p><label for="sql_database"><?php p($l -> t('Database')); ?></label><input type="text" id="sql_database" name="sql_database" value="<?php p($_['sql_database']); ?>" /></p>
+
+ <p><label for="sql_password"><?php p($l -> t('Password')); ?></label><input type="password" id="sql_password" name="sql_password" value="<?php p($_['sql_password']); ?>" /></p>
+
+ <p><input type="submit" id="sqlVerify" value="<?php p($l -> t('Verify Settings')); ?>"></p>
+
</fieldset>
<fieldset id="sql-2">
- <table>
- <tr><td><label for="sql_table"><?php p($l -> t('Table')); ?></label></td><td><input type="text" id="sql_table" name="sql_table" value="<?php p($_['sql_table']); ?>" /></td></tr>
- <tr><td><label for="col_username"><?php p($l -> t('Username Column')); ?></label></td><td><input type="text" id="col_username" name="col_username" value="<?php p($_['col_username']); ?>" /></td></tr>
- <tr><td><label for="col_password"><?php p($l -> t('Password Column')); ?></label></td><td><input type="text" id="col_password" name="col_password" value="<?php p($_['col_password']); ?>" /></td></tr>
- <tr><td><label for="set_allow_pwchange"><?php p($l -> t('Allow password changing (read README!)')); ?></label></td><td><input type="checkbox" id="set_allow_pwchange" name="set_allow_pwchange" value="1"<?php
+ <p><label for="sql_table"><?php p($l -> t('Table')); ?></label><input type="text" id="sql_table" name="sql_table" value="<?php p($_['sql_table']); ?>" /></p>
+
+ <p><label for="col_username"><?php p($l -> t('Username Column')); ?></label><input type="text" id="col_username" name="col_username" value="<?php p($_['col_username']); ?>" /></p>
+
+ <p><label for="col_password"><?php p($l -> t('Password Column')); ?></label><input type="text" id="col_password" name="col_password" value="<?php p($_['col_password']); ?>" /></p>
+
+ <p><label for="set_allow_pwchange"><?php p($l -> t('Allow password changing (read README!)')); ?></label><input type="checkbox" id="set_allow_pwchange" name="set_allow_pwchange" value="1"<?php
if($_['set_allow_pwchange'])
p(' checked');
- ?> title="Allow changing passwords. Imposes a security risk as password salts are not recreated"></td></tr>
- <tr><td><label for="col_displayname"><?php p($l -> t('Real Name Column')); ?></label></td><td><input type="text" id="col_displayname" name="col_displayname" value="<?php p($_['col_displayname']); ?>" /></td></tr>
- <tr><td><label for="set_crypt_type"><?php p($l -> t('Encryption Type')); ?></label></td>
+ ?>><br>
+ <em><?php p($l -> t('Allow changing passwords. Imposes a security risk as password salts are not recreated')); ?></em></p>
+
+ <p><label for="col_displayname"><?php p($l -> t('Real Name Column')); ?></label><input type="text" id="col_displayname" name="col_displayname" value="<?php p($_['col_displayname']); ?>" /></p>
+
+ <p><label for="set_crypt_type"><?php p($l -> t('Encryption Type')); ?></label>
<?php $crypt_types = array('md5' => 'MD5', 'md5crypt' => 'MD5 Crypt', 'cleartext' => 'Cleartext', 'mysql_encrypt' => 'mySQL ENCRYPT()', 'system' => 'System (crypt)', 'mysql_password' => 'mySQL PASSWORD()', 'joomla' => 'Joomla MD5 Encryption', 'joomla2' => 'Joomla > 2.5.18 phpass', 'ssha256' => 'Salted SSHA256', 'redmine' => 'Redmine'); ?>
- <td><select id="set_crypt_type" name="set_crypt_type">
+ <select id="set_crypt_type" name="set_crypt_type">
<?php
foreach ($crypt_types as $driver => $name):
//echo $_['set_crypt_type'];
if($_['set_crypt_type'] === $driver): ?>
<option selected="selected" value="<?php p($driver); ?>"><?php p($name); ?></option>
<?php else: ?>
<option value="<?php p($driver); ?>"><?php p($name); ?></option>
<?php endif;
endforeach;
?>
- </select></td>
- </tr>
- <tr><td><label for="col_active"><?php p($l -> t('User Active Column')); ?></label></td><td><input type="text" id="col_active" name="col_active" value="<?php p($_['col_active']); ?>" /></td></tr>
- <tr><td><label for="set_active_invert"><?php p($l -> t('Invert Active Value')); ?></label></td><td><input type="checkbox" id="set_active_invert" name="set_active_invert" value="1"<?php
+ </select>
+ </p>
+
+ <p><label for="col_active"><?php p($l -> t('User Active Column')); ?></label><input type="text" id="col_active" name="col_active" value="<?php p($_['col_active']); ?>" /></p>
+
+ <p><label for="set_active_invert"><?php p($l -> t('Invert Active Value')); ?></label><input type="checkbox" id="set_active_invert" name="set_active_invert" value="1"<?php
if($_['set_active_invert'])
p(' checked');
- ?> title="Invert the logic of the active column (for blocked users in the SQL DB)" /></td></tr>
- <tr><td><label for="col_email"><?php p($l -> t('E-Mail Column')); ?></label></td><td><input type="text" id="col_email" name="col_email" value="<?php p($_['col_email']); ?>" /></td></tr>
- <tr><td><label for="set_mail_sync_mode"><?php p($l -> t('E-Mail address sync mode')); ?></label></td>
+ ?> /><br>
+ <em><?php p($l -> t("Invert the logic of the active column (for blocked users in the SQL DB)")); ?></em></p>
+
+ </fieldset>
+
+ <fieldset id="sql-3">
+
+ <p><label for="col_email"><?php p($l -> t('E-Mail Column')); ?></label><input type="text" id="col_email" name="col_email" value="<?php p($_['col_email']); ?>" /></p>
+
+ <p><label for="set_mail_sync_mode"><?php p($l -> t('E-Mail address sync mode')); ?></label>
<?php $mail_modes = array('none' => 'No Synchronisation', 'initial' => 'Synchronise only once', 'forceoc' => 'ownCloud always wins', 'forcesql' => 'SQL always wins'); ?>
- <td><select id="set_mail_sync_mode" name="set_mail_sync_mode">
+ <select id="set_mail_sync_mode" name="set_mail_sync_mode">
<?php
foreach ($mail_modes as $mode => $name):
//echo $_['set_mail_sync_mode'];
if($_['set_mail_sync_mode'] === $mode): ?>
<option selected="selected" value="<?php p($mode); ?>"><?php p($name); ?></option>
<?php else: ?>
<option value="<?php p($mode); ?>"><?php p($name); ?></option>
<?php endif;
endforeach;
?>
</select>
- </td></tr>
- <tr><td><label for="set_default_domain"><?php p($l -> t('Append Default Domain')); ?></label></td><td><input type="text" id="set_default_domain", name="set_default_domain" value="<?php p($_['set_default_domain']); ?>" /></td></tr>
- <tr><td><label for="set_strip_domain"><?php p($l -> t('Strip Domain Part from Username')); ?></label></td><td><input type="checkbox" id="set_strip_domain" name="set_strip_domain" value="1"<?php
+ </p>
+
+ </fieldset>
+
+ <fieldset id="sql-4">
+
+ <p><label for="set_default_domain"><?php p($l -> t('Append Default Domain')); ?></label><input type="text" id="set_default_domain", name="set_default_domain" value="<?php p($_['set_default_domain']); ?>" /><br>
+ <em><?php p($l -> t('Append this string, e.g. a domain name, to each user name. The @-sign is automatically inserted.')); ?></em>
+ </p>
+
+ <p><label for="set_strip_domain"><?php p($l -> t('Strip Domain Part from Username')); ?></label><input type="checkbox" id="set_strip_domain" name="set_strip_domain" value="1"<?php
if($_['set_strip_domain'])
p(' checked');
- ?> title="Strip Domain Part from Username when logging in and retrieving username lists"></td></tr>
- </table>
+ ?> /><br>
+ <em><?php p($l -> t("Strip Domain Part including @-sign from Username when logging in and retrieving username lists")); ?></em></p>
+
+ </fieldset>
+
+ <fieldset id="sql-5">
+ <p><label for="set_enable_gethome"><?php p($l -> t('Enable support for getHome()')); ?></label><input type="checkbox" id="set_enable_gethome", name="set_enable_gethome" value="1" <?php
+ if($_['set_enable_gethome'])
+ p(' checked');
+ ?>/></p>
+
+ <p><label for="set_gethome_mode"><?php p($l -> t('Method for getHome')); ?></label>
+ <?php $gethome_modes = array('query' => 'SQL Column', 'static' => 'Static (with Variables)'); ?>
+ <select id="set_gethome_mode" name="set_gethome_mode">
+ <?php
+ foreach ($gethome_modes as $mode => $name):
+ //echo $_['set_mail_sync_mode'];
+ if($_['set_gethome_mode'] === $mode): ?>
+ <option selected="selected" value="<?php p($mode); ?>"><?php p($name); ?></option>
+ <?php else: ?>
+ <option value="<?php p($mode); ?>"><?php p($name); ?></option>
+ <?php endif;
+ endforeach;
+ ?>
+ </select>
+ </p>
+
+ <p><label for="col_gethome"><?php p($l -> t('Home Column')); ?></label><input type="text" id="col_gethome" name="col_gethome" value="<?php p($_['col_gethome']); ?>"></p>
+
+ <p><label for="set_gethome"><?php p($l -> t('Home Dir')); ?></label><input type="text" id="set_gethome" name="set_gethome" value="<?php p($_['set_gethome']); ?>"><br>
+ <em><?php p($l -> 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')); ?></em></p>
+
</fieldset>
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']); ?>" id="requesttoken" />
<input type="hidden" name="appname" value="user_sql" />
<input id="sqlSubmit" type="submit" value="<?php p($l -> t('Save')); ?>" />
<div id="sql_update_message" class="statusmessage"><?php p($l -> t('Saving...')); ?></div>
<div id="sql_loading_message" class="statusmessage"><?php p($l -> t('Loading...')); ?></div>
<div id="sql_verify_message" class="statusmessage"><?php p($l -> t('Verifying...')); ?></div>
<div id="sql_error_message" class="errormessage"></div>
<div id="sql_success_message" class="successmessage"></div>
</div>
</form>
</div>
diff --git a/user_sql.php b/user_sql.php
--- a/user_sql.php
+++ b/user_sql.php
@@ -1,733 +1,775 @@
<?php
/**
* ownCloud - user_sql
*
* @author Andreas Böhler and contributors
* @copyright 2012-2015 Andreas Böhler <dev (at) aboehler (dot) at>
*
* credits go to Ed W for several SQL injection fixes and caching support
* credits go to Frédéric France for providing Joomla support
* credits go to Mark Jansenn for providing Joomla 2.5.18+ / 3.2.1+ support
* credits go to Dominik Grothaus for providing SSHA256 support and fixing a few bugs
* credits go to Sören Eberhardt-Biermann for providing multi-host support
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\user_sql;
use \OCA\user_sql\lib\Helper;
class OC_USER_SQL extends \OC_User_Backend implements \OCP\IUserBackend, \OCP\UserInterface
{
protected $cache;
protected $settings;
protected $helper;
protected $session_cache_name;
/**
* The default constructor. It loads the settings for the given domain
* and tries to connect to the database.
*/
public function __construct()
{
$memcache = \OC::$server->getMemCacheFactory();
if ( $memcache -> isAvailable())
{
$this -> cache = $memcache -> create();
}
$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 -> session_cache_name = 'USER_SQL_CACHE';
return false;
}
/**
* Sync the user's E-Mail address with the address stored by ownCloud.
* 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
*
* @param string $uid The user's ID to sync
* @return bool Success or Fail
*/
private function doEmailSync($uid)
{
\OCP\Util::writeLog('OC_USER_SQL', "Entering doEmailSync for UID: $uid", \OCP\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)
{
return false;
}
$newMail = $row[$this -> settings['col_email']];
$currMail = \OCP\Config::getUserValue($ocUid, 'settings', 'email', '');
switch($this -> settings['set_mail_sync_mode'])
{
case 'initial':
if($currMail === '')
\OCP\Config::setUserValue($ocUid, 'settings', 'email', $newMail);
break;
case 'forcesql':
if($currMail !== $newMail)
\OCP\Config::setUserValue($ocUid, 'settings', 'email', $newMail);
break;
case 'forceoc':
if(($currMail !== '') && ($currMail !== $newMail))
{
$row = $this -> helper -> runQuery('setMail', array('uid' => $uid, 'currMail' => $currMail), true);
if($row === false)
{
\OCP\Util::writeLog('OC_USER_SQL', "Could not update E-Mail address in SQL database!", \OCP\Util::ERROR);
}
}
break;
}
return true;
}
/**
* This maps the username to the specified domain name.
* It can only append a default domain name.
*
* @param string $uid The UID to work with
* @return string The mapped UID
*/
private function doUserDomainMapping($uid)
{
$uid = trim($uid);
if($this -> settings['set_default_domain'] !== '')
{
\OCP\Util::writeLog('OC_USER_SQL', "Append default domain: ".$this -> settings['set_default_domain'], \OCP\Util::DEBUG);
if(strpos($uid, '@') === false)
{
$uid .= "@" . $this -> settings['set_default_domain'];
}
}
$uid = strtolower($uid);
\OCP\Util::writeLog('OC_USER_SQL', 'Returning mapped UID: ' . $uid, \OCP\Util::DEBUG);
return $uid;
}
/**
* Return the actions implemented by this backend
* @param $actions
* @return bool
*/
public function implementsAction($actions)
{
return (bool)((\OC_User_Backend::CHECK_PASSWORD
| \OC_User_Backend::GET_DISPLAYNAME
| \OC_User_Backend::COUNT_USERS
+ | $this -> settings['set_allow_pwchange'] === 'true' ? \OC_User_Backend::SET_PASSWORD : 0
+ | $this -> settings['set_enable_gethome'] === 'true' ? \OC_User_Backend::GET_HOME : 0
) & $actions);
}
/**
* Checks if this backend has user listing support
* @return bool
*/
public function hasUserListings()
{
return true;
}
+
+ /**
+ * Return the user's home directory, if enabled
+ * @param string $uid The user's ID to retrieve
+ * @return mixed The user's home directory or false
+ */
+ public function getHome($uid)
+ {
+ \OCP\Util::writeLog('OC_USER_SQL', "Entering getHome for UID: $uid", \OCP\Util::DEBUG);
+
+ if($this -> settings['set_enable_gethome'] !== 'true')
+ return false;
+
+ $uidMapped = $this -> doUserDomainMapping($uid);
+ $home = false;
+
+ switch($this->settings['set_gethome_mode'])
+ {
+ case 'query':
+ \OCP\Util::writeLog('OC_USER_SQL', "getHome with Query selected, running Query...", \OCP\Util::DEBUG);
+ $row = $this -> helper -> runQuery('getHome', array('uid' => $uidMapped));
+ if($row === false)
+ {
+ \OCP\Util::writeLog('OC_USER_SQL', "Got no row, return false", \OCP\Util::DEBUG);
+ return false;
+ }
+ $home = $row[$this -> settings['col_gethome']];
+ break;
+
+ case 'static':
+ \OCP\Util::writeLog('OC_USER_SQL', "getHome with static selected", \OCP\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;
+ }
+ \OCP\Util::writeLog('OC_USER_SQL', "Returning getHome for UID: $uid with Home $home", \OCP\Util::DEBUG);
+ return $home;
+ }
/**
* Create a new user account using this backend
* @return bool always false, as we can't create users
*/
public function createUser()
{
// Can't create user
\OCP\Util::writeLog('OC_USER_SQL', 'Not possible to create local users from web frontend using SQL user backend', \OCP\Util::ERROR);
return false;
}
/**
* Delete a user account using this backend
* @param string $uid The user's ID to delete
* @return bool always false, as we can't delete users
*/
public function deleteUser($uid)
{
// Can't delete user
\OCP\Util::writeLog('OC_USER_SQL', 'Not possible to delete local users from web frontend using SQL user backend', \OCP\Util::ERROR);
return false;
}
/**
* Set (change) a user password
* This can be enabled/disabled in the settings (set_allow_pwchange)
*
* @param string $uid The user ID
* @param string $password The user's new password
* @return bool The return status
*/
public function setPassword($uid, $password)
{
// Update the user's password - this might affect other services, that
// use the same database, as well
\OCP\Util::writeLog('OC_USER_SQL', "Entering setPassword for UID: $uid", \OCP\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)
{
return false;
}
$old_password = $row[$this -> settings['col_password']];
if($this -> settings['set_crypt_type'] === 'joomla2')
{
if(!class_exists('\PasswordHash'))
require_once('PasswordHash.php');
$hasher = new \PasswordHash(10, true);
$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)
return false;
$enc_password = sha1($salt['salt'].sha1($password));
} else
{
$enc_password = $this -> pacrypt($password, $old_password);
}
$res = $this -> helper -> runQuery('setPass', array('uid' => $uid, 'enc_password' => $enc_password), true);
if($res === false)
{
\OCP\Util::writeLog('OC_USER_SQL', "Could not update password!", \OCP\Util::ERROR);
return false;
}
\OCP\Util::writeLog('OC_USER_SQL', "Updated password successfully, return true", \OCP\Util::DEBUG);
return true;
}
/**
* Check if the password is correct
* @param string $uid The username
* @param string $password The password
* @return bool true/false
*
* Check if the password is correct without logging in the user
*/
public function checkPassword($uid, $password)
{
\OCP\Util::writeLog('OC_USER_SQL', "Entering checkPassword() for UID: $uid", \OCP\Util::DEBUG);
$uid = $this -> doUserDomainMapping($uid);
$row = $this -> helper -> runQuery('getPass', array('uid' => $uid));
if($row === false)
{
\OCP\Util::writeLog('OC_USER_SQL', "Got no row, return false", \OCP\Util::DEBUG);
return false;
}
$db_pass = $row[$this -> settings['col_password']];
\OCP\Util::writeLog('OC_USER_SQL', "Encrypting and checking password", \OCP\Util::DEBUG);
// Joomla 2.5.18 switched to phPass, which doesn't play nice with the way
// we check passwords
if($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);
}
// 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)
return false;
$ret = sha1($salt['salt'].sha1($password)) === $db_pass;
} else
{
$ret = $this -> pacrypt($password, $db_pass) === $db_pass;
}
if($ret)
{
\OCP\Util::writeLog('OC_USER_SQL', "Passwords matching, return true", \OCP\Util::DEBUG);
if($this -> settings['set_strip_domain'] === 'true')
{
$uid = explode("@", $uid);
$uid = $uid[0];
}
return $uid;
} else
{
\OCP\Util::writeLog('OC_USER_SQL', "Passwords do not match, return false", \OCP\Util::DEBUG);
return false;
}
}
/**
* Count the number of users
* @return int The user count
*/
public function countUsers()
{
\OCP\Util::writeLog('OC_USER_SQL', "Entering countUsers()", \OCP\Util::DEBUG);
$search = "%".$this -> doUserDomainMapping("");
$userCount = $this -> helper -> runQuery('countUsers', array('search' => $search));
if($userCount === false)
{
$userCount = 0;
}
else {
$userCount = reset($userCount);
}
\OCP\Util::writeLog('OC_USER_SQL', "Return usercount: ".$userCount, \OCP\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)
* @return array with all uids
*/
public function getUsers($search = '', $limit = null, $offset = null)
{
\OCP\Util::writeLog('OC_USER_SQL', "Entering getUsers() with Search: $search, Limit: $limit, Offset: $offset", \OCP\Util::DEBUG);
$users = array();
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)
return array();
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);
}
\OCP\Util::writeLog('OC_USER_SQL', "Return list of results", \OCP\Util::DEBUG);
return $users;
}
/**
* Check if a user exists
* @param string $uid the username
* @return boolean
*/
public function userExists($uid)
{
$cacheKey = 'sql_user_exists_' . $uid;
$cacheVal = $this -> getCache ($cacheKey);
\OCP\Util::writeLog('OC_USER_SQL', "userExists() for UID: $uid cacheVal: $cacheVal", \OCP\Util::DEBUG);
if(!is_null($cacheVal))
return (bool)$cacheVal;
\OCP\Util::writeLog('OC_USER_SQL', "Entering userExists() for UID: $uid", \OCP\Util::DEBUG);
$uid = $this -> doUserDomainMapping($uid);
$exists = (bool)$this -> helper -> runQuery('userExists', array('uid' => $uid));;
$this -> setCache ($cacheKey, $exists, 60);
if(!$exists)
{
\OCP\Util::writeLog('OC_USER_SQL', "Empty row, user does not exists, return false", \OCP\Util::DEBUG);
return false;
} else
{
\OCP\Util::writeLog('OC_USER_SQL', "User exists, return true", \OCP\Util::DEBUG);
return true;
}
}
/**
* Get the display name of the user
* @param string $uid The user ID
* @return mixed The user's display name or FALSE
*/
public function getDisplayName($uid)
{
\OCP\Util::writeLog('OC_USER_SQL', "Entering getDisplayName() for UID: $uid", \OCP\Util::DEBUG);
$this -> doEmailSync($uid);
$uid = $this -> doUserDomainMapping($uid);
if(!$this -> userExists($uid))
{
return false;
}
$row = $this -> helper -> runQuery('getDisplayName', array('uid' => $uid));
if(!$row)
{
\OCP\Util::writeLog('OC_USER_SQL', "Empty row, user has no display name or does not exist, return false", \OCP\Util::DEBUG);
return false;
} else
{
\OCP\Util::writeLog('OC_USER_SQL', "User exists, return true", \OCP\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);
$displayNames = array();
foreach($uids as $uid)
{
$displayNames[$uid] = $this -> getDisplayName($uid);
}
return $displayNames;
}
/**
* Returns the backend name
* @return string
*/
public function getBackendName()
{
return 'SQL';
}
/**
* The following functions were directly taken from PostfixAdmin and just
* slightly modified
* to suit our needs.
* Encrypt a password, using the apparopriate hashing mechanism as defined in
* config.inc.php ($this->crypt_type).
* When wanting to compare one pw to another, it's necessary to provide the
* 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
* @return string encrypted password.
*/
private function pacrypt($pw, $pw_db = "")
{
\OCP\Util::writeLog('OC_USER_SQL', "Entering private pacrypt()", \OCP\Util::DEBUG);
$pw = stripslashes($pw);
$password = "";
$salt = "";
if($this -> settings['set_crypt_type'] === 'md5crypt')
{
$split_salt = preg_split('/\$/', $pw_db);
if(isset($split_salt[2]))
{
$salt = $split_salt[2];
}
$password = $this -> md5crypt($pw, $salt);
} elseif($this -> settings['set_crypt_type'] === 'md5')
{
$password = md5($pw);
} 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')
{
$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 !== "")
{
$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));
}
if($row === false)
{
return false;
}
$password = $row[0];
} elseif($this -> settings['set_crypt_type'] === 'mysql_password')
{
$this -> helper -> runQuery('mysqlPassword', array('pw' => $pw));
if($row === false)
{
return false;
}
$password = $row[0];
}
// 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]))
{
$salt = $split_salt[1];
}
$password = ($salt) ? md5($pw . $salt) : md5($pw);
$password .= ':' . $salt;
}
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
{
\OCP\Util::writeLog('OC_USER_SQL', "unknown/invalid crypt_type settings: ".$this->settings['set_crypt_type'], \OCP\Util::ERROR);
die('unknown/invalid Encryption type setting: ' . $this -> settings['set_crypt_type']);
}
\OCP\Util::writeLog('OC_USER_SQL', "pacrypt() done, return", \OCP\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 $magic ?
* @return string The encrypted password
*/
private function md5crypt($pw, $salt = "", $magic = "")
{
$MAGIC = "$1$";
if($magic === "")
$magic = $MAGIC;
if($salt === "")
$salt = $this -> create_salt();
$slist = explode("$", $salt);
if($slist[0] === "1")
$salt = $slist[1];
$salt = substr($salt, 0, 8);
$ctx = $pw . $magic . $salt;
$final = $this -> pahex2bin(md5($pw . $salt . $pw));
for($i = strlen($pw); $i > 0; $i -= 16)
{
if($i > 16)
{
$ctx .= substr($final, 0, 16);
} else
{
$ctx .= substr($final, 0, $i);
}
}
$i = strlen($pw);
while($i > 0)
{
if($i & 1)
$ctx .= chr(0);
else
$ctx .= $pw[0];
$i = $i>>1;
}
$final = $this -> pahex2bin(md5($ctx));
for($i = 0; $i < 1000; $i++)
{
$ctx1 = "";
if($i & 1)
{
$ctx1 .= $pw;
} else
{
$ctx1 .= substr($final, 0, 16);
}
if($i % 3)
$ctx1 .= $salt;
if($i % 7)
$ctx1 .= $pw;
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);
return "$magic$salt\$$passwd";
}
/**
* Create a new salte
* @return string The salt
*/
private function create_salt()
{
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 $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);
}
/**
* PostfixAdmin's hex2bin function
* @param string $str The string to convert
* @return string The converted string
*/
private function pahex2bin($str)
{
if(function_exists('hex2bin'))
{
return hex2bin($str);
} else
{
$len = strlen($str);
$nstr = "";
for($i = 0; $i < $len; $i += 2)
{
$num = sscanf(substr($str, $i, 2), "%x");
$nstr .= chr($num[0]);
}
return $nstr;
}
}
/**
* Convert to 64?
*/
private function to64($v, $n)
{
$ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
$ret = "";
while(($n - 1) >= 0)
{
$n--;
$ret .= $ITOA64[$v & 0x3f];
$v = $v>>6;
}
return $ret;
}
/**
* Store a value in memcache or the session, if no memcache is available
* @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)
{
if ($this -> cache === NULL)
{
$_SESSION[$this -> session_cache_name][$key] = array(
'value' => $value,
'time' => time(),
'ttl' => $ttl,
);
} else
{
$this -> cache -> set($key,$value,$ttl);
}
}
/**
* Fetch a value from memcache or session, if memcache is not available.
* Returns NULL if there's no value stored or the value expired.
* @param string $key
* @return mixed|NULL
*/
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 = $value['value'];
}
}
} else
{
$retVal = $this -> cache -> get ($key);
}
return $retVal;
}
}
?>
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Dec 22, 9:28 PM (2 d, 21 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
527081
Default Alt Text
(72 KB)
Attached To
rUSQL ownCloud user_sql PlugIn
Event Timeline
Log In to Comment