Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F223263
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
139 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/plugins/password/drivers/chpasswd.php b/plugins/password/drivers/chpasswd.php
index 137275e69..45c56dba3 100644
--- a/plugins/password/drivers/chpasswd.php
+++ b/plugins/password/drivers/chpasswd.php
@@ -1,39 +1,54 @@
<?php
/**
- * chpasswd Driver
+ * chpasswd driver
*
* Driver that adds functionality to change the systems user password via
* the 'chpasswd' command.
*
* For installation instructions please read the README file.
*
* @version 2.0
* @author Alex Cartwright <acartwright@mutinydesign.co.uk>
+ *
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_chpasswd_password
{
public function save($currpass, $newpass)
{
$cmd = rcmail::get_instance()->config->get('password_chpasswd_cmd');
$username = $_SESSION['username'];
$handle = popen($cmd, "w");
fwrite($handle, "$username:$newpass\n");
if (pclose($handle) == 0) {
return PASSWORD_SUCCESS;
}
else {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: Unable to execute $cmd"
), true, false);
}
return PASSWORD_ERROR;
}
}
diff --git a/plugins/password/drivers/cpanel.php b/plugins/password/drivers/cpanel.php
index b71c33ec1..663c125ce 100644
--- a/plugins/password/drivers/cpanel.php
+++ b/plugins/password/drivers/cpanel.php
@@ -1,72 +1,87 @@
<?php
/**
* cPanel Password Driver
*
* Driver that adds functionality to change the users cPanel password.
* Originally written by Fulvio Venturelli <fulvio@venturelli.org>
*
* Completely rewritten using the cPanel API2 call Email::passwdpop
* as opposed to the original coding against the UI, which is a fragile method that
* makes the driver to always return a failure message for any language other than English
* see http://trac.roundcube.net/ticket/1487015
*
* This driver has been tested with o2switch hosting and seems to work fine.
*
* @version 3.0
* @author Christian Chech <christian@chech.fr>
+ *
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_cpanel_password
{
public function save($curpas, $newpass)
{
require_once 'xmlapi.php';
$rcmail = rcmail::get_instance();
$this->cuser = $rcmail->config->get('password_cpanel_username');
// Setup the xmlapi connection
$this->xmlapi = new xmlapi($rcmail->config->get('password_cpanel_host'));
$this->xmlapi->set_port($rcmail->config->get('password_cpanel_port'));
$this->xmlapi->password_auth($this->cuser, $rcmail->config->get('password_cpanel_password'));
$this->xmlapi->set_output('json');
$this->xmlapi->set_debug(0);
if ($this->setPassword($_SESSION['username'], $newpass)) {
return PASSWORD_SUCCESS;
}
else {
return PASSWORD_ERROR;
}
}
/**
* Change email account password
*
* Returns true on success or false on failure.
* @param string $password email account password
* @return bool
*/
function setPassword($address, $password)
{
if (strpos($address, '@')) {
list($data['email'], $data['domain']) = explode('@', $address);
}
else {
list($data['email'], $data['domain']) = array($address, '');
}
$data['password'] = $password;
$query = $this->xmlapi->api2_query($this->cuser, 'Email', 'passwdpop', $data);
$query = json_decode($query, true);
if ($query['cpanelresult']['data'][0]['result'] == 1) {
return true;
}
return false;
}
}
diff --git a/plugins/password/drivers/dbmail.php b/plugins/password/drivers/dbmail.php
index 5cfe92cd7..d76486021 100644
--- a/plugins/password/drivers/dbmail.php
+++ b/plugins/password/drivers/dbmail.php
@@ -1,42 +1,57 @@
<?php
/**
* DBMail Password Driver
*
* Driver that adds functionality to change the users DBMail password.
* The code is derrived from the Squirrelmail "Change SASL Password" Plugin
* by Galen Johnson.
*
* It only works with dbmail-users on the same host where Roundcube runs
* and requires shell access and gcc in order to compile the binary.
*
* For installation instructions please read the README file.
*
* @version 1.0
+ *
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_dbmail_password
{
function save($currpass, $newpass)
{
$curdir = RCUBE_PLUGINS_DIR . 'password/helpers';
$username = escapeshellcmd($_SESSION['username']);
$args = rcmail::get_instance()->config->get('password_dbmail_args', '');
exec("$curdir/chgdbmailusers -c $username -w $newpass $args", $output, $returnvalue);
if ($returnvalue == 0) {
return PASSWORD_SUCCESS;
}
else {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: Unable to execute $curdir/chgdbmailusers"
), true, false);
}
return PASSWORD_ERROR;
}
}
diff --git a/plugins/password/drivers/directadmin.php b/plugins/password/drivers/directadmin.php
index 44ecea406..08ade5130 100644
--- a/plugins/password/drivers/directadmin.php
+++ b/plugins/password/drivers/directadmin.php
@@ -1,488 +1,502 @@
<?php
/**
* DirectAdmin Password Driver
*
* Driver to change passwords via DirectAdmin Control Panel
*
* @version 2.1
* @author Victor Benincasa <vbenincasa@gmail.com>
*
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_directadmin_password
{
public function save($curpass, $passwd)
{
$rcmail = rcmail::get_instance();
$Socket = new HTTPSocket;
$da_user = $_SESSION['username'];
$da_curpass = $curpass;
$da_newpass = $passwd;
$da_host = $rcmail->config->get('password_directadmin_host');
$da_port = $rcmail->config->get('password_directadmin_port');
if (strpos($da_user, '@') === false) {
return array('code' => PASSWORD_ERROR, 'message' => 'Change the SYSTEM user password through control panel!');
}
$da_host = str_replace('%h', $_SESSION['imap_host'], $da_host);
$da_host = str_replace('%d', $rcmail->user->get_username('domain'), $da_host);
$Socket->connect($da_host,$da_port);
$Socket->set_method('POST');
$Socket->query('/CMD_CHANGE_EMAIL_PASSWORD',
array(
'email' => $da_user,
'oldpassword' => $da_curpass,
'password1' => $da_newpass,
'password2' => $da_newpass,
'api' => '1'
));
$response = $Socket->fetch_parsed_body();
//DEBUG
//rcube::console("Password Plugin: [USER: $da_user] [HOST: $da_host] - Response: [SOCKET: ".$Socket->result_status_code."] [DA ERROR: ".strip_tags($response['error'])."] [TEXT: ".$response[text]."]");
if($Socket->result_status_code != 200)
return array('code' => PASSWORD_CONNECT_ERROR, 'message' => $Socket->error[0]);
elseif($response['error'] == 1)
return array('code' => PASSWORD_ERROR, 'message' => strip_tags($response['text']));
else
return PASSWORD_SUCCESS;
}
}
/**
* Socket communication class.
*
* Originally designed for use with DirectAdmin's API, this class will fill any HTTP socket need.
*
* Very, very basic usage:
* $Socket = new HTTPSocket;
* echo $Socket->get('http://user:pass@somehost.com:2222/CMD_API_SOMEAPI?query=string&this=that');
*
* @author Phi1 'l0rdphi1' Stier <l0rdphi1@liquenox.net>
* @updates 2.7 and 2.8 by Victor Benincasa <vbenincasa @ gmail.com>
* @package HTTPSocket
* @version 2.8
*/
class HTTPSocket {
var $version = '2.8';
/* all vars are private except $error, $query_cache, and $doFollowLocationHeader */
var $method = 'GET';
var $remote_host;
var $remote_port;
var $remote_uname;
var $remote_passwd;
var $result;
var $result_header;
var $result_body;
var $result_status_code;
var $lastTransferSpeed;
var $bind_host;
var $error = array();
var $warn = array();
var $query_cache = array();
var $doFollowLocationHeader = TRUE;
var $redirectURL;
var $extra_headers = array();
/**
* Create server "connection".
*
*/
function connect($host, $port = '' )
{
if (!is_numeric($port))
{
$port = 2222;
}
$this->remote_host = $host;
$this->remote_port = $port;
}
function bind( $ip = '' )
{
if ( $ip == '' )
{
$ip = $_SERVER['SERVER_ADDR'];
}
$this->bind_host = $ip;
}
/**
* Change the method being used to communicate.
*
* @param string|null request method. supports GET, POST, and HEAD. default is GET
*/
function set_method( $method = 'GET' )
{
$this->method = strtoupper($method);
}
/**
* Specify a username and password.
*
* @param string|null username. defualt is null
* @param string|null password. defualt is null
*/
function set_login( $uname = '', $passwd = '' )
{
if ( strlen($uname) > 0 )
{
$this->remote_uname = $uname;
}
if ( strlen($passwd) > 0 )
{
$this->remote_passwd = $passwd;
}
}
/**
* Query the server
*
* @param string containing properly formatted server API. See DA API docs and examples. Http:// URLs O.K. too.
* @param string|array query to pass to url
* @param int if connection KB/s drops below value here, will drop connection
*/
function query( $request, $content = '', $doSpeedCheck = 0 )
{
$this->error = $this->warn = array();
$this->result_status_code = NULL;
// is our request a http(s):// ... ?
if (preg_match('/^(http|https):\/\//i',$request))
{
$location = parse_url($request);
$this->connect($location['host'],$location['port']);
$this->set_login($location['user'],$location['pass']);
$request = $location['path'];
$content = $location['query'];
if ( strlen($request) < 1 )
{
$request = '/';
}
}
$array_headers = array(
'User-Agent' => "HTTPSocket/$this->version",
'Host' => ( $this->remote_port == 80 ? parse_url($this->remote_host,PHP_URL_HOST) : parse_url($this->remote_host,PHP_URL_HOST).":".$this->remote_port ),
'Accept' => '*/*',
'Connection' => 'Close' );
foreach ( $this->extra_headers as $key => $value )
{
$array_headers[$key] = $value;
}
$this->result = $this->result_header = $this->result_body = '';
// was content sent as an array? if so, turn it into a string
if (is_array($content))
{
$pairs = array();
foreach ( $content as $key => $value )
{
$pairs[] = "$key=".urlencode($value);
}
$content = join('&',$pairs);
unset($pairs);
}
$OK = TRUE;
// instance connection
if ($this->bind_host)
{
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket,$this->bind_host);
if (!@socket_connect($socket,$this->remote_host,$this->remote_port))
{
$OK = FALSE;
}
}
else
{
$socket = @fsockopen( $this->remote_host, $this->remote_port, $sock_errno, $sock_errstr, 10 );
}
if ( !$socket || !$OK )
{
$this->error[] = "Can't create socket connection to $this->remote_host:$this->remote_port.";
return 0;
}
// if we have a username and password, add the header
if ( isset($this->remote_uname) && isset($this->remote_passwd) )
{
$array_headers['Authorization'] = 'Basic '.base64_encode("$this->remote_uname:$this->remote_passwd");
}
// for DA skins: if $this->remote_passwd is NULL, try to use the login key system
if ( isset($this->remote_uname) && $this->remote_passwd == NULL )
{
$array_headers['Cookie'] = "session={$_SERVER['SESSION_ID']}; key={$_SERVER['SESSION_KEY']}";
}
// if method is POST, add content length & type headers
if ( $this->method == 'POST' )
{
$array_headers['Content-type'] = 'application/x-www-form-urlencoded';
$array_headers['Content-length'] = strlen($content);
}
// else method is GET or HEAD. we don't support anything else right now.
else
{
if ($content)
{
$request .= "?$content";
}
}
// prepare query
$query = "$this->method $request HTTP/1.0\r\n";
foreach ( $array_headers as $key => $value )
{
$query .= "$key: $value\r\n";
}
$query .= "\r\n";
// if POST we need to append our content
if ( $this->method == 'POST' && $content )
{
$query .= "$content\r\n\r\n";
}
// query connection
if ($this->bind_host)
{
socket_write($socket,$query);
// now load results
while ( $out = socket_read($socket,2048) )
{
$this->result .= $out;
}
}
else
{
fwrite( $socket, $query, strlen($query) );
// now load results
$this->lastTransferSpeed = 0;
$status = socket_get_status($socket);
$startTime = time();
$length = 0;
while ( !feof($socket) && !$status['timed_out'] )
{
$chunk = fgets($socket,1024);
$length += strlen($chunk);
$this->result .= $chunk;
$elapsedTime = time() - $startTime;
if ( $elapsedTime > 0 )
{
$this->lastTransferSpeed = ($length/1024)/$elapsedTime;
}
if ( $doSpeedCheck > 0 && $elapsedTime > 5 && $this->lastTransferSpeed < $doSpeedCheck )
{
$this->warn[] = "kB/s for last 5 seconds is below 50 kB/s (~".( ($length/1024)/$elapsedTime )."), dropping connection...";
$this->result_status_code = 503;
break;
}
}
if ( $this->lastTransferSpeed == 0 )
{
$this->lastTransferSpeed = $length/1024;
}
}
list($this->result_header,$this->result_body) = preg_split("/\r\n\r\n/",$this->result,2);
if ($this->bind_host)
{
socket_close($socket);
}
else
{
fclose($socket);
}
$this->query_cache[] = $query;
$headers = $this->fetch_header();
// what return status did we get?
if (!$this->result_status_code)
{
preg_match("#HTTP/1\.. (\d+)#",$headers[0],$matches);
$this->result_status_code = $matches[1];
}
// did we get the full file?
if ( !empty($headers['content-length']) && $headers['content-length'] != strlen($this->result_body) )
{
$this->result_status_code = 206;
}
// now, if we're being passed a location header, should we follow it?
if ($this->doFollowLocationHeader)
{
if ($headers['location'])
{
$this->redirectURL = $headers['location'];
$this->query($headers['location']);
}
}
}
function getTransferSpeed()
{
return $this->lastTransferSpeed;
}
/**
* The quick way to get a URL's content :)
*
* @param string URL
* @param boolean return as array? (like PHP's file() command)
* @return string result body
*/
function get($location, $asArray = FALSE )
{
$this->query($location);
if ( $this->get_status_code() == 200 )
{
if ($asArray)
{
return preg_split("/\n/",$this->fetch_body());
}
return $this->fetch_body();
}
return FALSE;
}
/**
* Returns the last status code.
* 200 = OK;
* 403 = FORBIDDEN;
* etc.
*
* @return int status code
*/
function get_status_code()
{
return $this->result_status_code;
}
/**
* Adds a header, sent with the next query.
*
* @param string header name
* @param string header value
*/
function add_header($key,$value)
{
$this->extra_headers[$key] = $value;
}
/**
* Clears any extra headers.
*
*/
function clear_headers()
{
$this->extra_headers = array();
}
/**
* Return the result of a query.
*
* @return string result
*/
function fetch_result()
{
return $this->result;
}
/**
* Return the header of result (stuff before body).
*
* @param string (optional) header to return
* @return array result header
*/
function fetch_header( $header = '' )
{
$array_headers = preg_split("/\r\n/",$this->result_header);
$array_return = array( 0 => $array_headers[0] );
unset($array_headers[0]);
foreach ( $array_headers as $pair )
{
list($key,$value) = preg_split("/: /",$pair,2);
$array_return[strtolower($key)] = $value;
}
if ( $header != '' )
{
return $array_return[strtolower($header)];
}
return $array_return;
}
/**
* Return the body of result (stuff after header).
*
* @return string result body
*/
function fetch_body()
{
return $this->result_body;
}
/**
* Return parsed body in array format.
*
* @return array result parsed
*/
function fetch_parsed_body()
{
parse_str($this->result_body,$x);
return $x;
}
}
diff --git a/plugins/password/drivers/domainfactory.php b/plugins/password/drivers/domainfactory.php
index 62d9bfce2..95088e9dd 100644
--- a/plugins/password/drivers/domainfactory.php
+++ b/plugins/password/drivers/domainfactory.php
@@ -1,89 +1,100 @@
<?php
/**
* domainFACTORY Password Driver
*
* Driver to change passwords with the hosting provider domainFACTORY.
* http://www.df.eu/
*
* @version 2.1
* @author Till Krüss <me@tillkruess.com>
* @link http://tillkruess.com/projects/roundcube/
*
+ * Copyright (C) 2005-2014, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_domainfactory_password
{
- function save($curpass, $passwd)
- {
- $rcmail = rcmail::get_instance();
-
- if (is_null($curpass)) {
- $curpass = $rcmail->decrypt($_SESSION['password']);
- }
-
- if ($ch = curl_init()) {
-
- // initial login
- curl_setopt_array($ch, array(
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_URL => 'https://ssl.df.eu/chmail.php',
- CURLOPT_POST => true,
- CURLOPT_POSTFIELDS => http_build_query(array(
- 'login' => $rcmail->user->get_username(),
- 'pwd' => $curpass,
- 'action' => 'change'
- ))
- ));
-
- if ($result = curl_exec($ch)) {
- // login successful, get token!
- $postfields = array(
- 'pwd1' => $passwd,
- 'pwd2' => $passwd,
- 'action[update]' => 'Speichern'
- );
-
- preg_match_all('~<input name="(.+?)" type="hidden" value="(.+?)">~i', $result, $fields);
- foreach ($fields[1] as $field_key => $field_name) {
- $postfields[$field_name] = $fields[2][$field_key];
- }
-
- // change password
- $ch = curl_copy_handle($ch);
- curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields));
- if ($result = curl_exec($ch)) {
+ function save($curpass, $passwd)
+ {
+ $rcmail = rcmail::get_instance();
- // has the password been changed?
- if (strpos($result, 'Einstellungen erfolgreich') !== false) {
- return PASSWORD_SUCCESS;
- }
+ if (is_null($curpass)) {
+ $curpass = $rcmail->decrypt($_SESSION['password']);
+ }
- // show error message(s) if possible
- if (strpos($result, '<div class="d-msg-text">') !== false) {
- preg_match_all('#<div class="d-msg-text">(.*?)</div>#s', $result, $errors);
- if (isset($errors[1])) {
- $error_message = '';
- foreach ( $errors[1] as $error ) {
- $error_message .= trim(mb_convert_encoding( $error, 'UTF-8', 'ISO-8859-15' )).' ';
- }
- return array('code' => PASSWORD_ERROR, 'message' => $error_message);
- }
- }
+ if ($ch = curl_init()) {
+ // initial login
+ curl_setopt_array($ch, array(
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_URL => 'https://ssl.df.eu/chmail.php',
+ CURLOPT_POST => true,
+ CURLOPT_POSTFIELDS => http_build_query(array(
+ 'login' => $rcmail->user->get_username(),
+ 'pwd' => $curpass,
+ 'action' => 'change'
+ ))
+ ));
+ if ($result = curl_exec($ch)) {
+ // login successful, get token!
+ $postfields = array(
+ 'pwd1' => $passwd,
+ 'pwd2' => $passwd,
+ 'action[update]' => 'Speichern'
+ );
- } else {
- return PASSWORD_CONNECT_ERROR;
- }
+ preg_match_all('~<input name="(.+?)" type="hidden" value="(.+?)">~i', $result, $fields);
+ foreach ($fields[1] as $field_key => $field_name) {
+ $postfields[$field_name] = $fields[2][$field_key];
+ }
- } else {
- return PASSWORD_CONNECT_ERROR;
- }
+ // change password
+ $ch = curl_copy_handle($ch);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields));
+ if ($result = curl_exec($ch)) {
+ // has the password been changed?
+ if (strpos($result, 'Einstellungen erfolgreich') !== false) {
+ return PASSWORD_SUCCESS;
+ }
- } else {
- return PASSWORD_CONNECT_ERROR;
- }
+ // show error message(s) if possible
+ if (strpos($result, '<div class="d-msg-text">') !== false) {
+ preg_match_all('#<div class="d-msg-text">(.*?)</div>#s', $result, $errors);
+ if (isset($errors[1])) {
+ $error_message = '';
+ foreach ($errors[1] as $error) {
+ $error_message .= trim(mb_convert_encoding( $error, 'UTF-8', 'ISO-8859-15' )).' ';
+ }
+ return array('code' => PASSWORD_ERROR, 'message' => $error_message);
+ }
+ }
+ }
+ else {
+ return PASSWORD_CONNECT_ERROR;
+ }
+ }
+ else {
+ return PASSWORD_CONNECT_ERROR;
+ }
+ }
+ else {
+ return PASSWORD_CONNECT_ERROR;
+ }
- return PASSWORD_ERROR;
- }
+ return PASSWORD_ERROR;
+ }
}
diff --git a/plugins/password/drivers/expect.php b/plugins/password/drivers/expect.php
index 1f68924df..57fe905ee 100644
--- a/plugins/password/drivers/expect.php
+++ b/plugins/password/drivers/expect.php
@@ -1,58 +1,73 @@
<?php
/**
- * expect Driver
+ * expect driver
*
* Driver that adds functionality to change the systems user password via
* the 'expect' command.
*
* For installation instructions please read the README file.
*
* @version 2.0
* @author Andy Theuninck <gohanman@gmail.com)
- *
+ *
* Based on chpasswd roundcubemail password driver by
* @author Alex Cartwright <acartwright@mutinydesign.co.uk)
* and expect horde passwd driver by
* @author Gaudenz Steinlin <gaudenz@soziologie.ch>
*
* Configuration settings:
* password_expect_bin => location of expect (e.g. /usr/bin/expect)
* password_expect_script => path to "password-expect" file
* password_expect_params => arguments for the expect script
* see the password-expect file for details. This is probably
- * a good starting default:
+ * a good starting default:
* -telent -host localhost -output /tmp/passwd.log -log /tmp/passwd.log
+ *
+ * Copyright (C) 2005-2014, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_expect_password
{
public function save($currpass, $newpass)
{
$rcmail = rcmail::get_instance();
$bin = $rcmail->config->get('password_expect_bin');
$script = $rcmail->config->get('password_expect_script');
$params = $rcmail->config->get('password_expect_params');
$username = $_SESSION['username'];
$cmd = $bin . ' -f ' . $script . ' -- ' . $params;
$handle = popen($cmd, "w");
fwrite($handle, "$username\n");
fwrite($handle, "$currpass\n");
fwrite($handle, "$newpass\n");
if (pclose($handle) == 0) {
return PASSWORD_SUCCESS;
}
else {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: Unable to execute $cmd"
), true, false);
}
return PASSWORD_ERROR;
}
}
diff --git a/plugins/password/drivers/gearman.php b/plugins/password/drivers/gearman.php
index 36571a98f..983aee046 100644
--- a/plugins/password/drivers/gearman.php
+++ b/plugins/password/drivers/gearman.php
@@ -1,55 +1,70 @@
<?php
/**
* Gearman Password Driver
*
* Payload is json string containing username, oldPassword and newPassword
* Return value is a json string saying result: true if success.
*
* @version 1.0
* @author Mohammad Anwari <mdamt@mdamt.net>
+ *
+ * Copyright (C) 2005-2014, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_gearman_password
{
function save($currpass, $newpass)
{
if (extension_loaded('gearman')) {
$rcmail = rcmail::get_instance();
$user = $_SESSION['username'];
$payload = array(
'username' => $user,
'oldPassword' => $currpass,
'newPassword' => $newpass,
);
$gmc = new GearmanClient();
$gmc->addServer($rcmail->config->get('password_gearman_host'));
$result = $gmc->doNormal('setPassword', json_encode($payload));
$success = json_decode($result);
if ($success && $success->result == 1) {
return PASSWORD_SUCCESS;
}
else {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: Gearman authentication failed for user $user: $error"
), true, false);
}
}
else {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: PECL Gearman module not loaded"
), true, false);
}
return PASSWORD_ERROR;
}
}
diff --git a/plugins/password/drivers/hmail.php b/plugins/password/drivers/hmail.php
index 650434617..49f7f6cf4 100644
--- a/plugins/password/drivers/hmail.php
+++ b/plugins/password/drivers/hmail.php
@@ -1,61 +1,76 @@
<?php
/**
* hMailserver password driver
*
* @version 2.0
* @author Roland 'rosali' Liebl <myroundcube@mail4us.net>
+ *
+ * Copyright (C) 2005-2014, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_hmail_password
{
public function save($curpass, $passwd)
{
$rcmail = rcmail::get_instance();
if ($curpass == '' || $passwd == '') {
return PASSWORD_ERROR;
}
try {
$remote = $rcmail->config->get('hmailserver_remote_dcom', false);
if ($remote)
$obApp = new COM("hMailServer.Application", $rcmail->config->get('hmailserver_server'));
else
$obApp = new COM("hMailServer.Application");
}
catch (Exception $e) {
rcube::write_log('errors', "Plugin password (hmail driver): " . trim(strip_tags($e->getMessage())));
rcube::write_log('errors', "Plugin password (hmail driver): This problem is often caused by DCOM permissions not being set.");
return PASSWORD_ERROR;
}
$username = $rcmail->user->data['username'];
if (strstr($username,'@')){
$temparr = explode('@', $username);
$domain = $temparr[1];
}
else {
$domain = $rcmail->config->get('username_domain',false);
if (!$domain) {
rcube::write_log('errors','Plugin password (hmail driver): $config[\'username_domain\'] is not defined.');
return PASSWORD_ERROR;
}
$username = $username . "@" . $domain;
}
$obApp->Authenticate($username, $curpass);
try {
$obDomain = $obApp->Domains->ItemByName($domain);
$obAccount = $obDomain->Accounts->ItemByAddress($username);
$obAccount->Password = $passwd;
$obAccount->Save();
return PASSWORD_SUCCESS;
}
catch (Exception $e) {
rcube::write_log('errors', "Plugin password (hmail driver): " . trim(strip_tags($e->getMessage())));
rcube::write_log('errors', "Plugin password (hmail driver): This problem is often caused by DCOM permissions not being set.");
return PASSWORD_ERROR;
}
}
}
diff --git a/plugins/password/drivers/ldap.php b/plugins/password/drivers/ldap.php
index cc62595b5..0c932372d 100644
--- a/plugins/password/drivers/ldap.php
+++ b/plugins/password/drivers/ldap.php
@@ -1,305 +1,318 @@
<?php
/**
* LDAP Password Driver
*
* Driver for passwords stored in LDAP
* This driver use the PEAR Net_LDAP2 class (http://pear.php.net/package/Net_LDAP2).
*
* @version 2.0
* @author Edouard MOREAU <edouard.moreau@ensma.fr>
*
* method hashPassword based on code from the phpLDAPadmin development team (http://phpldapadmin.sourceforge.net/).
* method randomSalt based on code from the phpLDAPadmin development team (http://phpldapadmin.sourceforge.net/).
*
+ * Copyright (C) 2005-2014, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_ldap_password
{
public function save($curpass, $passwd)
{
$rcmail = rcmail::get_instance();
require_once 'Net/LDAP2.php';
// Building user DN
if ($userDN = $rcmail->config->get('password_ldap_userDN_mask')) {
$userDN = self::substitute_vars($userDN);
} else {
$userDN = $this->search_userdn($rcmail);
}
if (empty($userDN)) {
return PASSWORD_CONNECT_ERROR;
}
// Connection Method
switch($rcmail->config->get('password_ldap_method')) {
case 'admin':
$binddn = $rcmail->config->get('password_ldap_adminDN');
$bindpw = $rcmail->config->get('password_ldap_adminPW');
break;
case 'user':
default:
$binddn = $userDN;
$bindpw = $curpass;
break;
}
// Configuration array
$ldapConfig = array (
'binddn' => $binddn,
'bindpw' => $bindpw,
'basedn' => $rcmail->config->get('password_ldap_basedn'),
'host' => $rcmail->config->get('password_ldap_host'),
'port' => $rcmail->config->get('password_ldap_port'),
'starttls' => $rcmail->config->get('password_ldap_starttls'),
'version' => $rcmail->config->get('password_ldap_version'),
);
// Connecting using the configuration array
$ldap = Net_LDAP2::connect($ldapConfig);
// Checking for connection error
if (PEAR::isError($ldap)) {
return PASSWORD_CONNECT_ERROR;
}
$crypted_pass = self::hash_password($passwd, $rcmail->config->get('password_ldap_encodage'));
$force = $rcmail->config->get('password_ldap_force_replace');
$pwattr = $rcmail->config->get('password_ldap_pwattr');
$lchattr = $rcmail->config->get('password_ldap_lchattr');
$smbpwattr = $rcmail->config->get('password_ldap_samba_pwattr');
$smblchattr = $rcmail->config->get('password_ldap_samba_lchattr');
$samba = $rcmail->config->get('password_ldap_samba');
// Support password_ldap_samba option for backward compat.
if ($samba && !$smbpwattr) {
$smbpwattr = 'sambaNTPassword';
$smblchattr = 'sambaPwdLastSet';
}
// Crypt new password
if (!$crypted_pass) {
return PASSWORD_CRYPT_ERROR;
}
// Crypt new samba password
if ($smbpwattr && !($samba_pass = self::hash_password($passwd, 'samba'))) {
return PASSWORD_CRYPT_ERROR;
}
// Writing new crypted password to LDAP
$userEntry = $ldap->getEntry($userDN);
if (Net_LDAP2::isError($userEntry)) {
return PASSWORD_CONNECT_ERROR;
}
if (!$userEntry->replace(array($pwattr => $crypted_pass), $force)) {
return PASSWORD_CONNECT_ERROR;
}
// Updating PasswordLastChange Attribute if desired
if ($lchattr) {
$current_day = (int)(time() / 86400);
if (!$userEntry->replace(array($lchattr => $current_day), $force)) {
return PASSWORD_CONNECT_ERROR;
}
}
// Update Samba password and last change fields
if ($smbpwattr) {
$userEntry->replace(array($smbpwattr => $samba_pass), $force);
}
// Update Samba password last change field
if ($smblchattr) {
$userEntry->replace(array($smblchattr => time()), $force);
}
if (Net_LDAP2::isError($userEntry->update())) {
return PASSWORD_CONNECT_ERROR;
}
// All done, no error
return PASSWORD_SUCCESS;
}
/**
* Bind with searchDN and searchPW and search for the user's DN.
* Use search_base and search_filter defined in config file.
* Return the found DN.
*/
function search_userdn($rcmail)
{
$binddn = $rcmail->config->get('password_ldap_searchDN');
$bindpw = $rcmail->config->get('password_ldap_searchPW');
$ldapConfig = array (
'basedn' => $rcmail->config->get('password_ldap_basedn'),
'host' => $rcmail->config->get('password_ldap_host'),
'port' => $rcmail->config->get('password_ldap_port'),
'starttls' => $rcmail->config->get('password_ldap_starttls'),
'version' => $rcmail->config->get('password_ldap_version'),
);
// allow anonymous searches
if (!empty($binddn)) {
$ldapConfig['binddn'] = $binddn;
$ldapConfig['bindpw'] = $bindpw;
}
$ldap = Net_LDAP2::connect($ldapConfig);
if (PEAR::isError($ldap)) {
return '';
}
$base = self::substitute_vars($rcmail->config->get('password_ldap_search_base'));
$filter = self::substitute_vars($rcmail->config->get('password_ldap_search_filter'));
$options = array (
'scope' => 'sub',
'attributes' => array(),
);
$result = $ldap->search($base, $filter, $options);
$ldap->done();
if (PEAR::isError($result) || ($result->count() != 1)) {
return '';
}
return $result->current()->dn();
}
/**
* Substitute %login, %name, %domain, %dc in $str
* See plugin config for details
*/
static function substitute_vars($str)
{
$str = str_replace('%login', $_SESSION['username'], $str);
$str = str_replace('%l', $_SESSION['username'], $str);
$parts = explode('@', $_SESSION['username']);
if (count($parts) == 2) {
$dc = 'dc='.strtr($parts[1], array('.' => ',dc=')); // hierarchal domain string
$str = str_replace('%name', $parts[0], $str);
$str = str_replace('%n', $parts[0], $str);
$str = str_replace('%dc', $dc, $str);
$str = str_replace('%domain', $parts[1], $str);
$str = str_replace('%d', $parts[1], $str);
}
return $str;
}
/**
* Code originaly from the phpLDAPadmin development team
* http://phpldapadmin.sourceforge.net/
*
* Hashes a password and returns the hash based on the specified enc_type
*/
static function hash_password($password_clear, $encodage_type)
{
$encodage_type = strtolower($encodage_type);
switch ($encodage_type) {
case 'crypt':
$crypted_password = '{CRYPT}' . crypt($password_clear, self::random_salt(2));
break;
case 'ext_des':
/* Extended DES crypt. see OpenBSD crypt man page */
if (!defined('CRYPT_EXT_DES') || CRYPT_EXT_DES == 0) {
/* Your system crypt library does not support extended DES encryption */
return false;
}
$crypted_password = '{CRYPT}' . crypt($password_clear, '_' . self::random_salt(8));
break;
case 'md5crypt':
if (!defined('CRYPT_MD5') || CRYPT_MD5 == 0) {
/* Your system crypt library does not support md5crypt encryption */
return false;
}
$crypted_password = '{CRYPT}' . crypt($password_clear, '$1$' . self::random_salt(9));
break;
case 'blowfish':
if (!defined('CRYPT_BLOWFISH') || CRYPT_BLOWFISH == 0) {
/* Your system crypt library does not support blowfish encryption */
return false;
}
/* Hardcoded to second blowfish version and set number of rounds */
$crypted_password = '{CRYPT}' . crypt($password_clear, '$2a$12$' . self::random_salt(13));
break;
case 'md5':
$crypted_password = '{MD5}' . base64_encode(pack('H*', md5($password_clear)));
break;
case 'sha':
if (function_exists('sha1')) {
/* Use PHP 4.3.0+ sha1 function, if it is available */
$crypted_password = '{SHA}' . base64_encode(pack('H*', sha1($password_clear)));
} else if (function_exists('mhash')) {
$crypted_password = '{SHA}' . base64_encode(mhash(MHASH_SHA1, $password_clear));
} else {
/* Your PHP install does not have the mhash() function */
return false;
}
break;
case 'ssha':
if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) {
mt_srand((double) microtime() * 1000000 );
$salt = mhash_keygen_s2k(MHASH_SHA1, $password_clear, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
$crypted_password = '{SSHA}' . base64_encode(mhash(MHASH_SHA1, $password_clear . $salt) . $salt);
} else {
/* Your PHP install does not have the mhash() function */
return false;
}
break;
case 'smd5':
if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) {
mt_srand((double) microtime() * 1000000 );
$salt = mhash_keygen_s2k(MHASH_MD5, $password_clear, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
$crypted_password = '{SMD5}' . base64_encode(mhash(MHASH_MD5, $password_clear . $salt) . $salt);
} else {
/* Your PHP install does not have the mhash() function */
return false;
}
break;
case 'samba':
if (function_exists('hash')) {
$crypted_password = hash('md4', rcube_charset::convert($password_clear, RCUBE_CHARSET, 'UTF-16LE'));
$crypted_password = strtoupper($crypted_password);
} else {
/* Your PHP install does not have the hash() function */
return false;
}
break;
case 'ad':
$crypted_password = rcube_charset::convert('"' . $password_clear . '"', RCUBE_CHARSET, 'UTF-16LE');
break;
case 'clear':
default:
$crypted_password = $password_clear;
}
return $crypted_password;
}
/**
* Code originaly from the phpLDAPadmin development team
* http://phpldapadmin.sourceforge.net/
*
* Used to generate a random salt for crypt-style passwords
*/
static function random_salt($length)
{
$possible = '0123456789' . 'abcdefghijklmnopqrstuvwxyz' . 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . './';
$str = '';
// mt_srand((double)microtime() * 1000000);
while (strlen($str) < $length) {
$str .= substr($possible, (rand() % strlen($possible)), 1);
}
return $str;
}
-
}
diff --git a/plugins/password/drivers/ldap_simple.php b/plugins/password/drivers/ldap_simple.php
index 3c19ccde5..9123ea81f 100644
--- a/plugins/password/drivers/ldap_simple.php
+++ b/plugins/password/drivers/ldap_simple.php
@@ -1,223 +1,238 @@
<?php
/**
* Simple LDAP Password Driver
*
* Driver for passwords stored in LDAP
* This driver is based on Edouard's LDAP Password Driver, but does not
* require PEAR's Net_LDAP2 to be installed
*
* @version 2.0
* @author Wout Decre <wout@canodus.be>
+ * @author Aleksander Machniak <machniak@kolabsys.com>
+ *
+ * Copyright (C) 2005-2014, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_ldap_simple_password
{
private $debug = false;
function save($curpass, $passwd)
{
$rcmail = rcmail::get_instance();
$this->debug = $rcmail->config->get('ldap_debug');
$ldap_host = $rcmail->config->get('password_ldap_host');
$ldap_port = $rcmail->config->get('password_ldap_port');
$this->_debug("C: Connect to $ldap_host:$ldap_port");
// Connect
if (!$ds = ldap_connect($ldap_host, $ldap_port)) {
$this->_debug("S: NOT OK");
rcube::raise_error(array(
'code' => 100, 'type' => 'ldap',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Could not connect to LDAP server"
),
true);
return PASSWORD_CONNECT_ERROR;
}
$this->_debug("S: OK");
// Set protocol version
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $rcmail->config->get('password_ldap_version'));
// Start TLS
if ($rcmail->config->get('password_ldap_starttls')) {
if (!ldap_start_tls($ds)) {
ldap_unbind($ds);
return PASSWORD_CONNECT_ERROR;
}
}
// include 'ldap' driver, we share some static methods with it
require_once INSTALL_PATH . 'plugins/password/drivers/ldap.php';
// other plugins might want to modify user DN
$plugin = $rcmail->plugins->exec_hook('password_ldap_bind', array(
'user_dn' => '', 'conn' => $ds));
// Build user DN
if (!empty($plugin['user_dn'])) {
$user_dn = $plugin['user_dn'];
}
else if ($user_dn = $rcmail->config->get('password_ldap_userDN_mask')) {
$user_dn = rcube_ldap_password::substitute_vars($user_dn);
}
else {
$user_dn = $this->search_userdn($rcmail, $ds);
}
if (empty($user_dn)) {
ldap_unbind($ds);
return PASSWORD_CONNECT_ERROR;
}
// Connection method
switch ($rcmail->config->get('password_ldap_method')) {
case 'admin':
$binddn = $rcmail->config->get('password_ldap_adminDN');
$bindpw = $rcmail->config->get('password_ldap_adminPW');
break;
case 'user':
default:
$binddn = $user_dn;
$bindpw = $curpass;
break;
}
$lchattr = $rcmail->config->get('password_ldap_lchattr');
$pwattr = $rcmail->config->get('password_ldap_pwattr');
$smbpwattr = $rcmail->config->get('password_ldap_samba_pwattr');
$smblchattr = $rcmail->config->get('password_ldap_samba_lchattr');
$samba = $rcmail->config->get('password_ldap_samba');
$pass_mode = $rcmail->config->get('password_ldap_encodage');
$crypted_pass = rcube_ldap_password::hash_password($passwd, $pass_mode);
// Support password_ldap_samba option for backward compat.
if ($samba && !$smbpwattr) {
$smbpwattr = 'sambaNTPassword';
$smblchattr = 'sambaPwdLastSet';
}
// Crypt new password
if (!$crypted_pass) {
return PASSWORD_CRYPT_ERROR;
}
// Crypt new Samba password
if ($smbpwattr && !($samba_pass = rcube_ldap_password::hash_password($passwd, 'samba'))) {
return PASSWORD_CRYPT_ERROR;
}
$this->_debug("C: Bind $binddn, pass: **** [" . strlen($bindpw) . "]");
// Bind
if (!ldap_bind($ds, $binddn, $bindpw)) {
$this->_debug("S: ".ldap_error($ds));
ldap_unbind($ds);
return PASSWORD_CONNECT_ERROR;
}
$this->_debug("S: OK");
$entry[$pwattr] = $crypted_pass;
// Update PasswordLastChange Attribute if desired
if ($lchattr) {
$entry[$lchattr] = (int)(time() / 86400);
}
// Update Samba password
if ($smbpwattr) {
$entry[$smbpwattr] = $samba_pass;
}
// Update Samba password last change
if ($smblchattr) {
$entry[$smblchattr] = time();
}
$this->_debug("C: Modify $user_dn: " . print_r($entry, true));
if (!ldap_modify($ds, $user_dn, $entry)) {
$this->_debug("S: ".ldap_error($ds));
ldap_unbind($ds);
return PASSWORD_CONNECT_ERROR;
}
$this->_debug("S: OK");
// All done, no error
ldap_unbind($ds);
return PASSWORD_SUCCESS;
}
/**
* Bind with searchDN and searchPW and search for the user's DN
* Use search_base and search_filter defined in config file
* Return the found DN
*/
function search_userdn($rcmail, $ds)
{
$search_user = $rcmail->config->get('password_ldap_searchDN');
$search_pass = $rcmail->config->get('password_ldap_searchPW');
$search_base = $rcmail->config->get('password_ldap_search_base');
$search_filter = $rcmail->config->get('password_ldap_search_filter');
if (empty($search_filter)) {
return false;
}
$this->_debug("C: Bind " . ($search_user ? $search_user : '[anonymous]'));
// Bind
if (!ldap_bind($ds, $search_user, $search_pass)) {
$this->_debug("S: ".ldap_error($ds));
return false;
}
$this->_debug("S: OK");
$search_base = rcube_ldap_password::substitute_vars($search_base);
$search_filter = rcube_ldap_password::substitute_vars($search_filter);
$this->_debug("C: Search $search_base for $search_filter");
// Search for the DN
if (!$sr = ldap_search($ds, $search_base, $search_filter)) {
$this->_debug("S: ".ldap_error($ds));
return false;
}
$found = ldap_count_entries($ds, $sr);
$this->_debug("S: OK [found $found records]");
// If no or more entries were found, return false
if ($found != 1) {
return false;
}
return ldap_get_dn($ds, ldap_first_entry($ds, $sr));
}
/**
* Prints debug info to the log
*/
private function _debug($str)
{
if ($this->debug) {
rcube::write_log('ldap', $str);
}
}
-
}
diff --git a/plugins/password/drivers/pam.php b/plugins/password/drivers/pam.php
index 4d0ba1656..cd5a92f49 100644
--- a/plugins/password/drivers/pam.php
+++ b/plugins/password/drivers/pam.php
@@ -1,43 +1,58 @@
<?php
/**
* PAM Password Driver
*
* @version 2.0
* @author Aleksander Machniak
+ *
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_pam_password
{
function save($currpass, $newpass)
{
$user = $_SESSION['username'];
$error = '';
if (extension_loaded('pam') || extension_loaded('pam_auth')) {
if (pam_auth($user, $currpass, $error, false)) {
if (pam_chpass($user, $currpass, $newpass)) {
return PASSWORD_SUCCESS;
}
}
else {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: PAM authentication failed for user $user: $error"
), true, false);
}
}
else {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: PECL-PAM module not loaded"
), true, false);
}
return PASSWORD_ERROR;
}
}
diff --git a/plugins/password/drivers/plesk.php b/plugins/password/drivers/plesk.php
index 6f646d229..d0a511fbe 100644
--- a/plugins/password/drivers/plesk.php
+++ b/plugins/password/drivers/plesk.php
@@ -1,234 +1,241 @@
<?php
+
/**
* Roundcube Password Driver for Plesk-RPC.
*
* This driver changes a E-Mail-Password via Plesk-RPC
* Deps: PHP-Curl, SimpleXML
*
- * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
- * @copyright Adfinis SyGroup AG, 2014
- * @license GNU GPL v3
+ * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
+ * @copyright Adfinis SyGroup AG, 2014
*
* Config needed:
- * $config['password_plesk_host'] = '10.0.0.5';
- * $config['password_plesk_user'] = 'admin';
- * $config['password_plesk_pass'] = 'pass';
- * $config['password_plesk_rpc_port'] = 8443;
- * $config['password_plesk_rpc_path'] = enterprise/control/agent.php;
+ * $config['password_plesk_host'] = '10.0.0.5';
+ * $config['password_plesk_user'] = 'admin';
+ * $config['password_plesk_pass'] = 'pass';
+ * $config['password_plesk_rpc_port'] = 8443;
+ * $config['password_plesk_rpc_path'] = enterprise/control/agent.php;
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
*
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
/**
* Roundcube Password Driver Class
*
* See {ROUNDCUBE_ROOT}/plugins/password/README for API description
*
- * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
+ * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
*/
-class rcube_plesk_password {
-
- /**
- * this method is called from roundcube to change the password
- *
- * roundcube allready validated the old password so we just need to change it at this point
- *
- * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
- * @param string $curpass current password
- * @param string $newpass new password
- * @returns PASSWORD_SUCCESS|PASSWORD_ERROR
- */
- function save($currpass, $newpass) {
-
- // get config
- $rcmail = rcmail::get_instance();
- $host = $rcmail->config->get('password_plesk_host');
- $user = $rcmail->config->get('password_plesk_user');
- $pass = $rcmail->config->get('password_plesk_pass');
- $port = $rcmail->config->get('password_plesk_rpc_port');
- $path = $rcmail->config->get('password_plesk_rpc_path');
-
- // create plesk-object
- $plesk = new plesk_rpc;
- $plesk->init($host, $port, $path, $user, $pass);
-
- // try to change password and return the status
- $result = $plesk->change_mailbox_password($_SESSION['username'], $newpass);
- //$plesk->destroy();
-
- if ($result) {
- return PASSWORD_SUCCESS;
- }
-
- return PASSWORD_ERROR;
- }
-
+class rcube_plesk_password
+{
+ /**
+ * this method is called from roundcube to change the password
+ *
+ * roundcube allready validated the old password so we just need to change it at this point
+ *
+ * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
+ * @param string $curpass Current password
+ * @param string $newpass New password
+ * @returns int PASSWORD_SUCCESS|PASSWORD_ERROR
+ */
+ function save($currpass, $newpass)\
+ {
+ // get config
+ $rcmail = rcmail::get_instance();
+ $host = $rcmail->config->get('password_plesk_host');
+ $user = $rcmail->config->get('password_plesk_user');
+ $pass = $rcmail->config->get('password_plesk_pass');
+ $port = $rcmail->config->get('password_plesk_rpc_port');
+ $path = $rcmail->config->get('password_plesk_rpc_path');
+
+ // create plesk-object
+ $plesk = new plesk_rpc;
+ $plesk->init($host, $port, $path, $user, $pass);
+
+ // try to change password and return the status
+ $result = $plesk->change_mailbox_password($_SESSION['username'], $newpass);
+ //$plesk->destroy();
+
+ if ($result) {
+ return PASSWORD_SUCCESS;
+ }
+
+ return PASSWORD_ERROR;
+ }
}
/**
* Plesk RPC-Class
*
* Striped down version of Plesk-RPC-Class
* Just functions for changing mail-passwords included
*
* Documentation of Plesk RPC-API: http://download1.parallels.com/Plesk/PP11/11.0/Doc/en-US/online/plesk-api-rpc/
*
- * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
+ * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
*/
-class plesk_rpc {
-
- /**
- * init plesk-rpc via curl
- *
- * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
- * @param string $host plesk host
- * @param string $port plesk rpc port
- * @param string $path plesk rpc path
- * @param string $user plesk user
- * @param string $user plesk password
- * @returns void
- */
- function init($host, $port, $path, $user, $pass) {
- $headers = array(
- sprintf("HTTP_AUTH_LOGIN: %s", $user),
- sprintf("HTTP_AUTH_PASSWD: %s", $pass),
- "Content-Type: text/xml"
- );
- $url = sprintf("https://%s:%s/%s", $host, $port, $path);
- $this->curl = curl_init();
- curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT , 5);
- curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST , 0);
- curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER , false);
- curl_setopt($this->curl, CURLOPT_HTTPHEADER , $headers);
- curl_setopt($this->curl, CURLOPT_URL , $url);
- }
-
-
- /**
- * send a request to the plesk
- *
- * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
- * @param string $packet XML-Packet to send to Plesk
- * @returns bool request was successfull or not
- */
- function send_request($packet) {
- curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($this->curl, CURLOPT_POSTFIELDS, $packet);
- $retval = curl_exec($this->curl);
-
- return $retval;
- }
-
-
- /**
- * close curl
- *
- * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
- * @returns void
- */
- function destroy(){
- curl_close($this->curl);
- }
-
-
- /**
- * Creates an Initial SimpleXML-Object for Plesk-RPC
- *
- * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
- * @returns object SimpleXML object
- */
- function get_request_obj(){
- $request = new SimpleXMLElement("<packet></packet>");
- $request->addAttribute("version", "1.6.3.0");
-
- return $request;
- }
-
- /**
- * Get all hosting-informations of a domain
- *
- * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
- * @param string $domain domain-name
- * @returns object SimpleXML object
- */
- function domain_info($domain){
- // build xml
- $request = $this->get_request_obj();
- $site = $request->addChild("site");
- $get = $site->addChild("get");
- $filter = $get->addChild("filter");
-
- $filter->addChild("name", utf8_encode($domain));
- $dataset = $get->addChild("dataset");
-
- $dataset->addChild("hosting");
- $packet = $request->asXML();
-
- // send the request
- $res = $this->send_request($packet);
-
- // make it to simple-xml-object
- $xml = new SimpleXMLElement($res);
-
- return $xml;
- }
-
- /**
- * Get psa-id of a domain
- *
- * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
- * @param string $domain domain-name
- * @returns bool|int false if failed and integer if successed
- */
- function get_domain_id($domain){
- $xml = $this->domain_info($domain);
- $id = intval($xml->site->get->result->id);
- $id = (is_int($id)) ? $id : false;
- return $id;
- }
-
-
- /**
- * Change Password of a mailbox
- *
- * @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
- * @param string $mailbox full email-adress (user@domain.tld)
- * @param string $newpass new password of mailbox
- * @returns bool
- */
- function change_mailbox_password($mailbox, $newpass){
-
- list($user, $domain) = explode("@", $mailbox);
- $domain_id = $this->get_domain_id($domain);
-
- // if domain cannot be resolved to an id, do not continue
- if (!$domain_id) {
- return false;
- }
-
- // build xml-packet
- $request = $this -> get_request_obj();
- $mail = $request -> addChild("mail");
- $update = $mail -> addChild("update");
- $add = $update -> addChild("set");
- $filter = $add -> addChild("filter");
- $filter->addChild("site-id", $domain_id);
-
- $mailname = $filter->addChild("mailname");
- $mailname->addChild("name", $user);
-
- $password = $mailname->addChild("password");
- $password->addChild("value", $newpass);
- $password->addChild("type", "plain");
-
- $packet = $request->asXML();
-
- // send the request to plesk
- $res = $this->send_request($packet);
- $xml = new SimpleXMLElement($res);
- $res = strval($xml->mail->update->set->result->status);
-
- return $res == "ok";
- }
+class plesk_rpc
+{
+ /**
+ * init plesk-rpc via curl
+ *
+ * @param string $host plesk host
+ * @param string $port plesk rpc port
+ * @param string $path plesk rpc path
+ * @param string $user plesk user
+ * @param string $user plesk password
+ * @returns void
+ */
+ function init($host, $port, $path, $user, $pass)
+ {
+ $headers = array(
+ sprintf("HTTP_AUTH_LOGIN: %s", $user),
+ sprintf("HTTP_AUTH_PASSWD: %s", $pass),
+ "Content-Type: text/xml"
+ );
+
+ $url = sprintf("https://%s:%s/%s", $host, $port, $path);
+ $this->curl = curl_init();
+
+ curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT , 5);
+ curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST , 0);
+ curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER , false);
+ curl_setopt($this->curl, CURLOPT_HTTPHEADER , $headers);
+ curl_setopt($this->curl, CURLOPT_URL , $url);
+ }
+
+ /**
+ * send a request to the plesk
+ *
+ * @param string $packet XML-Packet to send to Plesk
+ * @returns bool request was successfull or not
+ */
+ function send_request($packet)
+ {
+ curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($this->curl, CURLOPT_POSTFIELDS, $packet);
+ $retval = curl_exec($this->curl);
+
+ return $retval;
+ }
+
+ /**
+ * close curl
+ */
+ function destroy(){
+ curl_close($this->curl);
+ }
+
+ /**
+ * Creates an Initial SimpleXML-Object for Plesk-RPC
+ *
+ * @returns object SimpleXML object
+ */
+ function get_request_obj()
+ {
+ $request = new SimpleXMLElement("<packet></packet>");
+ $request->addAttribute("version", "1.6.3.0");
+
+ return $request;
+ }
+
+ /**
+ * Get all hosting-informations of a domain
+ *
+ * @param string $domain domain-name
+ * @returns object SimpleXML object
+ */
+ function domain_info($domain)
+ {
+ // build xml
+ $request = $this->get_request_obj();
+ $site = $request->addChild("site");
+ $get = $site->addChild("get");
+ $filter = $get->addChild("filter");
+
+ $filter->addChild("name", utf8_encode($domain));
+ $dataset = $get->addChild("dataset");
+
+ $dataset->addChild("hosting");
+ $packet = $request->asXML();
+
+ // send the request
+ $res = $this->send_request($packet);
+
+ // make it to simple-xml-object
+ $xml = new SimpleXMLElement($res);
+
+ return $xml;
+ }
+
+ /**
+ * Get psa-id of a domain
+ *
+ * @param string $domain domain-name
+ *
+ * @returns bool|int false if failed and integer if successed
+ */
+ function get_domain_id($domain)
+ {
+ $xml = $this->domain_info($domain);
+ $id = intval($xml->site->get->result->id);
+ $id = (is_int($id)) ? $id : false;
+
+ return $id;
+ }
+
+ /**
+ * Change Password of a mailbox
+ *
+ * @param string $mailbox full email-adress (user@domain.tld)
+ * @param string $newpass new password of mailbox
+ *
+ * @returns bool
+ */
+ function change_mailbox_password($mailbox, $newpass)
+ {
+ list($user, $domain) = explode("@", $mailbox);
+ $domain_id = $this->get_domain_id($domain);
+
+ // if domain cannot be resolved to an id, do not continue
+ if (!$domain_id) {
+ return false;
+ }
+
+ // build xml-packet
+ $request = $this -> get_request_obj();
+ $mail = $request -> addChild("mail");
+ $update = $mail -> addChild("update");
+ $add = $update -> addChild("set");
+ $filter = $add -> addChild("filter");
+ $filter->addChild("site-id", $domain_id);
+
+ $mailname = $filter->addChild("mailname");
+ $mailname->addChild("name", $user);
+
+ $password = $mailname->addChild("password");
+ $password->addChild("value", $newpass);
+ $password->addChild("type", "plain");
+
+ $packet = $request->asXML();
+
+ // send the request to plesk
+ $res = $this->send_request($packet);
+ $xml = new SimpleXMLElement($res);
+ $res = strval($xml->mail->update->set->result->status);
+
+ return $res == "ok";
+ }
}
-
diff --git a/plugins/password/drivers/poppassd.php b/plugins/password/drivers/poppassd.php
index e18ec2660..8ddbef5d3 100644
--- a/plugins/password/drivers/poppassd.php
+++ b/plugins/password/drivers/poppassd.php
@@ -1,67 +1,82 @@
<?php
/**
* Poppassd Password Driver
*
* Driver to change passwords via Poppassd/Courierpassd
*
* @version 2.0
* @author Philip Weir
*
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_poppassd_password
{
function format_error_result($code, $line)
{
if (preg_match('/^\d\d\d\s+(\S.*)\s*$/', $line, $matches)) {
return array('code' => $code, 'message' => $matches[1]);
- } else {
- return $code;
}
+
+ return $code;
}
function save($curpass, $passwd)
{
$rcmail = rcmail::get_instance();
// include('Net/Socket.php');
$poppassd = new Net_Socket();
$result = $poppassd->connect($rcmail->config->get('password_pop_host'), $rcmail->config->get('password_pop_port'), null);
if (PEAR::isError($result)) {
return $this->format_error_result(PASSWORD_CONNECT_ERROR, $result->getMessage());
}
else {
$result = $poppassd->readLine();
if(!preg_match('/^2\d\d/', $result)) {
$poppassd->disconnect();
return $this->format_error_result(PASSWORD_ERROR, $result);
}
else {
$poppassd->writeLine("user ". $_SESSION['username']);
$result = $poppassd->readLine();
- if(!preg_match('/^[23]\d\d/', $result) ) {
+ if (!preg_match('/^[23]\d\d/', $result) ) {
$poppassd->disconnect();
return $this->format_error_result(PASSWORD_CONNECT_ERROR, $result);
}
else {
$poppassd->writeLine("pass ". $curpass);
$result = $poppassd->readLine();
- if(!preg_match('/^[23]\d\d/', $result) ) {
+ if (!preg_match('/^[23]\d\d/', $result) ) {
$poppassd->disconnect();
return $this->format_error_result(PASSWORD_ERROR, $result);
}
else {
$poppassd->writeLine("newpass ". $passwd);
$result = $poppassd->readLine();
$poppassd->disconnect();
- if (!preg_match('/^2\d\d/', $result))
+ if (!preg_match('/^2\d\d/', $result)) {
return $this->format_error_result(PASSWORD_ERROR, $result);
- else
- return PASSWORD_SUCCESS;
+ }
+
+ return PASSWORD_SUCCESS;
}
}
}
}
}
}
diff --git a/plugins/password/drivers/pw_usermod.php b/plugins/password/drivers/pw_usermod.php
index 237e275a7..c519bf4a4 100644
--- a/plugins/password/drivers/pw_usermod.php
+++ b/plugins/password/drivers/pw_usermod.php
@@ -1,41 +1,56 @@
<?php
/**
* pw_usermod Driver
*
* Driver that adds functionality to change the systems user password via
* the 'pw usermod' command.
*
* For installation instructions please read the README file.
*
* @version 2.0
* @author Alex Cartwright <acartwright@mutinydesign.co.uk>
* @author Adamson Huang <adomputer@gmail.com>
+ *
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_pw_usermod_password
{
public function save($currpass, $newpass)
{
$username = $_SESSION['username'];
$cmd = rcmail::get_instance()->config->get('password_pw_usermod_cmd');
$cmd .= " $username > /dev/null";
$handle = popen($cmd, "w");
fwrite($handle, "$newpass\n");
if (pclose($handle) == 0) {
return PASSWORD_SUCCESS;
}
else {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: Unable to execute $cmd"
), true, false);
}
return PASSWORD_ERROR;
}
}
diff --git a/plugins/password/drivers/sasl.php b/plugins/password/drivers/sasl.php
index 8776eff2e..f3baef557 100644
--- a/plugins/password/drivers/sasl.php
+++ b/plugins/password/drivers/sasl.php
@@ -1,45 +1,60 @@
<?php
/**
* SASL Password Driver
*
* Driver that adds functionality to change the users Cyrus/SASL password.
* The code is derrived from the Squirrelmail "Change SASL Password" Plugin
* by Galen Johnson.
*
* It only works with saslpasswd2 on the same host where Roundcube runs
* and requires shell access and gcc in order to compile the binary.
*
* For installation instructions please read the README file.
*
* @version 2.0
* @author Thomas Bruederli
+ *
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_sasl_password
{
function save($currpass, $newpass)
{
$curdir = RCUBE_PLUGINS_DIR . 'password/helpers';
$username = escapeshellcmd($_SESSION['username']);
$args = rcmail::get_instance()->config->get('password_saslpasswd_args', '');
if ($fh = popen("$curdir/chgsaslpasswd -p $args $username", 'w')) {
fwrite($fh, $newpass."\n");
$code = pclose($fh);
if ($code == 0)
return PASSWORD_SUCCESS;
}
else {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: Unable to execute $curdir/chgsaslpasswd"
), true, false);
}
return PASSWORD_ERROR;
}
}
diff --git a/plugins/password/drivers/smb.php b/plugins/password/drivers/smb.php
index 9f2b96afa..3e34c79a1 100644
--- a/plugins/password/drivers/smb.php
+++ b/plugins/password/drivers/smb.php
@@ -1,60 +1,74 @@
<?php
/**
* smb Driver
*
* Driver that adds functionality to change the systems user password via
* the 'smbpasswd' command.
*
* For installation instructions please read the README file.
*
* @version 2.0
* @author Andy Theuninck <gohanman@gmail.com)
*
* Based on chpasswd roundcubemail password driver by
* @author Alex Cartwright <acartwright@mutinydesign.co.uk)
* and smbpasswd horde passwd driver by
* @author Rene Lund Jensen <Rene@lundjensen.net>
*
* Configuration settings:
* password_smb_host => samba host (default: localhost)
* password_smb_cmd => smbpasswd binary (default: /usr/bin/smbpasswd)
+ *
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_smb_password
{
public function save($currpass, $newpass)
{
$host = rcmail::get_instance()->config->get('password_smb_host','localhost');
$bin = rcmail::get_instance()->config->get('password_smb_cmd','/usr/bin/smbpasswd');
$username = $_SESSION['username'];
$host = rcube_utils::parse_host($host);
$tmpfile = tempnam(sys_get_temp_dir(),'smb');
$cmd = $bin . ' -r ' . $host . ' -s -U "' . $username . '" > ' . $tmpfile . ' 2>&1';
$handle = @popen($cmd, 'w');
fputs($handle, $currpass."\n");
fputs($handle, $newpass."\n");
fputs($handle, $newpass."\n");
@pclose($handle);
$res = file($tmpfile);
unlink($tmpfile);
if (strstr($res[count($res) - 1], 'Password changed for user') !== false) {
return PASSWORD_SUCCESS;
}
else {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: Unable to execute $cmd"
), true, false);
}
return PASSWORD_ERROR;
}
-
}
diff --git a/plugins/password/drivers/sql.php b/plugins/password/drivers/sql.php
index 7a51dfe44..e52de4b79 100644
--- a/plugins/password/drivers/sql.php
+++ b/plugins/password/drivers/sql.php
@@ -1,201 +1,217 @@
<?php
/**
* SQL Password Driver
*
* Driver for passwords stored in SQL database
*
* @version 2.0
* @author Aleksander 'A.L.E.C' Machniak <alec@alec.pl>
*
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_sql_password
{
function save($curpass, $passwd)
{
$rcmail = rcmail::get_instance();
- if (!($sql = $rcmail->config->get('password_query')))
+ if (!($sql = $rcmail->config->get('password_query'))) {
$sql = 'SELECT update_passwd(%c, %u)';
+ }
if ($dsn = $rcmail->config->get('password_db_dsn')) {
// #1486067: enable new_link option
if (is_array($dsn) && empty($dsn['new_link']))
$dsn['new_link'] = true;
else if (!is_array($dsn) && !preg_match('/\?new_link=true/', $dsn))
$dsn .= '?new_link=true';
$db = rcube_db::factory($dsn, '', false);
$db->set_debug((bool)$rcmail->config->get('sql_debug'));
$db->db_connect('w');
}
else {
$db = $rcmail->get_dbh();
}
if ($db->is_error()) {
return PASSWORD_ERROR;
}
// crypted password
if (strpos($sql, '%c') !== FALSE) {
$salt = '';
- if (!($crypt_hash = $rcmail->config->get('password_crypt_hash')))
- {
+ if (!($crypt_hash = $rcmail->config->get('password_crypt_hash'))) {
if (CRYPT_MD5)
$crypt_hash = 'md5';
else if (CRYPT_STD_DES)
$crypt_hash = 'des';
}
- switch ($crypt_hash)
- {
+ switch ($crypt_hash) {
case 'md5':
$len = 8;
$salt_hashindicator = '$1$';
break;
case 'des':
$len = 2;
break;
case 'blowfish':
$len = 22;
$salt_hashindicator = '$2a$';
break;
case 'sha256':
$len = 16;
$salt_hashindicator = '$5$';
break;
case 'sha512':
$len = 16;
$salt_hashindicator = '$6$';
break;
default:
return PASSWORD_CRYPT_ERROR;
}
//Restrict the character set used as salt (#1488136)
$seedchars = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
for ($i = 0; $i < $len ; $i++) {
$salt .= $seedchars[rand(0, 63)];
}
$sql = str_replace('%c', $db->quote(crypt($passwd, $salt_hashindicator ? $salt_hashindicator .$salt.'$' : $salt)), $sql);
}
// dovecotpw
if (strpos($sql, '%D') !== FALSE) {
if (!($dovecotpw = $rcmail->config->get('password_dovecotpw')))
$dovecotpw = 'dovecotpw';
if (!($method = $rcmail->config->get('password_dovecotpw_method')))
$method = 'CRAM-MD5';
// use common temp dir
$tmp_dir = $rcmail->config->get('temp_dir');
$tmpfile = tempnam($tmp_dir, 'roundcube-');
$pipe = popen("$dovecotpw -s '$method' > '$tmpfile'", "w");
if (!$pipe) {
unlink($tmpfile);
return PASSWORD_CRYPT_ERROR;
}
else {
fwrite($pipe, $passwd . "\n", 1+strlen($passwd)); usleep(1000);
fwrite($pipe, $passwd . "\n", 1+strlen($passwd));
pclose($pipe);
$newpass = trim(file_get_contents($tmpfile), "\n");
if (!preg_match('/^\{' . $method . '\}/', $newpass)) {
return PASSWORD_CRYPT_ERROR;
}
if (!$rcmail->config->get('password_dovecotpw_with_method'))
$newpass = trim(str_replace('{' . $method . '}', '', $newpass));
unlink($tmpfile);
}
$sql = str_replace('%D', $db->quote($newpass), $sql);
}
// hashed passwords
if (preg_match('/%[n|q]/', $sql)) {
if (!extension_loaded('hash')) {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: 'hash' extension not loaded!"
), true, false);
return PASSWORD_ERROR;
}
- if (!($hash_algo = strtolower($rcmail->config->get('password_hash_algorithm'))))
+ if (!($hash_algo = strtolower($rcmail->config->get('password_hash_algorithm')))) {
$hash_algo = 'sha1';
+ }
$hash_passwd = hash($hash_algo, $passwd);
$hash_curpass = hash($hash_algo, $curpass);
if ($rcmail->config->get('password_hash_base64')) {
$hash_passwd = base64_encode(pack('H*', $hash_passwd));
$hash_curpass = base64_encode(pack('H*', $hash_curpass));
}
$sql = str_replace('%n', $db->quote($hash_passwd, 'text'), $sql);
$sql = str_replace('%q', $db->quote($hash_curpass, 'text'), $sql);
}
// Handle clear text passwords securely (#1487034)
$sql_vars = array();
if (preg_match_all('/%[p|o]/', $sql, $m)) {
foreach ($m[0] as $var) {
if ($var == '%p') {
$sql = preg_replace('/%p/', '?', $sql, 1);
$sql_vars[] = (string) $passwd;
}
else { // %o
$sql = preg_replace('/%o/', '?', $sql, 1);
$sql_vars[] = (string) $curpass;
}
}
}
$local_part = $rcmail->user->get_username('local');
$domain_part = $rcmail->user->get_username('domain');
$username = $_SESSION['username'];
$host = $_SESSION['imap_host'];
// convert domains to/from punnycode
if ($rcmail->config->get('password_idn_ascii')) {
$domain_part = rcube_utils::idn_to_ascii($domain_part);
$username = rcube_utils::idn_to_ascii($username);
$host = rcube_utils::idn_to_ascii($host);
}
else {
$domain_part = rcube_utils::idn_to_utf8($domain_part);
$username = rcube_utils::idn_to_utf8($username);
$host = rcube_utils::idn_to_utf8($host);
}
// at least we should always have the local part
$sql = str_replace('%l', $db->quote($local_part, 'text'), $sql);
$sql = str_replace('%d', $db->quote($domain_part, 'text'), $sql);
$sql = str_replace('%u', $db->quote($username, 'text'), $sql);
$sql = str_replace('%h', $db->quote($host, 'text'), $sql);
$res = $db->query($sql, $sql_vars);
if (!$db->is_error()) {
if (strtolower(substr(trim($sql),0,6)) == 'select') {
- if ($db->fetch_array($res))
+ if ($db->fetch_array($res)) {
return PASSWORD_SUCCESS;
- } else {
+ }
+ }
+ else {
// This is the good case: 1 row updated
if ($db->affected_rows($res) == 1)
return PASSWORD_SUCCESS;
// @TODO: Some queries don't affect any rows
// Should we assume a success if there was no error?
}
}
return PASSWORD_ERROR;
}
}
diff --git a/plugins/password/drivers/virtualmin.php b/plugins/password/drivers/virtualmin.php
index 36c54664b..3001ad9d0 100644
--- a/plugins/password/drivers/virtualmin.php
+++ b/plugins/password/drivers/virtualmin.php
@@ -1,79 +1,94 @@
<?php
/**
* Virtualmin Password Driver
*
* Driver that adds functionality to change the users Virtualmin password.
* The code is derrived from the Squirrelmail "Change Cyrus/SASL Password" Plugin
* by Thomas Bruederli.
*
* It only works with virtualmin on the same host where Roundcube runs
* and requires shell access and gcc in order to compile the binary.
*
* @version 3.0
* @author Martijn de Munnik
+ *
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_virtualmin_password
{
function save($currpass, $newpass)
{
$rcmail = rcmail::get_instance();
$format = $rcmail->config->get('password_virtualmin_format', 0);
$username = $_SESSION['username'];
switch ($format) {
case 1: // username%domain
$domain = substr(strrchr($username, "%"), 1);
break;
case 2: // username.domain (could be bogus)
$pieces = explode(".", $username);
$domain = $pieces[count($pieces)-2]. "." . end($pieces);
break;
case 3: // domain.username (could be bogus)
$pieces = explode(".", $username);
$domain = $pieces[0]. "." . $pieces[1];
break;
case 4: // username-domain
$domain = substr(strrchr($username, "-"), 1);
break;
case 5: // domain-username
$domain = str_replace(strrchr($username, "-"), "", $username);
break;
case 6: // username_domain
$domain = substr(strrchr($username, "_"), 1);
break;
case 7: // domain_username
$pieces = explode("_", $username);
$domain = $pieces[0];
break;
default: // username@domain
$domain = substr(strrchr($username, "@"), 1);
}
if (!$domain) {
$domain = $rcmail->user->get_username('domain');
}
$username = escapeshellcmd($username);
$domain = escapeshellcmd($domain);
$newpass = escapeshellcmd($newpass);
$curdir = RCUBE_PLUGINS_DIR . 'password/helpers';
exec("$curdir/chgvirtualminpasswd modify-user --domain $domain --user $username --pass $newpass", $output, $returnvalue);
if ($returnvalue == 0) {
return PASSWORD_SUCCESS;
}
else {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: Unable to execute $curdir/chgvirtualminpasswd"
), true, false);
}
return PASSWORD_ERROR;
}
}
diff --git a/plugins/password/drivers/vpopmaild.php b/plugins/password/drivers/vpopmaild.php
index 40731206a..a7644fc21 100644
--- a/plugins/password/drivers/vpopmaild.php
+++ b/plugins/password/drivers/vpopmaild.php
@@ -1,55 +1,70 @@
<?php
/**
* vpopmail Password Driver
*
* Driver to change passwords via vpopmaild
*
* @version 2.0
* @author Johannes Hessellund
*
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_vpopmaild_password
{
function save($curpass, $passwd)
{
$rcmail = rcmail::get_instance();
// include('Net/Socket.php');
$vpopmaild = new Net_Socket();
if (PEAR::isError($vpopmaild->connect($rcmail->config->get('password_vpopmaild_host'),
$rcmail->config->get('password_vpopmaild_port'), null))) {
return PASSWORD_CONNECT_ERROR;
}
-
+
$vpopmaild->setTimeout($rcmail->config->get('password_vpopmaild_timeout'),0);
$result = $vpopmaild->readLine();
if(!preg_match('/^\+OK/', $result)) {
$vpopmaild->disconnect();
return PASSWORD_CONNECT_ERROR;
}
$vpopmaild->writeLine("slogin ". $_SESSION['username'] . " " . $curpass);
$result = $vpopmaild->readLine();
if(!preg_match('/^\+OK/', $result) ) {
$vpopmaild->writeLine("quit");
$vpopmaild->disconnect();
return PASSWORD_ERROR;
}
$vpopmaild->writeLine("mod_user ". $_SESSION['username']);
$vpopmaild->writeLine("clear_text_password ". $passwd);
$vpopmaild->writeLine(".");
$result = $vpopmaild->readLine();
$vpopmaild->writeLine("quit");
$vpopmaild->disconnect();
- if (!preg_match('/^\+OK/', $result))
+ if (!preg_match('/^\+OK/', $result)) {
return PASSWORD_ERROR;
+ }
return PASSWORD_SUCCESS;
}
}
diff --git a/plugins/password/drivers/ximss.php b/plugins/password/drivers/ximss.php
index 3b5286a27..54477f730 100644
--- a/plugins/password/drivers/ximss.php
+++ b/plugins/password/drivers/ximss.php
@@ -1,76 +1,89 @@
<?php
/**
* Communigate driver for the Password Plugin for Roundcube
*
* Tested with Communigate Pro 5.1.2
*
* Configuration options:
* password_ximss_host - Host name of Communigate server
* password_ximss_port - XIMSS port on Communigate server
*
- *
* References:
* http://www.communigate.com/WebGuide/XMLAPI.html
*
* @version 2.0
* @author Erik Meitner <erik wanderings.us>
+ *
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_ximss_password
{
function save($pass, $newpass)
{
$rcmail = rcmail::get_instance();
$host = $rcmail->config->get('password_ximss_host');
$port = $rcmail->config->get('password_ximss_port');
$sock = stream_socket_client("tcp://$host:$port", $errno, $errstr, 30);
if ($sock === FALSE) {
return PASSWORD_CONNECT_ERROR;
}
// send all requests at once(pipelined)
fwrite( $sock, '<login id="A001" authData="'.$_SESSION['username'].'" password="'.$pass.'" />'."\0");
fwrite( $sock, '<passwordModify id="A002" oldPassword="'.$pass.'" newPassword="'.$newpass.'" />'."\0");
fwrite( $sock, '<bye id="A003" />'."\0");
//example responses
// <session id="A001" urlID="4815-vN2Txjkggy7gjHRD10jw" userName="user@example.com"/>\0
// <response id="A001"/>\0
// <response id="A002"/>\0
// <response id="A003"/>\0
// or an error:
// <response id="A001" errorText="incorrect password or account name" errorNum="515"/>\0
$responseblob = '';
while (!feof($sock)) {
$responseblob .= fgets($sock, 1024);
}
fclose($sock);
foreach( explode( "\0",$responseblob) as $response ) {
$resp = simplexml_load_string("<xml>".$response."</xml>");
if( $resp->response[0]['id'] == 'A001' ) {
if( isset( $resp->response[0]['errorNum'] ) ) {
return PASSWORD_CONNECT_ERROR;
}
}
else if( $resp->response[0]['id'] == 'A002' ) {
if( isset( $resp->response[0]['errorNum'] )) {
return PASSWORD_ERROR;
}
}
else if( $resp->response[0]['id'] == 'A003' ) {
if( isset($resp->response[0]['errorNum'] )) {
//There was a problem during logout(This is probably harmless)
}
}
} //foreach
return PASSWORD_SUCCESS;
-
}
}
diff --git a/plugins/password/drivers/xmail.php b/plugins/password/drivers/xmail.php
index 47beb2178..a7d00a279 100644
--- a/plugins/password/drivers/xmail.php
+++ b/plugins/password/drivers/xmail.php
@@ -1,106 +1,119 @@
<?php
/**
* XMail Password Driver
*
* Driver for XMail password
*
* @version 2.0
* @author Helio Cavichiolo Jr <helio@hcsistemas.com.br>
*
* Setup xmail_host, xmail_user, xmail_pass and xmail_port into
* config.inc.php of password plugin as follows:
*
* $config['xmail_host'] = 'localhost';
* $config['xmail_user'] = 'YourXmailControlUser';
* $config['xmail_pass'] = 'YourXmailControlPass';
* $config['xmail_port'] = 6017;
*
+ * Copyright (C) 2005-2013, The Roundcube Dev Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_xmail_password
{
function save($currpass, $newpass)
{
$rcmail = rcmail::get_instance();
list($user,$domain) = explode('@', $_SESSION['username']);
$xmail = new XMail;
$xmail->hostname = $rcmail->config->get('xmail_host');
$xmail->username = $rcmail->config->get('xmail_user');
$xmail->password = $rcmail->config->get('xmail_pass');
$xmail->port = $rcmail->config->get('xmail_port');
if (!$xmail->connect()) {
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: Unable to connect to mail server"
), true, false);
return PASSWORD_CONNECT_ERROR;
}
else if (!$xmail->send("userpasswd\t".$domain."\t".$user."\t".$newpass."\n")) {
$xmail->close();
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: Unable to change password"
), true, false);
return PASSWORD_ERROR;
}
else {
$xmail->close();
return PASSWORD_SUCCESS;
}
}
}
class XMail {
var $socket;
var $hostname = 'localhost';
var $username = 'xmail';
var $password = '';
var $port = 6017;
function send($msg)
{
socket_write($this->socket,$msg);
if (substr(socket_read($this->socket, 512, PHP_BINARY_READ),0,1) != "+") {
return false;
}
return true;
}
function connect()
{
$this->socket = socket_create(AF_INET, SOCK_STREAM, 0);
if ($this->socket < 0)
return false;
$result = socket_connect($this->socket, $this->hostname, $this->port);
if ($result < 0) {
socket_close($this->socket);
return false;
}
if (substr(socket_read($this->socket, 512, PHP_BINARY_READ),0,1) != "+") {
socket_close($this->socket);
return false;
}
if (!$this->send("$this->username\t$this->password\n")) {
socket_close($this->socket);
return false;
}
return true;
}
function close()
{
$this->send("quit\n");
socket_close($this->socket);
}
}
-
diff --git a/program/lib/Roundcube/rcube_db.php b/program/lib/Roundcube/rcube_db.php
index a46df97d3..100afd530 100644
--- a/program/lib/Roundcube/rcube_db.php
+++ b/program/lib/Roundcube/rcube_db.php
@@ -1,1185 +1,1186 @@
<?php
/**
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Database wrapper class that implements PHP PDO functions |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
/**
* Database independent query interface.
* This is a wrapper for the PHP PDO.
*
* @package Framework
* @subpackage Database
*/
class rcube_db
{
public $db_provider;
protected $db_dsnw; // DSN for write operations
protected $db_dsnr; // DSN for read operations
protected $db_connected = false; // Already connected ?
protected $db_mode; // Connection mode
protected $dbh; // Connection handle
protected $dbhs = array();
protected $table_connections = array();
protected $db_error = false;
protected $db_error_msg = '';
protected $conn_failure = false;
protected $db_index = 0;
protected $last_result;
protected $tables;
protected $variables;
protected $options = array(
// column/table quotes
'identifier_start' => '"',
'identifier_end' => '"',
);
const DEBUG_LINE_LENGTH = 4096;
/**
* Factory, returns driver-specific instance of the class
*
* @param string $db_dsnw DSN for read/write operations
* @param string $db_dsnr Optional DSN for read only operations
* @param bool $pconn Enables persistent connections
*
* @return rcube_db Object instance
*/
public static function factory($db_dsnw, $db_dsnr = '', $pconn = false)
{
$driver = strtolower(substr($db_dsnw, 0, strpos($db_dsnw, ':')));
$driver_map = array(
'sqlite2' => 'sqlite',
'sybase' => 'mssql',
'dblib' => 'mssql',
'mysqli' => 'mysql',
+ 'oci' => 'oracle',
);
$driver = isset($driver_map[$driver]) ? $driver_map[$driver] : $driver;
$class = "rcube_db_$driver";
if (!$driver || !class_exists($class)) {
rcube::raise_error(array('code' => 600, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => "Configuration error. Unsupported database driver: $driver"),
true, true);
}
return new $class($db_dsnw, $db_dsnr, $pconn);
}
/**
* Object constructor
*
* @param string $db_dsnw DSN for read/write operations
* @param string $db_dsnr Optional DSN for read only operations
* @param bool $pconn Enables persistent connections
*/
public function __construct($db_dsnw, $db_dsnr = '', $pconn = false)
{
if (empty($db_dsnr)) {
$db_dsnr = $db_dsnw;
}
$this->db_dsnw = $db_dsnw;
$this->db_dsnr = $db_dsnr;
$this->db_pconn = $pconn;
$this->db_dsnw_array = self::parse_dsn($db_dsnw);
$this->db_dsnr_array = self::parse_dsn($db_dsnr);
$config = rcube::get_instance()->config;
$this->options['table_prefix'] = $config->get('db_prefix');
$this->options['dsnw_noread'] = $config->get('db_dsnw_noread', false);
$this->options['table_dsn_map'] = array_map(array($this, 'table_name'), $config->get('db_table_dsn', array()));
}
/**
* Connect to specific database
*
* @param array $dsn DSN for DB connections
* @param string $mode Connection mode (r|w)
*/
protected function dsn_connect($dsn, $mode)
{
$this->db_error = false;
$this->db_error_msg = null;
// return existing handle
if ($this->dbhs[$mode]) {
$this->dbh = $this->dbhs[$mode];
$this->db_mode = $mode;
return $this->dbh;
}
// Get database specific connection options
$dsn_string = $this->dsn_string($dsn);
$dsn_options = $this->dsn_options($dsn);
if ($this->db_pconn) {
$dsn_options[PDO::ATTR_PERSISTENT] = true;
}
// Connect
try {
// with this check we skip fatal error on PDO object creation
if (!class_exists('PDO', false)) {
throw new Exception('PDO extension not loaded. See http://php.net/manual/en/intro.pdo.php');
}
$this->conn_prepare($dsn);
$dbh = new PDO($dsn_string, $dsn['username'], $dsn['password'], $dsn_options);
// don't throw exceptions or warnings
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
}
catch (Exception $e) {
$this->db_error = true;
$this->db_error_msg = $e->getMessage();
rcube::raise_error(array('code' => 500, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => $this->db_error_msg), true, false);
return null;
}
$this->dbh = $dbh;
$this->dbhs[$mode] = $dbh;
$this->db_mode = $mode;
$this->db_connected = true;
$this->conn_configure($dsn, $dbh);
}
/**
* Driver-specific preparation of database connection
*
* @param array $dsn DSN for DB connections
*/
protected function conn_prepare($dsn)
{
}
/**
* Driver-specific configuration of database connection
*
* @param array $dsn DSN for DB connections
* @param PDO $dbh Connection handler
*/
protected function conn_configure($dsn, $dbh)
{
}
/**
* Connect to appropriate database depending on the operation
*
* @param string $mode Connection mode (r|w)
* @param boolean $force Enforce using the given mode
*/
public function db_connect($mode, $force = false)
{
// previous connection failed, don't attempt to connect again
if ($this->conn_failure) {
return;
}
// no replication
if ($this->db_dsnw == $this->db_dsnr) {
$mode = 'w';
}
// Already connected
if ($this->db_connected) {
// connected to db with the same or "higher" mode (if allowed)
if ($this->db_mode == $mode || $this->db_mode == 'w' && !$force && !$this->options['dsnw_noread']) {
return;
}
}
$dsn = ($mode == 'r') ? $this->db_dsnr_array : $this->db_dsnw_array;
$this->dsn_connect($dsn, $mode);
// use write-master when read-only fails
if (!$this->db_connected && $mode == 'r' && $this->is_replicated()) {
$this->dsn_connect($this->db_dsnw_array, 'w');
}
$this->conn_failure = !$this->db_connected;
}
/**
* Analyze the given SQL statement and select the appropriate connection to use
*/
protected function dsn_select($query)
{
// no replication
if ($this->db_dsnw == $this->db_dsnr) {
return 'w';
}
// Read or write ?
$mode = preg_match('/^(select|show|set)/i', $query) ? 'r' : 'w';
// find tables involved in this query
if (preg_match_all('/(?:^|\s)(from|update|into|join)\s+'.$this->options['identifier_start'].'?([a-z0-9._]+)'.$this->options['identifier_end'].'?\s+/i', $query, $matches, PREG_SET_ORDER)) {
foreach ($matches as $m) {
$table = $m[2];
// always use direct mapping
if ($this->options['table_dsn_map'][$table]) {
$mode = $this->options['table_dsn_map'][$table];
break; // primary table rules
}
else if ($mode == 'r') {
// connected to db with the same or "higher" mode for this table
$db_mode = $this->table_connections[$table];
if ($db_mode == 'w' && !$this->options['dsnw_noread']) {
$mode = $db_mode;
}
}
}
// remember mode chosen (for primary table)
$table = $matches[0][2];
$this->table_connections[$table] = $mode;
}
return $mode;
}
/**
* Activate/deactivate debug mode
*
* @param boolean $dbg True if SQL queries should be logged
*/
public function set_debug($dbg = true)
{
$this->options['debug_mode'] = $dbg;
}
/**
* Writes debug information/query to 'sql' log file
*
* @param string $query SQL query
*/
protected function debug($query)
{
if ($this->options['debug_mode']) {
if (($len = strlen($query)) > self::DEBUG_LINE_LENGTH) {
$diff = $len - self::DEBUG_LINE_LENGTH;
$query = substr($query, 0, self::DEBUG_LINE_LENGTH)
. "... [truncated $diff bytes]";
}
rcube::write_log('sql', '[' . (++$this->db_index) . '] ' . $query . ';');
}
}
/**
* Getter for error state
*
* @param mixed $result Optional query result
*
* @return string Error message
*/
public function is_error($result = null)
{
if ($result !== null) {
return $result === false ? $this->db_error_msg : null;
}
return $this->db_error ? $this->db_error_msg : null;
}
/**
* Connection state checker
*
* @return boolean True if in connected state
*/
public function is_connected()
{
return !is_object($this->dbh) ? false : $this->db_connected;
}
/**
* Is database replication configured?
*
* @return bool Returns true if dsnw != dsnr
*/
public function is_replicated()
{
return !empty($this->db_dsnr) && $this->db_dsnw != $this->db_dsnr;
}
/**
* Get database runtime variables
*
* @param string $varname Variable name
* @param mixed $default Default value if variable is not set
*
* @return mixed Variable value or default
*/
public function get_variable($varname, $default = null)
{
// to be implemented by driver class
return $default;
}
/**
* Execute a SQL query
*
* @param string SQL query to execute
* @param mixed Values to be inserted in query
*
* @return number Query handle identifier
*/
public function query()
{
$params = func_get_args();
$query = array_shift($params);
// Support one argument of type array, instead of n arguments
if (count($params) == 1 && is_array($params[0])) {
$params = $params[0];
}
return $this->_query($query, 0, 0, $params);
}
/**
* Execute a SQL query with limits
*
* @param string SQL query to execute
* @param int Offset for LIMIT statement
* @param int Number of rows for LIMIT statement
* @param mixed Values to be inserted in query
*
* @return PDOStatement|bool Query handle or False on error
*/
public function limitquery()
{
$params = func_get_args();
$query = array_shift($params);
$offset = array_shift($params);
$numrows = array_shift($params);
return $this->_query($query, $offset, $numrows, $params);
}
/**
* Execute a SQL query with limits
*
* @param string $query SQL query to execute
* @param int $offset Offset for LIMIT statement
* @param int $numrows Number of rows for LIMIT statement
* @param array $params Values to be inserted in query
*
* @return PDOStatement|bool Query handle or False on error
*/
protected function _query($query, $offset, $numrows, $params)
{
$query = ltrim($query);
$this->db_connect($this->dsn_select($query), true);
// check connection before proceeding
if (!$this->is_connected()) {
return $this->last_result = false;
}
if ($numrows || $offset) {
$query = $this->set_limit($query, $numrows, $offset);
}
// Because in Roundcube we mostly use queries that are
// executed only once, we will not use prepared queries
$pos = 0;
$idx = 0;
if (count($params)) {
while ($pos = strpos($query, '?', $pos)) {
if ($query[$pos+1] == '?') { // skip escaped '?'
$pos += 2;
}
else {
$val = $this->quote($params[$idx++]);
unset($params[$idx-1]);
$query = substr_replace($query, $val, $pos, 1);
$pos += strlen($val);
}
}
}
// replace escaped '?' back to normal, see self::quote()
$query = str_replace('??', '?', $query);
$query = rtrim($query, " \t\n\r\0\x0B;");
$this->debug($query);
// destroy reference to previous result, required for SQLite driver (#1488874)
$this->last_result = null;
$this->db_error_msg = null;
// send query
$result = $this->dbh->query($query);
if ($result === false) {
$result = $this->handle_error($query);
}
$this->last_result = $result;
return $result;
}
/**
* Helper method to handle DB errors.
* This by default logs the error but could be overriden by a driver implementation
*
* @param string Query that triggered the error
* @return mixed Result to be stored and returned
*/
protected function handle_error($query)
{
$error = $this->dbh->errorInfo();
if (empty($this->options['ignore_key_errors']) || !in_array($error[0], array('23000', '23505'))) {
$this->db_error = true;
$this->db_error_msg = sprintf('[%s] %s', $error[1], $error[2]);
rcube::raise_error(array('code' => 500, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => $this->db_error_msg . " (SQL Query: $query)"
), true, false);
}
return false;
}
/**
* Get number of affected rows for the last query
*
* @param mixed $result Optional query handle
*
* @return int Number of (matching) rows
*/
public function affected_rows($result = null)
{
if ($result || ($result === null && ($result = $this->last_result))) {
return $result->rowCount();
}
return 0;
}
/**
* Get number of rows for a SQL query
* If no query handle is specified, the last query will be taken as reference
*
* @param mixed $result Optional query handle
* @return mixed Number of rows or false on failure
* @deprecated This method shows very poor performance and should be avoided.
*/
public function num_rows($result = null)
{
if ($result || ($result === null && ($result = $this->last_result))) {
// repeat query with SELECT COUNT(*) ...
if (preg_match('/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/ims', $result->queryString, $m)) {
$query = $this->dbh->query('SELECT COUNT(*) FROM ' . $m[1], PDO::FETCH_NUM);
return $query ? intval($query->fetchColumn(0)) : false;
}
else {
$num = count($result->fetchAll());
$result->execute(); // re-execute query because there's no seek(0)
return $num;
}
}
return false;
}
/**
* Get last inserted record ID
*
* @param string $table Table name (to find the incremented sequence)
*
* @return mixed ID or false on failure
*/
public function insert_id($table = '')
{
if (!$this->db_connected || $this->db_mode == 'r') {
return false;
}
if ($table) {
// resolve table name
$table = $this->table_name($table);
}
$id = $this->dbh->lastInsertId($table);
return $id;
}
/**
* Get an associative array for one row
* If no query handle is specified, the last query will be taken as reference
*
* @param mixed $result Optional query handle
*
* @return mixed Array with col values or false on failure
*/
public function fetch_assoc($result = null)
{
return $this->_fetch_row($result, PDO::FETCH_ASSOC);
}
/**
* Get an index array for one row
* If no query handle is specified, the last query will be taken as reference
*
* @param mixed $result Optional query handle
*
* @return mixed Array with col values or false on failure
*/
public function fetch_array($result = null)
{
return $this->_fetch_row($result, PDO::FETCH_NUM);
}
/**
* Get col values for a result row
*
* @param mixed $result Optional query handle
* @param int $mode Fetch mode identifier
*
* @return mixed Array with col values or false on failure
*/
protected function _fetch_row($result, $mode)
{
if ($result || ($result === null && ($result = $this->last_result))) {
return $result->fetch($mode);
}
return false;
}
/**
* Adds LIMIT,OFFSET clauses to the query
*
* @param string $query SQL query
* @param int $limit Number of rows
* @param int $offset Offset
*
* @return string SQL query
*/
protected function set_limit($query, $limit = 0, $offset = 0)
{
if ($limit) {
$query .= ' LIMIT ' . intval($limit);
}
if ($offset) {
$query .= ' OFFSET ' . intval($offset);
}
return $query;
}
/**
* Returns list of tables in a database
*
* @return array List of all tables of the current database
*/
public function list_tables()
{
// get tables if not cached
if ($this->tables === null) {
$q = $this->query('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_NAME');
if ($q) {
$this->tables = $q->fetchAll(PDO::FETCH_COLUMN, 0);
}
else {
$this->tables = array();
}
}
return $this->tables;
}
/**
* Returns list of columns in database table
*
* @param string $table Table name
*
* @return array List of table cols
*/
public function list_cols($table)
{
$q = $this->query('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ?',
array($table));
if ($q) {
return $q->fetchAll(PDO::FETCH_COLUMN, 0);
}
return array();
}
/**
* Formats input so it can be safely used in a query
*
* @param mixed $input Value to quote
* @param string $type Type of data (integer, bool, ident)
*
* @return string Quoted/converted string for use in query
*/
public function quote($input, $type = null)
{
// handle int directly for better performance
if ($type == 'integer' || $type == 'int') {
return intval($input);
}
if (is_null($input)) {
return 'NULL';
}
if ($type == 'ident') {
return $this->quote_identifier($input);
}
// create DB handle if not available
if (!$this->dbh) {
$this->db_connect('r');
}
if ($this->dbh) {
$map = array(
'bool' => PDO::PARAM_BOOL,
'integer' => PDO::PARAM_INT,
);
$type = isset($map[$type]) ? $map[$type] : PDO::PARAM_STR;
return strtr($this->dbh->quote($input, $type), array('?' => '??')); // escape ?
}
return 'NULL';
}
/**
* Escapes a string so it can be safely used in a query
*
* @param string $str A string to escape
*
* @return string Escaped string for use in a query
*/
public function escape($str)
{
if (is_null($str)) {
return 'NULL';
}
return substr($this->quote($str), 1, -1);
}
/**
* Quotes a string so it can be safely used as a table or column name
*
* @param string $str Value to quote
*
* @return string Quoted string for use in query
* @deprecated Replaced by rcube_db::quote_identifier
* @see rcube_db::quote_identifier
*/
public function quoteIdentifier($str)
{
return $this->quote_identifier($str);
}
/**
* Escapes a string so it can be safely used in a query
*
* @param string $str A string to escape
*
* @return string Escaped string for use in a query
* @deprecated Replaced by rcube_db::escape
* @see rcube_db::escape
*/
public function escapeSimple($str)
{
return $this->escape($str);
}
/**
* Quotes a string so it can be safely used as a table or column name
*
* @param string $str Value to quote
*
* @return string Quoted string for use in query
*/
public function quote_identifier($str)
{
$start = $this->options['identifier_start'];
$end = $this->options['identifier_end'];
$name = array();
foreach (explode('.', $str) as $elem) {
$elem = str_replace(array($start, $end), '', $elem);
$name[] = $start . $elem . $end;
}
return implode($name, '.');
}
/**
* Return SQL function for current time and date
*
* @param int $interval Optional interval (in seconds) to add/subtract
*
* @return string SQL function to use in query
*/
public function now($interval = 0)
{
if ($interval) {
$add = ' ' . ($interval > 0 ? '+' : '-') . ' INTERVAL ';
$add .= $interval > 0 ? intval($interval) : intval($interval) * -1;
$add .= ' SECOND';
}
return "now()" . $add;
}
/**
* Return list of elements for use with SQL's IN clause
*
* @param array $arr Input array
* @param string $type Type of data (integer, bool, ident)
*
* @return string Comma-separated list of quoted values for use in query
*/
public function array2list($arr, $type = null)
{
if (!is_array($arr)) {
return $this->quote($arr, $type);
}
foreach ($arr as $idx => $item) {
$arr[$idx] = $this->quote($item, $type);
}
return implode(',', $arr);
}
/**
* Return SQL statement to convert a field value into a unix timestamp
*
* This method is deprecated and should not be used anymore due to limitations
* of timestamp functions in Mysql (year 2038 problem)
*
* @param string $field Field name
*
* @return string SQL statement to use in query
* @deprecated
*/
public function unixtimestamp($field)
{
return "UNIX_TIMESTAMP($field)";
}
/**
* Return SQL statement to convert from a unix timestamp
*
* @param int $timestamp Unix timestamp
*
* @return string Date string in db-specific format
*/
public function fromunixtime($timestamp)
{
return date("'Y-m-d H:i:s'", $timestamp);
}
/**
* Return SQL statement for case insensitive LIKE
*
* @param string $column Field name
* @param string $value Search value
*
* @return string SQL statement to use in query
*/
public function ilike($column, $value)
{
return $this->quote_identifier($column).' LIKE '.$this->quote($value);
}
/**
* Abstract SQL statement for value concatenation
*
* @return string SQL statement to be used in query
*/
public function concat(/* col1, col2, ... */)
{
$args = func_get_args();
if (is_array($args[0])) {
$args = $args[0];
}
return '(' . join(' || ', $args) . ')';
}
/**
* Encodes non-UTF-8 characters in string/array/object (recursive)
*
* @param mixed $input Data to fix
* @param bool $serialized Enable serialization
*
* @return mixed Properly UTF-8 encoded data
*/
public static function encode($input, $serialized = false)
{
// use Base64 encoding to workaround issues with invalid
// or null characters in serialized string (#1489142)
if ($serialized) {
return base64_encode(serialize($input));
}
if (is_object($input)) {
foreach (get_object_vars($input) as $idx => $value) {
$input->$idx = self::encode($value);
}
return $input;
}
else if (is_array($input)) {
foreach ($input as $idx => $value) {
$input[$idx] = self::encode($value);
}
return $input;
}
return utf8_encode($input);
}
/**
* Decodes encoded UTF-8 string/object/array (recursive)
*
* @param mixed $input Input data
* @param bool $serialized Enable serialization
*
* @return mixed Decoded data
*/
public static function decode($input, $serialized = false)
{
// use Base64 encoding to workaround issues with invalid
// or null characters in serialized string (#1489142)
if ($serialized) {
// Keep backward compatybility where base64 wasn't used
if (strpos(substr($input, 0, 16), ':') !== false) {
return self::decode(@unserialize($input));
}
return @unserialize(base64_decode($input));
}
if (is_object($input)) {
foreach (get_object_vars($input) as $idx => $value) {
$input->$idx = self::decode($value);
}
return $input;
}
else if (is_array($input)) {
foreach ($input as $idx => $value) {
$input[$idx] = self::decode($value);
}
return $input;
}
return utf8_decode($input);
}
/**
* Return correct name for a specific database table
*
* @param string $table Table name
*
* @return string Translated table name
*/
public function table_name($table)
{
// add prefix to the table name if configured
if (($prefix = $this->options['table_prefix']) && strpos($table, $prefix) !== 0) {
return $prefix . $table;
}
return $table;
}
/**
* Set class option value
*
* @param string $name Option name
* @param mixed $value Option value
*/
public function set_option($name, $value)
{
$this->options[$name] = $value;
}
/**
* Set DSN connection to be used for the given table
*
* @param string Table name
* @param string DSN connection ('r' or 'w') to be used
*/
public function set_table_dsn($table, $mode)
{
$this->options['table_dsn_map'][$this->table_name($table)] = $mode;
}
/**
* MDB2 DSN string parser
*
* @param string $sequence Secuence name
*
* @return array DSN parameters
*/
public static function parse_dsn($dsn)
{
if (empty($dsn)) {
return null;
}
// Find phptype and dbsyntax
if (($pos = strpos($dsn, '://')) !== false) {
$str = substr($dsn, 0, $pos);
$dsn = substr($dsn, $pos + 3);
}
else {
$str = $dsn;
$dsn = null;
}
// Get phptype and dbsyntax
// $str => phptype(dbsyntax)
if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
$parsed['phptype'] = $arr[1];
$parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
}
else {
$parsed['phptype'] = $str;
$parsed['dbsyntax'] = $str;
}
if (empty($dsn)) {
return $parsed;
}
// Get (if found): username and password
// $dsn => username:password@protocol+hostspec/database
if (($at = strrpos($dsn,'@')) !== false) {
$str = substr($dsn, 0, $at);
$dsn = substr($dsn, $at + 1);
if (($pos = strpos($str, ':')) !== false) {
$parsed['username'] = rawurldecode(substr($str, 0, $pos));
$parsed['password'] = rawurldecode(substr($str, $pos + 1));
}
else {
$parsed['username'] = rawurldecode($str);
}
}
// Find protocol and hostspec
// $dsn => proto(proto_opts)/database
if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
$proto = $match[1];
$proto_opts = $match[2] ? $match[2] : false;
$dsn = $match[3];
}
// $dsn => protocol+hostspec/database (old format)
else {
if (strpos($dsn, '+') !== false) {
list($proto, $dsn) = explode('+', $dsn, 2);
}
if ( strpos($dsn, '//') === 0
&& strpos($dsn, '/', 2) !== false
&& $parsed['phptype'] == 'oci8'
) {
//oracle's "Easy Connect" syntax:
//"username/password@[//]host[:port][/service_name]"
//e.g. "scott/tiger@//mymachine:1521/oracle"
$proto_opts = $dsn;
$pos = strrpos($proto_opts, '/');
$dsn = substr($proto_opts, $pos + 1);
$proto_opts = substr($proto_opts, 0, $pos);
}
else if (strpos($dsn, '/') !== false) {
list($proto_opts, $dsn) = explode('/', $dsn, 2);
}
else {
$proto_opts = $dsn;
$dsn = null;
}
}
// process the different protocol options
$parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
$proto_opts = rawurldecode($proto_opts);
if (strpos($proto_opts, ':') !== false) {
list($proto_opts, $parsed['port']) = explode(':', $proto_opts);
}
if ($parsed['protocol'] == 'tcp') {
$parsed['hostspec'] = $proto_opts;
}
else if ($parsed['protocol'] == 'unix') {
$parsed['socket'] = $proto_opts;
}
// Get dabase if any
// $dsn => database
if ($dsn) {
// /database
if (($pos = strpos($dsn, '?')) === false) {
$parsed['database'] = rawurldecode($dsn);
// /database?param1=value1¶m2=value2
}
else {
$parsed['database'] = rawurldecode(substr($dsn, 0, $pos));
$dsn = substr($dsn, $pos + 1);
if (strpos($dsn, '&') !== false) {
$opts = explode('&', $dsn);
}
else { // database?param1=value1
$opts = array($dsn);
}
foreach ($opts as $opt) {
list($key, $value) = explode('=', $opt);
if (!array_key_exists($key, $parsed) || false === $parsed[$key]) {
// don't allow params overwrite
$parsed[$key] = rawurldecode($value);
}
}
}
}
return $parsed;
}
/**
* Returns PDO DSN string from DSN array
*
* @param array $dsn DSN parameters
*
* @return string DSN string
*/
protected function dsn_string($dsn)
{
$params = array();
$result = $dsn['phptype'] . ':';
if ($dsn['hostspec']) {
$params[] = 'host=' . $dsn['hostspec'];
}
if ($dsn['port']) {
$params[] = 'port=' . $dsn['port'];
}
if ($dsn['database']) {
$params[] = 'dbname=' . $dsn['database'];
}
if (!empty($params)) {
$result .= implode(';', $params);
}
return $result;
}
/**
* Returns driver-specific connection options
*
* @param array $dsn DSN parameters
*
* @return array Connection options
*/
protected function dsn_options($dsn)
{
$result = array();
return $result;
}
/**
* Execute the given SQL script
*
* @param string SQL queries to execute
*
* @return boolen True on success, False on error
*/
public function exec_script($sql)
{
$sql = $this->fix_table_names($sql);
$buff = '';
foreach (explode("\n", $sql) as $line) {
if (preg_match('/^--/', $line) || trim($line) == '')
continue;
$buff .= $line . "\n";
if (preg_match('/(;|^GO)$/', trim($line))) {
$this->query($buff);
$buff = '';
if ($this->db_error) {
break;
}
}
}
return !$this->db_error;
}
/**
* Parse SQL file and fix table names according to table prefix
*/
protected function fix_table_names($sql)
{
if (!$this->options['table_prefix']) {
return $sql;
}
$sql = preg_replace_callback(
'/((TABLE|TRUNCATE|(?<!ON )UPDATE|INSERT INTO|FROM'
. '| ON(?! (DELETE|UPDATE))|REFERENCES|CONSTRAINT|FOREIGN KEY|INDEX)'
. '\s+(IF (NOT )?EXISTS )?[`"]*)([^`"\( \r\n]+)/',
array($this, 'fix_table_names_callback'),
$sql
);
return $sql;
}
/**
* Preg_replace callback for fix_table_names()
*/
protected function fix_table_names_callback($matches)
{
return $matches[1] . $this->options['table_prefix'] . $matches[count($matches)-1];
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Mar 1, 2:35 AM (21 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
165523
Default Alt Text
(139 KB)
Attached To
Mode
R3 roundcubemail
Attached
Detach File
Event Timeline
Log In to Comment