Page MenuHomePhorge

No OneTemporary

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&param2=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

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)

Event Timeline