diff --git a/plugins/change-password-custom-sql/ChangePasswordCustomSqlDriver.php b/plugins/change-password-custom-sql/ChangePasswordCustomSqlDriver.php index c0dd532b49..1a60346e2f 100644 --- a/plugins/change-password-custom-sql/ChangePasswordCustomSqlDriver.php +++ b/plugins/change-password-custom-sql/ChangePasswordCustomSqlDriver.php @@ -146,7 +146,7 @@ public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNe $dsn = 'mysql:host='.$this->mHost.';dbname='.$this->mDatabase.';charset=utf8'; $options = array( - PDO::ATTR_EMULATE_PREPARES => false, + PDO::ATTR_EMULATE_PREPARES => true, PDO::ATTR_PERSISTENT => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ); @@ -160,15 +160,52 @@ public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNe $sEmailUser = \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail); $sEmailDomain = \MailSo\Base\Utils::GetDomainFromEmail($sEmail); - //simple check + // some variables cannot be prepared + $this->mSql = str_replace(array( + ':table' + ), array( + $this->mTable + ), $this->mSql); + + $placeholders = array( + ':email' => $sEmail, + ':oldpass' => $sPrevPassword, + ':newpass' => $sNewPassword, + ':domain' => $sEmailDomain, + ':username' => $sEmailUser + ); + + // we have to check that all placehoders are used in the query, passing any unused placeholders will generate an error + $used_placeholders = array(); + + foreach($placeholders as $placeholder => $value) { + if(preg_match_all('/'.$placeholder . '(?![a-zA-Z0-9\-])'.'/', $this->mSql) === 1) { + // backwards-compabitibility: remove single and double quotes around placeholders + $this->mSql = str_replace('`'.$placeholder.'`', $placeholder, $this->mSql); + $this->mSql = str_replace("'".$placeholder."'", $placeholder, $this->mSql); + $this->mSql = str_replace('"'.$placeholder.'"', $placeholder, $this->mSql); + $used_placeholders[$placeholder] = $value; + } + } + + $statement = $conn->prepare($this->mSql); + + // everything is ready (hopefully), bind the values + foreach($used_placeholders as $placeholder => $value) { + $statement->bindValue($placeholder, $value); + } - $old = array(':email', ':oldpass', ':newpass', ':domain', ':username', ':table' ); - $new = array($sEmail, $sPrevPassword, $sNewPassword, $sEmailDomain, $sEmailUser, $this->mTable); + // and execute + $mSqlReturn = $statement->execute(); - $this->mSql = str_replace($old, $new, $this->mSql); + /* can be used for debugging + ob_start(); + $statement->debugDumpParams(); + $r = ob_get_contents(); + ob_end_clean(); + $this->oLogger->Write($r); + */ - $update = $conn->prepare($this->mSql); - $mSqlReturn = $update->execute(array()); if ($mSqlReturn == true) { $bResult = true; diff --git a/plugins/change-password-custom-sql/index.php b/plugins/change-password-custom-sql/index.php index ad7f7e222c..692f86e7e5 100644 --- a/plugins/change-password-custom-sql/index.php +++ b/plugins/change-password-custom-sql/index.php @@ -46,7 +46,7 @@ public function configMapping() \RainLoop\Plugins\Property::NewInstance('mTable')->SetLabel('MySQL Table'), \RainLoop\Plugins\Property::NewInstance('mSql')->SetLabel('SQL statement') ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) - ->SetDescription('SQL statement (allowed wildcards :table, :email, :oldpass, :newpass, :domain, :username). When using MD5 OR SHA1 at tables, write it directly here as SQL functions. Fro non-SQL encryptions use another plugin or wait for new version.') + ->SetDescription('SQL statement (allowed wildcards :table, :email, :oldpass, :newpass, :domain, :username). Use SQL functions for encryption.') ->SetDefaultValue('UPDATE :table SET password = md5(:newpass) WHERE domain = :domain AND username = :username and oldpass = md5(:oldpass)') ); }