/** * @param \RainLoop\Model\Account $oHmailAccount * @param string $sPrevPassword * @param string $sNewPassword * * @return bool */ public function ChangePassword(\RainLoop\Account $oHmailAccount, $sPrevPassword, $sNewPassword) { if ($this->oLogger) { $this->oLogger->Write('Try to change password for ' . $oHmailAccount->Email()); } $bResult = false; try { $oHmailApp = new COM("hMailServer.Application"); $oHmailApp->Connect(); if ($oHmailApp->Authenticate($this->sLogin, $this->sPassword)) { $sEmail = $oHmailAccount->Email(); $sDomain = \MailSo\Base\Utils::GetDomainFromEmail($sEmail); $oHmailDomain = $oHmailApp->Domains->ItemByName($sDomain); if ($oHmailDomain) { $oHmailAccount = $oHmailDomain->Accounts->ItemByAddress($sEmail); if ($oHmailAccount) { $oHmailAccount->Password = $sNewPassword; $oHmailAccount->Save(); $bResult = true; } else { $this->oLogger->Write('HMAILSERVER: Unknown account (' . $sEmail . ')', \MailSo\Log\Enumerations\Type::ERROR); } } else { $this->oLogger->Write('HMAILSERVER: Unknown domain (' . $sDomain . ')', \MailSo\Log\Enumerations\Type::ERROR); } } else { $this->oLogger->Write('HMAILSERVER: Auth error', \MailSo\Log\Enumerations\Type::ERROR); } } catch (\Exception $oException) { if ($this->oLogger) { $this->oLogger->WriteException($oException); } } return $bResult; }
/** * @param string $sDesc * @param int $iType = \MailSo\Log\Enumerations\Type::INFO * * @return \VirtualminChangePasswordDriver */ public function WriteLog($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO) { if ($this->oLogger) { $this->oLogger->Write($sDesc, $iType); } return $this; }
/** * @param \RainLoop\Account $oAccount * @param string $sPrevPassword * @param string $sNewPassword * * @return bool */ public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) { if ($this->oLogger) { $this->oLogger->Write('ISP: Try to change password for ' . $oAccount->Email()); } $bResult = false; if (!empty($this->sDsn) && 0 < \strlen($this->sUser) && 0 < \strlen($this->sPassword) && $oAccount) { try { $oPdo = new \PDO($this->sDsn, $this->sUser, $this->sPassword); $oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $oStmt = $oPdo->prepare('SELECT password, mailuser_id FROM mail_user WHERE login = ? LIMIT 1'); if ($oStmt->execute(array($oAccount->IncLogin()))) { $aFetchResult = $oStmt->fetchAll(\PDO::FETCH_ASSOC); if (\is_array($aFetchResult) && isset($aFetchResult[0]['password'], $aFetchResult[0]['mailuser_id'])) { $sDbPassword = \stripslashes($aFetchResult[0]['password']); $sDbSalt = '$1$' . \substr($sDbPassword, 3, 8) . '$'; if (\crypt(\stripslashes($sPrevPassword), $sDbSalt) === $sDbPassword) { $oStmt = $oPdo->prepare('UPDATE mail_user SET password = ? WHERE mailuser_id = ?'); $bResult = (bool) $oStmt->execute(array($this->cryptPassword($sNewPassword), $aFetchResult[0]['mailuser_id'])); } } } } catch (\Exception $oException) { if ($this->oLogger) { $this->oLogger->WriteException($oException); } } } return $bResult; }
/** * @param \RainLoop\Account $oAccount * @param string $sPrevPassword * @param string $sNewPassword * * @return bool */ public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) { if ($this->oLogger) { $this->oLogger->Write('Try to change password for ' . $oAccount->Email()); } $bResult = false; $dsn = 'mysql:host=' . $this->mHost . ';dbname=' . $this->mDatabase . ';charset=utf8'; $options = array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_PERSISTENT => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION); try { $conn = new PDO($dsn, $this->mUser, $this->mPass, $options); $select = $conn->prepare("SELECT {$this->mColumn} FROM {$this->mTable} WHERE id = :id LIMIT 1"); $select->execute(array(':id' => $oAccount->Email())); $colCrypt = $select->fetchAll(PDO::FETCH_ASSOC); $sCryptPass = $colCrypt[0][$this->mColumn]; if (0 < strlen($sCryptPass) && crypt($sPrevPassword, $sCryptPass) === $sCryptPass && 7 < mb_strlen($sNewPassword) && 20 > mb_strlen($sNewPassword) && !preg_match('/[^A-Za-z0-9]+/', $sNewPassword)) { $update = $conn->prepare("UPDATE {$this->mTable} SET {$this->mColumn} = :crypt WHERE id = :id"); $update->execute(array(':id' => $oAccount->Email(), ':crypt' => crypt($sNewPassword, '$' . md5(rand())))); $bResult = true; if ($this->oLogger) { $this->oLogger->Write('Success! Password changed.'); } } else { $bResult = false; if ($this->oLogger) { $this->oLogger->Write('Something went wrong. Either current password is incorrect, or new password does not match criteria.'); } } } catch (\Exception $oException) { $bResult = false; if ($this->oLogger) { $this->oLogger->WriteException($oException); } } return $bResult; }
/** * @param \RainLoop\Model\Account $oAccount * @param string $sPrevPassword * @param string $sNewPassword * * @return bool */ public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) { if ($this->oLogger) { $this->oLogger->Write('Postfix: Try to change password for ' . $oAccount->Email()); } unset($sPrevPassword); $bResult = false; if (0 < \strlen($sNewPassword)) { try { $sDsn = 'mysql:host=' . $this->sHost . ';port=' . $this->iPort . ';dbname=' . $this->sDatabase; $oPdo = new \PDO($sDsn, $this->sUser, $this->sPassword); $oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $sUpdatePassword = $this->cryptPassword($sNewPassword, $oPdo); if (0 < \strlen($sUpdatePassword)) { $oStmt = $oPdo->prepare("UPDATE {$this->sTable} SET {$this->sPasscol} = ? WHERE {$this->sUsercol} = ?"); $bResult = (bool) $oStmt->execute(array($sUpdatePassword, $oAccount->Email())); } else { if ($this->oLogger) { $this->oLogger->Write('Postfix: Encrypted password is empty', \MailSo\Log\Enumerations\Type::ERROR); } } $oPdo = null; } catch (\Exception $oException) { if ($this->oLogger) { $this->oLogger->WriteException($oException); } } } return $bResult; }
/** * @param \RainLoop\Account $oAccount * @param string $sPrevPassword * @param string $sNewPassword * * @return bool */ public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) { if ($this->oLogger) { $this->oLogger->Write('Try to change password for ' . $oAccount->Email()); } include_once __DIR__ . '/xmlapi.php'; $bResult = false; if (!empty($this->sHost) && 0 < $this->iPost && 0 < \strlen($this->sUser) && 0 < \strlen($this->sPassword) && $oAccount && \class_exists('xmlapi')) { try { $oXmlApi = new \xmlapi($this->sHost); $oXmlApi->set_port($this->iPost); $oXmlApi->set_protocol($this->sSsl ? 'https' : 'http'); $oXmlApi->set_debug(false); $oXmlApi->set_output('json'); $oXmlApi->set_http_client('curl'); $oXmlApi->password_auth($this->sUser, $this->sPassword); $sEmail = $oAccount->Email(); $aArgs = array('email' => \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail), 'domain' => \MailSo\Base\Utils::GetDomainFromEmail($sEmail), 'password' => $sNewPassword); $sResult = $oXmlApi->api2_query($this->sUser, 'Email', 'passwdpop', $aArgs); if ($sResult) { $aResult = @\json_decode($sResult, true); $bResult = isset($aResult['cpanelresult']['data'][0]['result']) && !!$aResult['cpanelresult']['data'][0]['result']; } if (!$bResult && $this->oLogger) { $this->oLogger->Write('CPANEL: ' . $sResult, \MailSo\Log\Enumerations\Type::ERROR); } } catch (\Exception $oException) { if ($this->oLogger) { $this->oLogger->WriteException($oException); } } } return $bResult; }
/** * @param \RainLoop\Model\Account $oAccount * @param string $sPrevPassword * @param string $sNewPassword * * @return bool */ public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) { $bResult = false; try { $sDomain = \MailSo\Base\Utils::GetDomainFromEmail($oAccount->Email()); $sUserDn = \strtr($this->sUserDnFormat, array('{domain}' => $sDomain, '{domain:dc}' => 'dc=' . \strtr($sDomain, array('.' => ',dc=')), '{email}' => $oAccount->Email(), '{email:user}' => \MailSo\Base\Utils::GetAccountNameFromEmail($oAccount->Email()), '{email:domain}' => $sDomain, '{login}' => $oAccount->Login(), '{imap:login}' => $oAccount->Login(), '{imap:host}' => $oAccount->DomainIncHost(), '{imap:port}' => $oAccount->DomainIncPort())); $oCon = @\ldap_connect($this->sHostName); if ($oCon) { @\ldap_set_option($oCon, LDAP_OPT_PROTOCOL_VERSION, 3); if (!@\ldap_bind($oCon, $sUserDn, $sPrevPassword)) { if ($this->oLogger) { $sError = $oCon ? @\ldap_error($oCon) : ''; $iErrno = $oCon ? @\ldap_errno($oCon) : 0; $this->oLogger->Write('ldap_bind error: ' . $sError . ' (' . $iErrno . ')', \MailSo\Log\Enumerations\Type::WARNING, 'LDAP'); } return false; } } $sEncodedNewPassword = $sNewPassword; switch (\strtolower($this->sPasswordEncType)) { case 'sha': switch (true) { default: case \function_exists('sha1'): $sEncodedNewPassword = '******' . \base64_encode(\pack('H*', \sha1($sNewPassword))); break; case \function_exists('hash'): $sEncodedNewPassword = '******' . \base64_encode(\hash('sha1', $sNewPassword, true)); break; case \function_exists('mhash') && defined('MHASH_SHA1'): $sEncodedNewPassword = '******' . \base64_encode(\mhash(MHASH_SHA1, $sNewPassword)); break; } break; case 'md5': $sEncodedNewPassword = '******' . \base64_encode(\pack('H*', \md5($sNewPassword))); break; case 'crypt': $sEncodedNewPassword = '******' . \crypt($sNewPassword, $this->getSalt(2)); break; } $aEntry = array(); $aEntry[$this->sPasswordField] = (string) $sEncodedNewPassword; if (!!@\ldap_modify($oCon, $sUserDn, $aEntry)) { $bResult = true; } else { if ($this->oLogger) { $sError = $oCon ? @\ldap_error($oCon) : ''; $iErrno = $oCon ? @\ldap_errno($oCon) : 0; $this->oLogger->Write('ldap_modify error: ' . $sError . ' (' . $iErrno . ')', \MailSo\Log\Enumerations\Type::WARNING, 'LDAP'); } } } catch (\Exception $oException) { if ($this->oLogger) { $this->oLogger->WriteException($oException, \MailSo\Log\Enumerations\Type::WARNING, 'LDAP'); } $bResult = false; } return $bResult; }
/** * * @param mixed $oCon * @param string $sCmd * * @return string */ private function logLdapError($oCon, $sCmd) { if ($this->oLogger) { $sError = $oCon ? @\ldap_error($oCon) : ''; $iErrno = $oCon ? @\ldap_errno($oCon) : 0; $this->oLogger->Write($sCmd . ' error: ' . $sError . ' (' . $iErrno . ')', \MailSo\Log\Enumerations\Type::WARNING, 'LDAP'); } }
/** * @return string */ private function getAdminToken() { $sRand = \MailSo\Base\Utils::Md5Rand(); if (!$this->Cacher(null, true)->Set(\RainLoop\KeyPathHelper::SessionAdminKey($sRand), \time())) { $this->oLogger->Write('Cannot store an admin token', \MailSo\Log\Enumerations\Type::WARNING); $sRand = ''; } return '' === $sRand ? '' : \RainLoop\Utils::EncodeKeyValuesQ(array('token', \md5(APP_SALT), $sRand)); }
/** * @param \RainLoop\Account $oAccount * @param string $sPrevPassword * @param string $sNewPassword * * @return bool */ public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) { if ($this->oLogger) { $this->oLogger->Write('DirectAdmin: Try to change password for ' . $oAccount->Email()); } $bResult = false; if (!empty($this->sHost) && 0 < $this->iPort && $oAccount) { $sEmail = \trim(\strtolower($oAccount->Email())); $sHost = \trim($this->sHost); $sHost = \str_replace('{user:host-imap}', $oAccount->Domain()->IncHost(), $sHost); $sHost = \str_replace('{user:host-smtp}', $oAccount->Domain()->OutHost(), $sHost); $sHost = \str_replace('{user:domain}', \MailSo\Base\Utils::GetDomainFromEmail($sEmail), $sHost); $sHost = \rtrim($this->sHost, '/\\'); if (!\preg_match('/^http[s]?:\\/\\//i', $sHost)) { $sHost = 'http://' . $sHost; } $sUrl = $sHost . ':' . $this->iPort . '/CMD_CHANGE_EMAIL_PASSWORD'; $iCode = 0; $oHttp = \MailSo\Base\Http::SingletonInstance(); if ($this->oLogger) { $this->oLogger->Write('DirectAdmin[Api Request]:' . $sUrl); } $mResult = $oHttp->SendPostRequest($sUrl, array('email' => $sEmail, 'oldpassword' => $sPrevPassword, 'password1' => $sNewPassword, 'password2' => $sNewPassword, 'api' => '1'), 'MailSo Http User Agent (v1)', $iCode, $this->oLogger); if (false !== $mResult && 200 === $iCode) { $aRes = null; @\parse_str($mResult, $aRes); if (is_array($aRes) && (!isset($aRes['error']) || (int) $aRes['error'] !== 1)) { $bResult = true; } else { if ($this->oLogger) { $this->oLogger->Write('DirectAdmin[Error]: Response: ' . $mResult); } } } else { if ($this->oLogger) { $this->oLogger->Write('DirectAdmin[Error]: Empty Response: Code:' . $iCode); } } } return $bResult; }
/** * @param \Exception $oException * @param int $iDescType = \MailSo\Log\Enumerations\Type::NOTICE * @param bool $bThrowException = false * * @return void */ protected function writeLogException($oException, $iDescType = \MailSo\Log\Enumerations\Type::NOTICE, $bThrowException = false) { if ($this->oLogger) { if ($oException instanceof Exceptions\SocketCanNotConnectToHostException) { $this->oLogger->Write('Socket: [' . $oException->getSocketCode() . '] ' . $oException->getSocketMessage(), $iDescType, $this->getLogName()); } $this->oLogger->WriteException($oException, $iDescType, $this->getLogName()); } if ($bThrowException) { throw $oException; } }
/** * @param \RainLoop\Account $oAccount * @param string $sPrevPassword * @param string $sNewPassword * * @return bool */ public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword) { if ($this->oLogger) { $this->oLogger->Write('Try to change password for ' . $oAccount->Email()); } if (empty($this->mHost) || empty($this->mDatabase) || empty($this->mColumn) || empty($this->mTable)) { return false; } $bResult = false; $sDsn = 'mysql:host=' . $this->mHost . ';dbname=' . $this->mDatabase . ';charset=utf8'; $aOptions = array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_PERSISTENT => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION); $sLoginPart = \MailSo\Base\Utils::GetAccountNameFromEmail($oAccount->Email()); $sDomainPart = \MailSo\Base\Utils::GetDomainFromEmail($oAccount->Email()); try { $oConn = new PDO($sDsn, $this->mUser, $this->mPass, $aOptions); $oSelect = $oConn->prepare('SELECT ' . $this->mColumn . ' FROM ' . $this->mTable . ' WHERE pw_name=? AND pw_domain=? LIMIT 1'); $oSelect->execute(array($sLoginPart, $sDomainPart)); $aColCrypt = $oSelect->fetchAll(PDO::FETCH_ASSOC); $sCryptPass = isset($aColCrypt[0][$this->mColumn]) ? $aColCrypt[0][$this->mColumn] : ''; if (0 < \strlen($sCryptPass) && \crypt($sPrevPassword, $sCryptPass) === $sCryptPass) { $oUpdate = $oConn->prepare('UPDATE ' . $this->mTable . ' SET ' . $this->mColumn . '=ENCRYPT(?,concat("$1$",right(md5(rand()), 8 ),"$")), pw_clear_passwd=\'\' WHERE pw_name=? AND pw_domain=?'); $oUpdate->execute(array($sNewPassword, $sLoginPart, $sDomainPart)); $bResult = true; if ($this->oLogger) { $this->oLogger->Write('Success! Password changed.'); } } else { $bResult = false; if ($this->oLogger) { $this->oLogger->Write('Something went wrong. Either current password is incorrect, or new password does not match criteria.'); } } } catch (\Exception $oException) { $bResult = false; if ($this->oLogger) { $this->oLogger->WriteException($oException); } } return $bResult; }
/** * @return \MailSo\Log\Logger */ public function Logger() { if (null === $this->oLogger) { $this->oLogger = \MailSo\Log\Logger::SingletonInstance(); if (!!$this->Config()->Get('logs', 'enable', true)) { $this->oLogger->SetShowSecter(!$this->Config()->Get('logs', 'hide_passwords', true)); $sLogFileFullPath = \APP_PRIVATE_DATA . 'logs/' . $this->compileLogFileName(); $sLogFileDir = \dirname($sLogFileFullPath); if (!@is_dir($sLogFileDir)) { @mkdir($sLogFileDir, 0755, true); } $this->oLogger->Add(\MailSo\Log\Drivers\File::NewInstance($sLogFileFullPath)->WriteOnErrorOnly($this->Config()->Get('logs', 'write_on_error_only', true))->WriteOnTimeoutOnly($this->Config()->Get('logs', 'write_on_timeout_only', 30))); if (!$this->Config()->Get('debug', 'enable', false)) { $this->oLogger->AddForbiddenType(\MailSo\Log\Enumerations\Type::TIME); } $this->oLogger->WriteEmptyLine(); $oHttp = $this->Http(); $this->oLogger->Write('[DATE:' . \gmdate('d.m.y') . '][RL:' . APP_VERSION . '][PHP:' . PHP_VERSION . '][IP:' . $oHttp->GetClientIp() . '][PID:' . (\MailSo\Base\Utils::FunctionExistsAndEnabled('getmypid') ? \getmypid() : 'unknown') . '][GUID:' . \MailSo\Log\Logger::Guid() . ']'); $this->oLogger->Write('[' . $oHttp->GetMethod() . '] ' . $oHttp->GetScheme() . '://' . $oHttp->GetHost(false, false) . $oHttp->GetServer('REQUEST_URI', ''), \MailSo\Log\Enumerations\Type::NOTE, 'REQUEST'); } } return $this->oLogger; }
/** * @param string $sUrl * @param resource $rFile * @param string $sCustomUserAgent = 'MailSo Http User Agent (v1)' * @param string $sContentType = '' * @param int $iCode = 0 * @param \MailSo\Log\Logger $oLogger = null * @param int $iTimeout = 10 * @param string $sProxy = '' * @param string $sProxyAuth = '' * @param array $aHttpHeaders = array() * @param bool $bFollowLocation = true * * @return bool */ public function SaveUrlToFile($sUrl, $rFile, $sCustomUserAgent = 'MailSo Http User Agent (v1)', &$sContentType = '', &$iCode = 0, $oLogger = null, $iTimeout = 10, $sProxy = '', $sProxyAuth = '', $aHttpHeaders = array(), $bFollowLocation = true) { if (null === $sCustomUserAgent) { $sCustomUserAgent = 'MailSo Http User Agent (v1)'; } if (!is_resource($rFile)) { if ($oLogger) { $oLogger->Write('cURL: input resource invalid.', \MailSo\Log\Enumerations\Type::WARNING); } return false; } $aOptions = array(CURLOPT_URL => $sUrl, CURLOPT_HEADER => false, CURLOPT_FAILONERROR => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => !!$bFollowLocation, CURLOPT_MAXREDIRS => 7, CURLOPT_FILE => $rFile, CURLOPT_TIMEOUT => (int) $iTimeout); if (0 < \strlen($sCustomUserAgent)) { $aOptions[CURLOPT_USERAGENT] = $sCustomUserAgent; } if (0 < \strlen($sProxy)) { $aOptions[CURLOPT_PROXY] = $sProxy; if (0 < \strlen($sProxyAuth)) { $aOptions[CURLOPT_PROXYUSERPWD] = $sProxyAuth; } } if (\is_array($aHttpHeaders) && 0 < \count($aHttpHeaders)) { $aOptions[CURLOPT_HTTPHEADER] = $aHttpHeaders; } if ($oLogger) { $oLogger->Write('cUrl: URL: ' . $sUrl); if (isset($aOptions[CURLOPT_HTTPHEADER]) && \is_array($aOptions[CURLOPT_HTTPHEADER]) && 0 < \count($aOptions[CURLOPT_HTTPHEADER])) { $oLogger->Write('cUrl: Headers: ' . \print_r($aOptions[CURLOPT_HTTPHEADER], true)); } } \MailSo\Base\Http::DetectAndHackFollowLocationUrl($sUrl, $aOptions, $oLogger); $oCurl = \curl_init(); \curl_setopt_array($oCurl, $aOptions); $bResult = \curl_exec($oCurl); $iCode = (int) \curl_getinfo($oCurl, CURLINFO_HTTP_CODE); $sContentType = (string) \curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE); if ($oLogger) { $oLogger->Write('cUrl: Request result: ' . ($bResult ? 'true' : 'false') . ' (Status: ' . $iCode . ', ContentType: ' . $sContentType . ')'); if (!$bResult || 200 !== $iCode) { $oLogger->Write('cUrl: Error: ' . \curl_error($oCurl), \MailSo\Log\Enumerations\Type::WARNING); } } if (\is_resource($oCurl)) { \curl_close($oCurl); } return $bResult; }
/** * @param string $sSearch * @param string $sFolderName * @param string|bool $sFolderHash * @param bool $bUseSortIfSupported = true * @param bool $bUseESearchOrESortRequest = false * @param \MailSo\Cache\CacheClient|null $oCacher = null * * @return Array|bool */ private function getSearchUidsResult($sSearch, $sFolderName, $sFolderHash, $bUseSortIfSupported = true, $bUseESearchOrESortRequest = false, $oCacher = null) { $bUidsFromCacher = false; $aResultUids = false; $bUseCacheAfterSearch = true; $sSerializedHash = ''; $bESortSupported = $bUseSortIfSupported && $bUseESearchOrESortRequest ? $this->oImapClient->IsSupported('ESORT') : false; $bESearchSupported = $bUseESearchOrESortRequest ? $this->oImapClient->IsSupported('ESEARCH') : false; $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; $sSearchCriterias = $this->getImapSearchCriterias($sSearch, 0, $bUseCacheAfterSearch); if ($bUseCacheAfterSearch && $oCacher && $oCacher->IsInited()) { $sSerializedHash = ($bUseSortIfSupported ? 'S' : 'N') . '/' . $this->oImapClient->GetLogginedUser() . '@' . $this->oImapClient->GetConnectedHost() . ':' . $this->oImapClient->GetConnectedPort() . '/' . $sFolderName . '/' . $sSearchCriterias; $sSerializedLog = '"' . $sFolderName . '" / ' . $sSearchCriterias . ''; $sSerialized = $oCacher->Get($sSerializedHash); if (!empty($sSerialized)) { $aSerialized = @\unserialize($sSerialized); if (\is_array($aSerialized) && isset($aSerialized['FolderHash'], $aSerialized['Uids']) && \is_array($aSerialized['Uids']) && $sFolderHash === $aSerialized['FolderHash']) { if ($this->oLogger) { $this->oLogger->Write('Get Serialized UIDS from cache (' . $sSerializedLog . ') [count:' . \count($aSerialized['Uids']) . ']'); } $aResultUids = $aSerialized['Uids']; $bUidsFromCacher = true; } } } if (!\is_array($aResultUids)) { if ($bUseSortIfSupported) { if ($bESortSupported) { $aESorthData = $this->oImapClient->MessageSimpleESort(array('ARRIVAL'), $sSearchCriterias, array('ALL'), true, ''); if (isset($aESorthData['ALL'])) { $aResultUids = \MailSo\Base\Utils::ParseFetchSequence($aESorthData['ALL']); $aResultUids = \array_reverse($aResultUids); } unset($aESorthData); } else { $aResultUids = $this->oImapClient->MessageSimpleSort(array('REVERSE ARRIVAL'), $sSearchCriterias, true); } } else { if (!\MailSo\Base\Utils::IsAscii($sSearch)) { try { if ($bESearchSupported) { $aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), true, '', 'UTF-8'); if (isset($aESearchData['ALL'])) { $aResultUids = \MailSo\Base\Utils::ParseFetchSequence($aESearchData['ALL']); $aResultUids = \array_reverse($aResultUids); } unset($aESearchData); } else { $aResultUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, true, 'UTF-8'); } } catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) { $oException = null; $aResultUids = false; } } if (false === $aResultUids) { if ($bESearchSupported) { $aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), true); if (isset($aESearchData['ALL'])) { $aResultUids = \MailSo\Base\Utils::ParseFetchSequence($aESearchData['ALL']); $aResultUids = \array_reverse($aResultUids); } unset($aESearchData); } else { $aResultUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, true); } } } if (!$bUidsFromCacher && $bUseCacheAfterSearch && \is_array($aResultUids) && $oCacher && $oCacher->IsInited() && 0 < \strlen($sSerializedHash)) { $oCacher->Set($sSerializedHash, \serialize(array('FolderHash' => $sFolderHash, 'Uids' => $aResultUids))); if ($this->oLogger) { $this->oLogger->Write('Save Serialized UIDS to cache (' . $sSerializedLog . ') [count:' . \count($aResultUids) . ']'); } } } return $aResultUids; }
/** * @param string $sUrl * @param resource $rFile * @param string $sCustomUserAgent = 'MaiSo Http User Agent (v1)' * @param string $sContentType = '' * @param int $iCode = 0 * @param \MailSo\Log\Logger $oLogger = null * @param int $iTimeout = 10 * * @return bool */ public function SaveUrlToFile($sUrl, $rFile, $sCustomUserAgent = 'MaiSo Http User Agent (v1)', &$sContentType = '', &$iCode = 0, $oLogger = null, $iTimeout = 10) { if (!is_resource($rFile)) { if ($oLogger) { $oLogger->Write('cURL: input resource invalid.', \MailSo\Log\Enumerations\Type::WARNING); } return false; } $aOptions = array(CURLOPT_URL => $sUrl, CURLOPT_HEADER => false, CURLOPT_FAILONERROR => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_RETURNTRANSFER => true, CURLOPT_FILE => $rFile, CURLOPT_TIMEOUT => (int) $iTimeout); if (0 < \strlen($sCustomUserAgent)) { $aOptions[CURLOPT_USERAGENT] = $sCustomUserAgent; } $oCurl = \curl_init(); \curl_setopt_array($oCurl, $aOptions); if ($oLogger) { $oLogger->Write('cURL: Send request: ' . $sUrl); } $bResult = \curl_exec($oCurl); $iCode = (int) \curl_getinfo($oCurl, CURLINFO_HTTP_CODE); $sContentType = (string) \curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE); if ($oLogger) { $oLogger->Write('cURL: Request result: ' . ($bResult ? 'true' : 'false') . ' (Status: ' . $iCode . ', ContentType: ' . $sContentType . ')'); if (!$bResult || 200 !== $iCode) { $oLogger->Write('cURL: Error: ' . \curl_error($oCurl), \MailSo\Log\Enumerations\Type::WARNING); } } if (\is_resource($oCurl)) { \curl_close($oCurl); } return $bResult; }
/** * @param string $sDesc * @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO * * @return void */ protected function writeLog($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO) { if ($this->oLogger) { $this->oLogger->Write($sDesc, $iDescType, $this->getLogName()); } }
/** * @param string $sDesc * @param int $iType = \MailSo\Log\Enumerations\Type::INFO * * @return void */ public function WriteLog($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO) { if ($this->oLogger) { $this->oLogger->Write($sDesc, $iType, 'PLUGIN'); } }
/** * @param array $aMailFoldersHelper * @param int $iOptimizationLimit = 0 * * @return array */ public function folderListOptimization($aMailFoldersHelper, $iOptimizationLimit = 0) { // optimization if (10 < $iOptimizationLimit && \is_array($aMailFoldersHelper) && $iOptimizationLimit < \count($aMailFoldersHelper)) { if ($this->oLogger) { $this->oLogger->Write('Start optimization (limit:' . $iOptimizationLimit . ') for ' . \count($aMailFoldersHelper) . ' folders'); } $iForeachLimit = 1; $aFilteredNames = array('inbox', 'sent', 'outbox', 'sentmail', 'drafts', 'junk', 'spam', 'trash', 'bin', 'archives', 'archive', 'allmail', 'all', 'starred', 'flagged', 'important', 'contacts', 'chats'); $aNewMailFoldersHelper = array(); $iCountLimit = $iForeachLimit; foreach ($aMailFoldersHelper as $iIndex => $oFolder) { // mandatory folders if ($oFolder && \in_array(\strtolower($oFolder->NameRaw()), $aFilteredNames)) { $aNewMailFoldersHelper[] = $oFolder; $aMailFoldersHelper[$iIndex] = null; } } foreach ($aMailFoldersHelper as $iIndex => $oFolder) { // subscribed folders if ($oFolder && $oFolder->IsSubscribed()) { $aNewMailFoldersHelper[] = $oFolder; $aMailFoldersHelper[$iIndex] = null; $iCountLimit--; } if (0 > $iCountLimit) { if ($iOptimizationLimit < \count($aNewMailFoldersHelper)) { break; } else { $iCountLimit = $iForeachLimit; } } } $iCountLimit = $iForeachLimit; if ($iOptimizationLimit >= \count($aNewMailFoldersHelper)) { // name filter foreach ($aMailFoldersHelper as $iIndex => $oFolder) { if ($oFolder && !\preg_match('/[{}\\[\\]]/', $oFolder->NameRaw())) { $aNewMailFoldersHelper[] = $oFolder; $aMailFoldersHelper[$iIndex] = null; $iCountLimit--; } if (0 > $iCountLimit) { if ($iOptimizationLimit < \count($aNewMailFoldersHelper)) { break; } else { $iCountLimit = $iForeachLimit; } } } } $iCountLimit = $iForeachLimit; if ($iOptimizationLimit >= \count($aNewMailFoldersHelper)) { // other foreach ($aMailFoldersHelper as $iIndex => $oFolder) { if ($oFolder) { $aNewMailFoldersHelper[] = $oFolder; $aMailFoldersHelper[$iIndex] = null; $iCountLimit--; } if (0 > $iCountLimit) { if ($iOptimizationLimit < \count($aNewMailFoldersHelper)) { break; } else { $iCountLimit = $iForeachLimit; } } } } $aMailFoldersHelper = $aNewMailFoldersHelper; if ($this->oLogger) { $this->oLogger->Write('Result optimization: ' . \count($aMailFoldersHelper) . ' folders'); } } return $aMailFoldersHelper; }
/** * @param string $sFolderName * @param int $iOffset = 0 * @param int $iLimit = 10 * @param string $sSearch = '' * @param string $sPrevUidNext = '' * @param mixed $oCacher = null * @param string $sCachePrefix = '' * @param bool $bUseSortIfSupported = false * @param bool $bUseThreadSortIfSupported = false * @param array $aExpandedThreadsUids = array() * @param bool $bUseESearchOrESortRequest = false * * @return \MailSo\Mail\MessageCollection * * @throws \MailSo\Base\Exceptions\InvalidArgumentException * @throws \MailSo\Net\Exceptions\Exception * @throws \MailSo\Imap\Exceptions\Exception */ public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', $oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $aExpandedThreadsUids = array(), $bUseESearchOrESortRequest = false) { $sSearch = \trim($sSearch); if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || !\MailSo\Base\Validator::RangeInt($iLimit, 0, 999) || !is_string($sSearch)) { throw new \MailSo\Base\Exceptions\InvalidArgumentException(); } $this->oImapClient->FolderExamine($sFolderName); $oMessageCollection = MessageCollection::NewInstance(); $oMessageCollection->FolderName = $sFolderName; $oMessageCollection->Offset = $iOffset; $oMessageCollection->Limit = $iLimit; $oMessageCollection->Search = $sSearch; $aLastCollapsedThreadUids = array(); $aThreads = array(); $iMessageCount = 0; $iMessageRealCount = 0; $iMessageUnseenCount = 0; $iMessageCacheCount = 100; $sUidNext = '0'; $sSerializedHash = ''; $bESearchSupported = $bUseESearchOrESortRequest ? $this->oImapClient->IsSupported('ESEARCH') : false; $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; $bESortSupported = $bUseSortIfSupported && $bUseESearchOrESortRequest ? $this->oImapClient->IsSupported('ESORT') : false; $bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? $this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT') : false; if (!$oCacher || !$oCacher instanceof \MailSo\Cache\CacheClient) { $oCacher = null; } $this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); $iMessageCount = $iMessageRealCount; $oMessageCollection->FolderHash = self::GenerateHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); $oMessageCollection->UidNext = $sUidNext; $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext); $bCacher = false; $bSearch = false; if (0 < $iMessageRealCount) { $bIndexAsUid = false; $aIndexOrUids = array(); $bSearch = 0 < \strlen($sSearch); if ($bSearch || !$bUseThreadSortIfSupported) { $bIndexAsUid = true; $aIndexOrUids = null; $bUseCache = true; $sSearchCriterias = $this->getImapSearchCriterias($sSearch, 0, true, $bUseCache); if ($iMessageCacheCount < $iMessageRealCount && $bUseCache && $oCacher && $oCacher->IsInited()) { $sSerializedHash = ($bUseSortIfSupported ? 'S' : 'N') . '/' . ($bUseThreadSortIfSupported ? 'T' : 'N') . '/' . $this->oImapClient->GetLogginedUser() . '@' . $this->oImapClient->GetConnectedHost() . ':' . $this->oImapClient->GetConnectedPort() . '/' . $oMessageCollection->FolderName . '/' . $sSearchCriterias; $sSerializedLog = '"' . $oMessageCollection->FolderName . '" / ' . $sSearchCriterias . ''; $sSerialized = $oCacher->Get($sSerializedHash); if (!empty($sSerialized)) { $aSerialized = @\unserialize($sSerialized); if (\is_array($aSerialized) && isset($aSerialized['FolderHash'], $aSerialized['Uids']) && \is_array($aSerialized['Uids']) && $oMessageCollection->FolderHash === $aSerialized['FolderHash']) { if ($this->oLogger) { $this->oLogger->Write('Get Serialized UIDS from cache (' . $sSerializedLog . ') [count:' . \count($aSerialized['Uids']) . ']'); } $aIndexOrUids = $aSerialized['Uids']; $bCacher = true; } } } if (!\is_array($aIndexOrUids)) { if ($bUseSortIfSupported && !$bUseThreadSortIfSupported) { if ($bESortSupported) { $aESorthData = $this->oImapClient->MessageSimpleESort(array('ARRIVAL'), $sSearchCriterias, array('ALL'), $bIndexAsUid, ''); if (isset($aESorthData['ALL'])) { $aIndexOrUids = \MailSo\Base\Utils::ParseFetchSequence($aESorthData['ALL']); $aIndexOrUids = \array_reverse($aIndexOrUids); } unset($aESorthData); } else { $aIndexOrUids = $this->oImapClient->MessageSimpleSort(array('REVERSE ARRIVAL'), $sSearchCriterias, $bIndexAsUid); } } else { if (!\MailSo\Base\Utils::IsAscii($sSearch)) { try { if ($bESearchSupported) { $aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), $bIndexAsUid, '', 'UTF-8'); if (isset($aESearchData['ALL'])) { $aIndexOrUids = \MailSo\Base\Utils::ParseFetchSequence($aESearchData['ALL']); $aIndexOrUids = \array_reverse($aIndexOrUids); } unset($aESearchData); } else { $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid, 'UTF-8'); } } catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) { $oException = null; $aIndexOrUids = null; } } if (null === $aIndexOrUids) { if ($bESearchSupported) { $aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), $bIndexAsUid); if (isset($aESearchData['ALL'])) { $aIndexOrUids = \MailSo\Base\Utils::ParseFetchSequence($aESearchData['ALL']); $aIndexOrUids = \array_reverse($aIndexOrUids); } unset($aESearchData); } else { $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid); } } } } } else { if ($bUseThreadSortIfSupported && 1 < $iMessageCount) { $bIndexAsUid = true; $aThreads = $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $oCacher); $aIndexOrUids = $this->compileLineThreadUids($aThreads, $aLastCollapsedThreadUids, $aExpandedThreadsUids, 0); $iMessageCount = \count($aIndexOrUids); } else { $bIndexAsUid = false; $aIndexOrUids = array(1); if (1 < $iMessageCount) { $aIndexOrUids = \array_reverse(\range(1, $iMessageCount)); } } } if ($bIndexAsUid && !$bCacher && \is_array($aIndexOrUids) && $oCacher && $oCacher->IsInited() && 0 < \strlen($sSerializedHash)) { $oCacher->Set($sSerializedHash, \serialize(array('FolderHash' => $oMessageCollection->FolderHash, 'Uids' => $aIndexOrUids))); if ($this->oLogger) { $this->oLogger->Write('Save Serialized UIDS to cache (' . $sSerializedLog . ') [count:' . \count($aIndexOrUids) . ']'); } } if (\is_array($aIndexOrUids)) { $oMessageCollection->MessageCount = $iMessageRealCount; $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; $oMessageCollection->MessageResultCount = 0 === \strlen($sSearch) ? $iMessageCount : \count($aIndexOrUids); if (0 < count($aIndexOrUids)) { $iOffset = 0 > $iOffset ? 0 : $iOffset; $aRequestIndexOrUids = \array_slice($aIndexOrUids, $iOffset, $iLimit); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid); } } } $aLastCollapsedThreadUidsForPage = array(); if (!$bSearch && $bUseThreadSortIfSupported && 0 < \count($aThreads)) { $oMessageCollection->ForeachList(function ($oMessage) use($aThreads, $aLastCollapsedThreadUids, &$aLastCollapsedThreadUidsForPage) { $iUid = $oMessage->Uid(); if (in_array($iUid, $aLastCollapsedThreadUids)) { $aLastCollapsedThreadUidsForPage[] = $iUid; } if (isset($aThreads[$iUid]) && \is_array($aThreads[$iUid]) && 0 < \count($aThreads[$iUid])) { $oMessage->SetThreads($aThreads[$iUid]); $oMessage->SetThreadsLen(\count($aThreads[$iUid])); } else { if (!isset($aThreads[$iUid])) { foreach ($aThreads as $iKeyUid => $mSubItem) { if (is_array($mSubItem) && in_array($iUid, $mSubItem)) { $oMessage->SetParentThread($iKeyUid); $oMessage->SetThreadsLen(\count($mSubItem)); } } } } }); $oMessageCollection->LastCollapsedThreadUids = $aLastCollapsedThreadUidsForPage; } return $oMessageCollection; }