mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Added Allow/Disallow multiple identities
This commit is contained in:
parent
28d93f70ae
commit
2f482a6288
49 changed files with 32740 additions and 32243 deletions
|
|
@ -16,7 +16,7 @@ It's not recommended to use in production environment.
|
|||
|
||||
## License
|
||||
|
||||
RainLoop Webmail (**Community edition**) is released under
|
||||
**RainLoop Webmail (Community edition)** is released under
|
||||
**GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (AGPL)**.
|
||||
http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
|
|
|
|||
|
|
@ -225,7 +225,6 @@
|
|||
{
|
||||
var
|
||||
kn = require('Knoin/Knoin'),
|
||||
sStartupUrl = Utils.pString(Settings.settingsGet('StartupUrl')),
|
||||
sCustomLogoutLink = Utils.pString(Settings.settingsGet('CustomLogoutLink')),
|
||||
bInIframe = !!Settings.settingsGet('InIframe')
|
||||
;
|
||||
|
|
@ -235,7 +234,6 @@
|
|||
|
||||
if (bLogout)
|
||||
{
|
||||
sStartupUrl = '';
|
||||
this.clearClientSideToken();
|
||||
}
|
||||
|
||||
|
|
@ -244,11 +242,6 @@
|
|||
window.close();
|
||||
}
|
||||
|
||||
if (bAdmin)
|
||||
{
|
||||
sStartupUrl = '';
|
||||
}
|
||||
|
||||
sCustomLogoutLink = sCustomLogoutLink || (bAdmin ? Links.rootAdmin() : Links.rootUser());
|
||||
|
||||
if (bLogout && window.location.href !== sCustomLogoutLink)
|
||||
|
|
@ -267,7 +260,7 @@
|
|||
else
|
||||
{
|
||||
kn.routeOff();
|
||||
kn.setHash(Links.root(sStartupUrl), true);
|
||||
kn.setHash(Links.root(), true);
|
||||
kn.routeOff();
|
||||
|
||||
_.delay(function () {
|
||||
|
|
|
|||
|
|
@ -1273,6 +1273,7 @@
|
|||
self = this,
|
||||
$LAB = require('$LAB'),
|
||||
sJsHash = Settings.settingsGet('JsHash'),
|
||||
sStartupUrl = Utils.pString(Settings.settingsGet('StartupUrl')),
|
||||
iContactsSyncInterval = Utils.pInt(Settings.settingsGet('ContactsSyncInterval')),
|
||||
bGoogle = Settings.settingsGet('AllowGoogleSocial'),
|
||||
bFacebook = Settings.settingsGet('AllowFacebookSocial'),
|
||||
|
|
@ -1314,6 +1315,13 @@
|
|||
|
||||
if (bValue)
|
||||
{
|
||||
if ('' !== sStartupUrl)
|
||||
{
|
||||
kn.routeOff();
|
||||
kn.setHash(Links.root(sStartupUrl), true);
|
||||
kn.routeOn();
|
||||
}
|
||||
|
||||
if ($LAB && window.crypto && window.crypto.getRandomValues && Settings.capa(Enums.Capa.OpenPGP))
|
||||
{
|
||||
var fOpenpgpCallback = function (openpgp) {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@
|
|||
'AttachmentThumbnails': 'ATTACHMENT_THUMBNAILS',
|
||||
'Templates': 'TEMPLATES',
|
||||
'AutoLogout': 'AUTOLOGOUT',
|
||||
'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS'
|
||||
'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS',
|
||||
'Identities': 'IDENTITIES'
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -56,9 +56,12 @@
|
|||
'SettingsContacts', 'SETTINGS_LABELS/LABEL_CONTACTS_NAME', 'contacts');
|
||||
}
|
||||
|
||||
if (Settings.capa(Enums.Capa.AdditionalAccounts) || Settings.capa(Enums.Capa.Identities))
|
||||
{
|
||||
kn.addSettingsViewModel(require('Settings/User/Accounts'), 'SettingsAccounts',
|
||||
Settings.capa(Enums.Capa.AdditionalAccounts) ?
|
||||
'SETTINGS_LABELS/LABEL_ACCOUNTS_NAME' : 'SETTINGS_LABELS/LABEL_IDENTITIES_NAME', 'accounts');
|
||||
}
|
||||
|
||||
if (Settings.capa(Enums.Capa.Sieve))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
this.capaUserBackground = CapaAdminStore.userBackground;
|
||||
this.capaGravatar = CapaAdminStore.gravatar;
|
||||
this.capaAdditionalAccounts = CapaAdminStore.additionalAccounts;
|
||||
this.capaIdentities = CapaAdminStore.identities;
|
||||
this.capaAttachmentThumbnails = CapaAdminStore.attachmentThumbnails;
|
||||
this.capaTemplates = CapaAdminStore.templates;
|
||||
|
||||
|
|
@ -136,6 +137,12 @@
|
|||
});
|
||||
});
|
||||
|
||||
self.capaIdentities.subscribe(function (bValue) {
|
||||
Remote.saveAdminConfig(null, {
|
||||
'CapaIdentities': bValue ? '1' : '0'
|
||||
});
|
||||
});
|
||||
|
||||
self.capaTemplates.subscribe(function (bValue) {
|
||||
Remote.saveAdminConfig(null, {
|
||||
'CapaTemplates': bValue ? '1' : '0'
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
function AccountsUserSettings()
|
||||
{
|
||||
this.allowAdditionalAccount = Settings.capa(Enums.Capa.AdditionalAccounts);
|
||||
this.allowIdentities = true;
|
||||
this.allowIdentities = Settings.capa(Enums.Capa.Identities);;
|
||||
|
||||
this.accounts = AccountStore.accounts;
|
||||
this.identities = IdentityStore.identities;
|
||||
|
|
|
|||
|
|
@ -16,9 +16,12 @@
|
|||
AppStore = require('Stores/User/App'),
|
||||
LanguageStore = require('Stores/Language'),
|
||||
SettingsStore = require('Stores/User/Settings'),
|
||||
IdentityStore = require('Stores/User/Identity'),
|
||||
NotificationStore = require('Stores/User/Notification'),
|
||||
MessageStore = require('Stores/User/Message'),
|
||||
|
||||
Settings = require('Storage/Settings'),
|
||||
|
||||
Remote = require('Remote/User/Ajax')
|
||||
;
|
||||
|
||||
|
|
@ -62,6 +65,20 @@
|
|||
|
||||
this.isAnimationSupported = Globals.bAnimationSupported;
|
||||
|
||||
this.identities = IdentityStore.identities;
|
||||
|
||||
this.identityMain = ko.computed(function () {
|
||||
var aList = this.identities();
|
||||
return Utils.isArray(aList) ? _.find(aList, function (oItem) {
|
||||
return oItem && '' === oItem.id() ? true : false;
|
||||
}) : null;
|
||||
}, this);
|
||||
|
||||
this.identityMainDesc = ko.computed(function () {
|
||||
var oIdentity = this.identityMain();
|
||||
return oIdentity ? oIdentity.formattedName() : '---';
|
||||
}, this);
|
||||
|
||||
this.editorDefaultTypes = ko.computed(function () {
|
||||
Translator.trigger();
|
||||
return [
|
||||
|
|
@ -82,6 +99,15 @@
|
|||
}, this);
|
||||
}
|
||||
|
||||
GeneralUserSettings.prototype.editMainIdentity = function ()
|
||||
{
|
||||
var oIdentity = this.identityMain();
|
||||
if (oIdentity)
|
||||
{
|
||||
require('Knoin/Knoin').showScreenPopup(require('View/Popup/Identity'), [oIdentity]);
|
||||
}
|
||||
};
|
||||
|
||||
GeneralUserSettings.prototype.testSoundNotification = function ()
|
||||
{
|
||||
NotificationStore.playSoundNotification(true);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
function CapaAdminStore()
|
||||
{
|
||||
this.additionalAccounts = ko.observable(false);
|
||||
this.identities = ko.observable(false);
|
||||
this.gravatar = ko.observable(false);
|
||||
this.attachmentThumbnails = ko.observable(false);
|
||||
this.sieve = ko.observable(false);
|
||||
|
|
@ -32,6 +33,7 @@
|
|||
CapaAdminStore.prototype.populate = function()
|
||||
{
|
||||
this.additionalAccounts(Settings.capa(Enums.Capa.AdditionalAccounts));
|
||||
this.identities(Settings.capa(Enums.Capa.Identities));
|
||||
this.gravatar(Settings.capa(Enums.Capa.Gravatar));
|
||||
this.attachmentThumbnails(Settings.capa(Enums.Capa.AttachmentThumbnails));
|
||||
this.sieve(Settings.capa(Enums.Capa.Sieve));
|
||||
|
|
|
|||
|
|
@ -899,6 +899,20 @@ END;
|
|||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDomain
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function GetClearDomainName($sDomain)
|
||||
{
|
||||
$sResultDomain = \preg_replace(
|
||||
'/^(webmail|email|mail|www|imap4|pop3|imap|pop|demo|client|ssl|secure)\./i',
|
||||
'', $sDomain);
|
||||
|
||||
return false === \strpos($sResultDomain, '.') ? $sDomain : $sResultDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFileName
|
||||
*
|
||||
|
|
|
|||
|
|
@ -194,9 +194,8 @@ class Actions
|
|||
*/
|
||||
public function GetShortLifeSpecAuthToken($iLife = 60)
|
||||
{
|
||||
$sToken = $this->getAuthToken();
|
||||
$aAccountHash = \RainLoop\Utils::DecodeKeyValues($sToken);
|
||||
if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && is_array($aAccountHash))
|
||||
$aAccountHash = \RainLoop\Utils::DecodeKeyValues($this->getLocalAuthToken());
|
||||
if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && \is_array($aAccountHash))
|
||||
{
|
||||
$aAccountHash[10] = \time() + $iLife;
|
||||
return \RainLoop\Utils::EncodeKeyValues($aAccountHash);
|
||||
|
|
@ -458,6 +457,18 @@ class Actions
|
|||
$this->Config()->Get('labs', 'http_client_ip_check_proxy', false)), $sLine);
|
||||
}
|
||||
|
||||
if (false !== \strpos($sLine, '{request:domain}'))
|
||||
{
|
||||
$sLine = \str_replace('{request:domain}',
|
||||
$this->Http()->GetHost(false, true, true), $sLine);
|
||||
}
|
||||
|
||||
if (false !== \strpos($sLine, '{request:domain-clear}'))
|
||||
{
|
||||
$sLine = \str_replace('{request:domain-clear}',
|
||||
\MailSo\Base\Utils::GetClearDomainName($this->Http()->GetHost(false, true, true)), $sLine);
|
||||
}
|
||||
|
||||
$sLine = \preg_replace('/\{request:([^}]*)\}/i', 'request', $sLine);
|
||||
}
|
||||
|
||||
|
|
@ -489,8 +500,12 @@ class Actions
|
|||
{
|
||||
$sEmail = $oAccount->Email();
|
||||
$sLine = \str_replace('{user:email}', $sEmail, $sLine);
|
||||
$sLine = \str_replace('{user:login}', \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail), $sLine);
|
||||
$sLine = \str_replace('{user:domain}', \MailSo\Base\Utils::GetDomainFromEmail($sEmail), $sLine);
|
||||
$sLine = \str_replace('{user:login}',
|
||||
\MailSo\Base\Utils::GetAccountNameFromEmail($sEmail), $sLine);
|
||||
$sLine = \str_replace('{user:domain}',
|
||||
\MailSo\Base\Utils::GetDomainFromEmail($sEmail), $sLine);
|
||||
$sLine = \str_replace('{user:domain-clear}',
|
||||
\MailSo\Base\Utils::GetClearDomainName(\MailSo\Base\Utils::GetDomainFromEmail($sEmail)), $sLine);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -552,7 +567,7 @@ class Actions
|
|||
{
|
||||
if ($oAccount)
|
||||
{
|
||||
$sSpecAuthToken = '_'.$oAccount->GetAuthToken();
|
||||
$sSpecAuthToken = '_'.$oAccount->GetAuthTokenQ();
|
||||
|
||||
$this->SetSpecAuthToken($sSpecAuthToken);
|
||||
\RainLoop\Utils::SetCookie(self::AUTH_SPEC_TOKEN_KEY, $sSpecAuthToken, 0, '/', null, null, true);
|
||||
|
|
@ -560,7 +575,7 @@ class Actions
|
|||
if ($oAccount->SignMe() && 0 < \strlen($oAccount->SignMeToken()))
|
||||
{
|
||||
\RainLoop\Utils::SetCookie(self::AUTH_SIGN_ME_TOKEN_KEY,
|
||||
\RainLoop\Utils::EncodeKeyValues(array(
|
||||
\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||
'e' => $oAccount->Email(),
|
||||
't' => $oAccount->SignMeToken()
|
||||
)),
|
||||
|
|
@ -569,9 +584,9 @@ class Actions
|
|||
$this->StorageProvider()->Put($oAccount,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
||||
'sign_me',
|
||||
\RainLoop\Utils::EncodeKeyValues(array(
|
||||
\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||
'Time' => \time(),
|
||||
'AuthToken' => $oAccount->GetAuthToken(),
|
||||
'AuthToken' => $oAccount->GetAuthTokenQ(),
|
||||
'SignMetToken' => $oAccount->SignMeToken()
|
||||
))
|
||||
);
|
||||
|
|
@ -618,7 +633,7 @@ class Actions
|
|||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getAuthToken()
|
||||
private function getLocalAuthToken()
|
||||
{
|
||||
$sToken = $this->GetSpecAuthToken();
|
||||
return !empty($sToken) && '_' === \substr($sToken, 0, 1) ? \substr($sToken, 1) : '';
|
||||
|
|
@ -637,7 +652,7 @@ class Actions
|
|||
*/
|
||||
public function ClearAdminAuthToken()
|
||||
{
|
||||
$aAdminHash = \RainLoop\Utils::DecodeKeyValues($this->getAdminAuthToken());
|
||||
$aAdminHash = \RainLoop\Utils::DecodeKeyValuesQ($this->getAdminAuthToken());
|
||||
if (
|
||||
!empty($aAdminHash[0]) && !empty($aAdminHash[1]) && !empty($aAdminHash[2]) &&
|
||||
'token' === $aAdminHash[0] && \md5(APP_SALT) === $aAdminHash[1]
|
||||
|
|
@ -1085,7 +1100,7 @@ class Actions
|
|||
$sRand = '';
|
||||
}
|
||||
|
||||
return '' === $sRand ? '' : \RainLoop\Utils::EncodeKeyValues(array('token', \md5(APP_SALT), $sRand));
|
||||
return '' === $sRand ? '' : \RainLoop\Utils::EncodeKeyValuesQ(array('token', \md5(APP_SALT), $sRand));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1098,7 +1113,7 @@ class Actions
|
|||
$bResult = false;
|
||||
if ($this->Config()->Get('security', 'allow_admin_panel', true))
|
||||
{
|
||||
$aAdminHash = \RainLoop\Utils::DecodeKeyValues($this->getAdminAuthToken());
|
||||
$aAdminHash = \RainLoop\Utils::DecodeKeyValuesQ($this->getAdminAuthToken());
|
||||
if (!empty($aAdminHash[0]) && !empty($aAdminHash[1]) && !empty($aAdminHash[2]) &&
|
||||
'token' === $aAdminHash[0] && \md5(APP_SALT) === $aAdminHash[1] &&
|
||||
'' !== $this->Cacher(null, true)->Get(\RainLoop\KeyPathHelper::SessionAdminKey($aAdminHash[2]), '')
|
||||
|
|
@ -1124,7 +1139,7 @@ class Actions
|
|||
if (!empty($sTo))
|
||||
{
|
||||
\RainLoop\Utils::SetCookie(self::AUTH_MAILTO_TOKEN_KEY,
|
||||
\RainLoop\Utils::EncodeKeyValues(array(
|
||||
\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||
'Time' => \microtime(true),
|
||||
'MailTo' => 'MailTo',
|
||||
'To' => $sTo
|
||||
|
|
@ -1177,16 +1192,17 @@ class Actions
|
|||
* @param string $sToken
|
||||
* @param bool $bThrowExceptionOnFalse = true
|
||||
* @param bool $bValidateShortToken = true
|
||||
* @param bool $bQ = false
|
||||
*
|
||||
* @return \RainLoop\Model\Account|bool
|
||||
* @throws \RainLoop\Exceptions\ClientException
|
||||
*/
|
||||
public function GetAccountFromCustomToken($sToken, $bThrowExceptionOnFalse = true, $bValidateShortToken = true)
|
||||
public function GetAccountFromCustomToken($sToken, $bThrowExceptionOnFalse = true, $bValidateShortToken = true, $bQ = false)
|
||||
{
|
||||
$oResult = false;
|
||||
if (!empty($sToken))
|
||||
{
|
||||
$aAccountHash = \RainLoop\Utils::DecodeKeyValues($sToken);
|
||||
$aAccountHash = $bQ ? \RainLoop\Utils::DecodeKeyValuesQ($sToken) : \RainLoop\Utils::DecodeKeyValues($sToken);
|
||||
if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && // simple token validation
|
||||
8 <= \count($aAccountHash) && // length checking
|
||||
!empty($aAccountHash[7]) && // does short token exist
|
||||
|
|
@ -1236,7 +1252,7 @@ class Actions
|
|||
$sSignMeToken = \RainLoop\Utils::GetCookie(\RainLoop\Actions::AUTH_SIGN_ME_TOKEN_KEY, '');
|
||||
if (!empty($sSignMeToken))
|
||||
{
|
||||
$aTokenData = \RainLoop\Utils::DecodeKeyValues($sSignMeToken);
|
||||
$aTokenData = \RainLoop\Utils::DecodeKeyValuesQ($sSignMeToken);
|
||||
if (\is_array($aTokenData) && !empty($aTokenData['e']) && !empty($aTokenData['t']))
|
||||
{
|
||||
$sTokenSettings = $this->StorageProvider()->Get($aTokenData['e'],
|
||||
|
|
@ -1246,13 +1262,13 @@ class Actions
|
|||
|
||||
if (!empty($sTokenSettings))
|
||||
{
|
||||
$aSignMeData = \RainLoop\Utils::DecodeKeyValues($sTokenSettings);
|
||||
$aSignMeData = \RainLoop\Utils::DecodeKeyValuesQ($sTokenSettings);
|
||||
if (\is_array($aSignMeData) &&
|
||||
!empty($aSignMeData['AuthToken']) &&
|
||||
!empty($aSignMeData['SignMetToken']) &&
|
||||
$aSignMeData['SignMetToken'] === $aTokenData['t'])
|
||||
{
|
||||
$oAccount = $this->GetAccountFromCustomToken($aSignMeData['AuthToken'], false, false);
|
||||
$oAccount = $this->GetAccountFromCustomToken($aSignMeData['AuthToken'], false, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1273,7 +1289,7 @@ class Actions
|
|||
*/
|
||||
public function getAccountFromToken($bThrowExceptionOnFalse = true)
|
||||
{
|
||||
return $this->GetAccountFromCustomToken($this->getAuthToken(), $bThrowExceptionOnFalse);
|
||||
return $this->GetAccountFromCustomToken($this->getLocalAuthToken(), $bThrowExceptionOnFalse, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1467,9 +1483,10 @@ class Actions
|
|||
if (null !== $sToken)
|
||||
{
|
||||
\RainLoop\Utils::ClearCookie(self::AUTH_MAILTO_TOKEN_KEY);
|
||||
$mMailToData = \RainLoop\Utils::DecodeKeyValues($sToken);
|
||||
if (\is_array($mMailToData) && !empty($mMailToData['MailTo']) && 'MailTo' === $mMailToData['MailTo'] &&
|
||||
!empty($mMailToData['To']))
|
||||
|
||||
$mMailToData = \RainLoop\Utils::DecodeKeyValuesQ($sToken);
|
||||
if (\is_array($mMailToData) && !empty($mMailToData['MailTo']) &&
|
||||
'MailTo' === $mMailToData['MailTo'] && !empty($mMailToData['To']))
|
||||
{
|
||||
$aResult['MailToEmail'] = $mMailToData['To'];
|
||||
}
|
||||
|
|
@ -1496,6 +1513,8 @@ class Actions
|
|||
$aResult['WelcomePageUrl'] = '';
|
||||
$aResult['WelcomePageDisplay'] = '';
|
||||
}
|
||||
|
||||
$aResult['StartupUrl'] = $this->compileLogParams($aResult['StartupUrl'], $oAccount);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1509,6 +1528,8 @@ class Actions
|
|||
|
||||
$aResult['WelcomePageUrl'] = '';
|
||||
$aResult['WelcomePageDisplay'] = '';
|
||||
|
||||
$aResult['StartupUrl'] = '';
|
||||
}
|
||||
|
||||
$aResult['AllowGoogleSocial'] = (bool) $oConfig->Get('social', 'google_enable', false);
|
||||
|
|
@ -2109,51 +2130,27 @@ class Actions
|
|||
*/
|
||||
private function clientRsaDecryptHelper($sEncryptedData)
|
||||
{
|
||||
$aMatch = array();
|
||||
if ('rsa:xxx:' === substr($sEncryptedData, 0, 8) && $this->Config()->Get('security', 'use_rsa_encryption', false))
|
||||
{
|
||||
$oLogger = $this->Logger();
|
||||
$oLogger->Write('Trying to decode encrypted data', \MailSo\Log\Enumerations\Type::INFO, 'RSA');
|
||||
|
||||
$sPrivateKey = file_exists(APP_PRIVATE_DATA.'rsa/private') ?
|
||||
\file_get_contents(APP_PRIVATE_DATA.'rsa/private') : '';
|
||||
|
||||
if (!empty($sPrivateKey))
|
||||
{
|
||||
$sData = \trim(\substr($sEncryptedData, 8));
|
||||
|
||||
if (!\class_exists('Crypt_RSA'))
|
||||
{
|
||||
\set_include_path(\get_include_path().PATH_SEPARATOR.APP_VERSION_ROOT_PATH.'app/libraries/phpseclib');
|
||||
include_once 'Crypt/RSA.php';
|
||||
\defined('CRYPT_RSA_MODE') || \define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
|
||||
}
|
||||
|
||||
$oLogger->HideErrorNotices(true);
|
||||
|
||||
$oRsa = new \Crypt_RSA();
|
||||
$oRsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
|
||||
$oRsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
|
||||
$oRsa->setPrivateKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
|
||||
$oRsa->loadKey($sPrivateKey, CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
|
||||
|
||||
$sData = $oRsa->decrypt(\base64_decode($sData));
|
||||
if (\preg_match('/^[a-z0-9]{32}:(.+):[a-z0-9]{32}$/', $sData, $aMatch) && isset($aMatch[1]))
|
||||
{
|
||||
$sEncryptedData = $aMatch[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
$oLogger->Write('Invalid decrypted data', \MailSo\Log\Enumerations\Type::WARNING, 'RSA');
|
||||
}
|
||||
|
||||
$oLogger->HideErrorNotices(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oLogger->Write('Private key is not found', \MailSo\Log\Enumerations\Type::WARNING, 'RSA');
|
||||
}
|
||||
}
|
||||
// $aMatch = array();
|
||||
// if ('rsa:xxx:' === \substr($sEncryptedData, 0, 8) && $this->Config()->Get('security', 'use_rsa_encryption', false))
|
||||
// {
|
||||
// $oLogger = $this->Logger();
|
||||
// $oLogger->Write('Trying to decode encrypted data', \MailSo\Log\Enumerations\Type::INFO, 'RSA');
|
||||
// $oLogger->HideErrorNotices(true);
|
||||
//
|
||||
// $sData = \trim(\substr($sEncryptedData, 8));
|
||||
// $sData = \RainLoop\Utils::DecryptStringRSA(\base64_decode($sData));
|
||||
//
|
||||
// if (false !== $sData && \preg_match('/^[a-z0-9]{32}:(.+):[a-z0-9]{32}$/', $sData, $aMatch) && isset($aMatch[1]))
|
||||
// {
|
||||
// $sEncryptedData = $aMatch[1];
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// $oLogger->Write('Invalid decrypted data', \MailSo\Log\Enumerations\Type::WARNING, 'RSA');
|
||||
// }
|
||||
//
|
||||
// $oLogger->HideErrorNotices(false);
|
||||
// }
|
||||
|
||||
return $sEncryptedData;
|
||||
}
|
||||
|
|
@ -2290,6 +2287,7 @@ class Actions
|
|||
1 < \count($aOrder['Accounts']))
|
||||
{
|
||||
$aAccounts = \array_merge(\array_flip($aOrder['Accounts']), $aAccounts);
|
||||
|
||||
$aAccounts = \array_filter($aAccounts, function ($sHash) {
|
||||
return 5 < \strlen($sHash);
|
||||
});
|
||||
|
|
@ -2390,10 +2388,11 @@ class Actions
|
|||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param bool $bAllowIdentities = false
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetIdentities($oAccount)
|
||||
public function GetIdentities($oAccount, $bAllowIdentities = false)
|
||||
{
|
||||
$aIdentities = array();
|
||||
if ($oAccount)
|
||||
|
|
@ -2421,14 +2420,14 @@ class Actions
|
|||
|
||||
if ($oItem && $oItem->Validate())
|
||||
{
|
||||
if ('' === $oItem->Id())
|
||||
if ($oItem->IsAccountIdentities())
|
||||
{
|
||||
$oItem->SetEmail($oAccount->Email());
|
||||
$bHasAccountIdentity = true;
|
||||
|
||||
\array_unshift($aIdentities, $oItem);
|
||||
\array_push($aIdentities, $oItem);
|
||||
}
|
||||
else
|
||||
else if ($bAllowIdentities)
|
||||
{
|
||||
\array_push($aIdentities, $oItem);
|
||||
}
|
||||
|
|
@ -2442,7 +2441,7 @@ class Actions
|
|||
\RainLoop\Model\Identity::NewInstanceFromAccount($oAccount));
|
||||
}
|
||||
|
||||
if (1 < \count($aIdentities))
|
||||
if (1 < \count($aIdentities) && $bAllowIdentities)
|
||||
{
|
||||
$sOrder = $this->StorageProvider()->Get($oAccount,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
||||
|
|
@ -2454,8 +2453,16 @@ class Actions
|
|||
1 < \count($aOrder['Identities']))
|
||||
{
|
||||
$aList = $aOrder['Identities'];
|
||||
foreach ($aList as $iIndex => $sItem)
|
||||
{
|
||||
if ('' === $sItem)
|
||||
{
|
||||
$aList[$iIndex] = '---';
|
||||
}
|
||||
}
|
||||
|
||||
\usort($aIdentities, function ($a, $b) use ($aList) {
|
||||
return \array_search($a->Id(), $aList) < \array_search($b->Id(), $aList) ? -1 : 1;
|
||||
return \array_search($a->Id(true), $aList) < \array_search($b->Id(true), $aList) ? -1 : 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -2527,14 +2534,20 @@ class Actions
|
|||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param array $aIdentities = array()
|
||||
* @param bool $bAllowIdentities = false
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function SetIdentities($oAccount, $aIdentities = array())
|
||||
public function SetIdentities($oAccount, $aIdentities = array(), $bAllowIdentities = false)
|
||||
{
|
||||
$aResult = array();
|
||||
foreach ($aIdentities as $oItem)
|
||||
{
|
||||
if (!$bAllowIdentities && $oItem && !$oItem->IsAccountIdentities())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$aResult[] = $oItem->ToSimpleJSON(false);
|
||||
}
|
||||
|
||||
|
|
@ -2675,7 +2688,7 @@ class Actions
|
|||
$oNewAccount->SetParentEmail($sParentEmail);
|
||||
|
||||
$aAccounts[$oNewAccount->Email()] = $oNewAccount->GetAuthToken();
|
||||
if (0 === \strlen($oAccount->ParentEmail()))
|
||||
if (!$oAccount->IsAdditionalAccount())
|
||||
{
|
||||
$aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken();
|
||||
}
|
||||
|
|
@ -2824,7 +2837,7 @@ class Actions
|
|||
$mResult = array(
|
||||
'Files' => array(array(
|
||||
'FileName' => 'attachments.zip',
|
||||
'Hash' => \RainLoop\Utils::EncodeKeyValues(array(
|
||||
'Hash' => \RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||
'V' => APP_VERSION,
|
||||
'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
|
||||
'FileName' => 'attachments.zip',
|
||||
|
|
@ -2912,7 +2925,7 @@ class Actions
|
|||
{
|
||||
$mResult['Files'][] = array(
|
||||
'FileName' => isset($aItem['FileName']) ? $aItem['FileName'] : 'file.dat',
|
||||
'Hash' => \RainLoop\Utils::EncodeKeyValues($aItem)
|
||||
'Hash' => \RainLoop\Utils::EncodeKeyValuesQ($aItem)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -2943,20 +2956,34 @@ class Actions
|
|||
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidInputArgument);
|
||||
}
|
||||
|
||||
$aIdentitiesForSave = array();
|
||||
$aIdentities = $this->GetIdentities($oAccount,
|
||||
$this->GetCapa(false, \RainLoop\Enumerations\Capa::IDENTITIES, $oAccount));
|
||||
|
||||
$aIdentities = $this->GetIdentities($oAccount);
|
||||
$bAdded = false;
|
||||
$aIdentitiesForSave = array();
|
||||
foreach ($aIdentities as $oItem)
|
||||
{
|
||||
if ($oItem && $oItem->Id() !== $oIdentity->Id())
|
||||
if ($oItem)
|
||||
{
|
||||
if ($oItem->Id() === $oIdentity->Id())
|
||||
{
|
||||
$aIdentitiesForSave[] = $oIdentity;
|
||||
$bAdded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aIdentitiesForSave[] = $oItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$bAdded)
|
||||
{
|
||||
$aIdentitiesForSave[] = $oIdentity;
|
||||
}
|
||||
|
||||
return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aIdentitiesForSave));
|
||||
return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aIdentitiesForSave,
|
||||
$this->GetCapa(false, \RainLoop\Enumerations\Capa::IDENTITIES, $oAccount)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2968,6 +2995,11 @@ class Actions
|
|||
{
|
||||
$oAccount = $this->getAccountFromToken();
|
||||
|
||||
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::IDENTITIES, $oAccount))
|
||||
{
|
||||
return $this->FalseResponse(__FUNCTION__);
|
||||
}
|
||||
|
||||
$sId = \trim($this->GetActionParam('IdToDelete', ''));
|
||||
if (empty($sId))
|
||||
{
|
||||
|
|
@ -2975,7 +3007,7 @@ class Actions
|
|||
}
|
||||
|
||||
$aNew = array();
|
||||
$aIdentities = $this->GetIdentities($oAccount);
|
||||
$aIdentities = $this->GetIdentities($oAccount, $this->GetCapa(false, \RainLoop\Enumerations\Capa::IDENTITIES, $oAccount));
|
||||
foreach ($aIdentities as $oItem)
|
||||
{
|
||||
if ($oItem && $sId !== $oItem->Id())
|
||||
|
|
@ -2984,7 +3016,8 @@ class Actions
|
|||
}
|
||||
}
|
||||
|
||||
return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aNew));
|
||||
return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aNew,
|
||||
$this->GetCapa(false, \RainLoop\Enumerations\Capa::IDENTITIES, $oAccount)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3110,7 +3143,7 @@ class Actions
|
|||
$aAccounts = $this->GetActionParam('Accounts', null);
|
||||
$aIdentities = $this->GetActionParam('Identities', null);
|
||||
|
||||
if (!\is_array($aAccounts) || !\is_array($aIdentities))
|
||||
if (!\is_array($aAccounts) && !\is_array($aIdentities))
|
||||
{
|
||||
return $this->FalseResponse(__FUNCTION__);
|
||||
}
|
||||
|
|
@ -3118,8 +3151,8 @@ class Actions
|
|||
return $this->DefaultResponse(__FUNCTION__, $this->StorageProvider()->Put($oAccount,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'accounts_identities_order',
|
||||
\json_encode(array(
|
||||
'Accounts' => $aAccounts,
|
||||
'Identities' => $aIdentities
|
||||
'Accounts' => \is_array($aAccounts) ? $aAccounts : array(),
|
||||
'Identities' => \is_array($aIdentities) ? $aIdentities : array()
|
||||
))
|
||||
));
|
||||
}
|
||||
|
|
@ -3134,6 +3167,7 @@ class Actions
|
|||
$oAccount = $this->getAccountFromToken();
|
||||
|
||||
$mAccounts = false;
|
||||
|
||||
if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount))
|
||||
{
|
||||
$mAccounts = $this->GetAccounts($oAccount);
|
||||
|
|
@ -3147,7 +3181,8 @@ class Actions
|
|||
|
||||
return $this->DefaultResponse(__FUNCTION__, array(
|
||||
'Accounts' => $mAccounts,
|
||||
'Identities' => $this->GetIdentities($oAccount)
|
||||
'Identities' => $this->GetIdentities($oAccount,
|
||||
$this->GetCapa(false, \RainLoop\Enumerations\Capa::IDENTITIES, $oAccount))
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -3448,6 +3483,9 @@ class Actions
|
|||
case \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS:
|
||||
$this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_additional_accounts', 'bool');
|
||||
break;
|
||||
case \RainLoop\Enumerations\Capa::IDENTITIES:
|
||||
$this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_additional_identities', 'bool');
|
||||
break;
|
||||
case \RainLoop\Enumerations\Capa::TEMPLATES:
|
||||
$this->setConfigFromParams($oConfig, $sParamName, 'capa', 'templates', 'bool');
|
||||
break;
|
||||
|
|
@ -3560,6 +3598,7 @@ class Actions
|
|||
});
|
||||
|
||||
$this->setCapaFromParams($oConfig, 'CapaAdditionalAccounts', \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS);
|
||||
$this->setCapaFromParams($oConfig, 'CapaIdentities', \RainLoop\Enumerations\Capa::IDENTITIES);
|
||||
$this->setCapaFromParams($oConfig, 'CapaTemplates', \RainLoop\Enumerations\Capa::TEMPLATES);
|
||||
$this->setCapaFromParams($oConfig, 'CapaTwoFactorAuth', \RainLoop\Enumerations\Capa::TWO_FACTOR);
|
||||
$this->setCapaFromParams($oConfig, 'CapaTwoFactorAuthForce', \RainLoop\Enumerations\Capa::TWO_FACTOR_FORCE);
|
||||
|
|
@ -7128,19 +7167,19 @@ class Actions
|
|||
try
|
||||
{
|
||||
$aAttachments = $this->GetActionParam('Attachments', array());
|
||||
if (is_array($aAttachments) && 0 < count($aAttachments))
|
||||
if (\is_array($aAttachments) && 0 < \count($aAttachments))
|
||||
{
|
||||
$mResult = array();
|
||||
foreach ($aAttachments as $sAttachment)
|
||||
{
|
||||
$aValues = \RainLoop\Utils::DecodeKeyValues($sAttachment);
|
||||
if (is_array($aValues))
|
||||
$aValues = \RainLoop\Utils::DecodeKeyValuesQ($sAttachment);
|
||||
if (\is_array($aValues))
|
||||
{
|
||||
$sFolder = isset($aValues['Folder']) ? $aValues['Folder'] : '';
|
||||
$iUid = (int) isset($aValues['Uid']) ? $aValues['Uid'] : 0;
|
||||
$sMimeIndex = (string) isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : '';
|
||||
|
||||
$sTempName = md5($sAttachment);
|
||||
$sTempName = \md5($sAttachment);
|
||||
if (!$this->FilesProvider()->FileExists($oAccount, $sTempName))
|
||||
{
|
||||
$this->MailClient()->MessageMimeStream(
|
||||
|
|
@ -7738,7 +7777,7 @@ class Actions
|
|||
$aParams = $this->GetActionParam('Params', null);
|
||||
$this->Http()->ServerNoCache();
|
||||
|
||||
$aData = \RainLoop\Utils::DecodeKeyValues($sRawKey);
|
||||
$aData = \RainLoop\Utils::DecodeKeyValuesQ($sRawKey);
|
||||
if (isset($aParams[0], $aParams[1], $aParams[2]) &&
|
||||
'Raw' === $aParams[0] && 'FramedView' === $aParams[2] && isset($aData['Framed']) && $aData['Framed'] && $aData['FileName'])
|
||||
{
|
||||
|
|
@ -7842,6 +7881,11 @@ class Actions
|
|||
$aResult[] = \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS;
|
||||
}
|
||||
|
||||
if ($oConfig->Get('webmail', 'allow_additional_identities', false))
|
||||
{
|
||||
$aResult[] = \RainLoop\Enumerations\Capa::IDENTITIES;
|
||||
}
|
||||
|
||||
if ($oConfig->Get('security', 'allow_two_factor_auth', false) &&
|
||||
($bAdmin || ($oAccount && !$oAccount->IsAdditionalAccount())))
|
||||
{
|
||||
|
|
@ -8399,7 +8443,7 @@ class Actions
|
|||
$bResult = false;
|
||||
if (!empty($sRawKey))
|
||||
{
|
||||
$aValues = \RainLoop\Utils::DecodeKeyValues($sRawKey);
|
||||
$aValues = \RainLoop\Utils::DecodeKeyValuesQ($sRawKey);
|
||||
if (is_array($aValues))
|
||||
{
|
||||
$bResult = $aValues;
|
||||
|
|
@ -9205,7 +9249,7 @@ class Actions
|
|||
|
||||
$sSubject = $mResult['Subject'];
|
||||
$mResult['Hash'] = \md5($mResult['Folder'].$mResult['Uid']);
|
||||
$mResult['RequestHash'] = \RainLoop\Utils::EncodeKeyValues(array(
|
||||
$mResult['RequestHash'] = \RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||
'V' => APP_VERSION,
|
||||
'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
|
||||
'Folder' => $mResult['Folder'],
|
||||
|
|
@ -9270,7 +9314,7 @@ class Actions
|
|||
if (!!$this->Config()->Get('labs', 'use_local_proxy_for_external_images', false))
|
||||
{
|
||||
$fAdditionalExternalFilter = function ($sUrl) {
|
||||
return './?/ProxyExternal/'.\RainLoop\Utils::EncodeKeyValues(array(
|
||||
return './?/ProxyExternal/'.\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||
'Rnd' => \md5(\microtime(true)),
|
||||
'Token' => \RainLoop\Utils::GetConnectionToken(),
|
||||
'Url' => $sUrl
|
||||
|
|
@ -9421,7 +9465,7 @@ class Actions
|
|||
$mResult['IsThumbnail'] = $this->isFileHasThumbnail($mResult['FileName']);
|
||||
}
|
||||
|
||||
$mResult['Download'] = \RainLoop\Utils::EncodeKeyValues(array(
|
||||
$mResult['Download'] = \RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||
'V' => APP_VERSION,
|
||||
'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
|
||||
'Folder' => $mResult['Folder'],
|
||||
|
|
|
|||
|
|
@ -139,7 +139,8 @@ class Api
|
|||
{
|
||||
$sSsoHash = \MailSo\Base\Utils::Sha1Rand($sEmail.$sPassword);
|
||||
|
||||
return \RainLoop\Api::Actions()->Cacher()->Set(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash), \RainLoop\Utils::EncodeKeyValues(array(
|
||||
return \RainLoop\Api::Actions()->Cacher()->Set(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash),
|
||||
\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||
'Email' => $sEmail,
|
||||
'Password' => $sPassword,
|
||||
'AdditionalOptions' => $aAdditionalOptions,
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ class Application extends \RainLoop\Config\AbstractConfig
|
|||
'allow_languages_on_settings' => array(true, 'Allow language selection on settings screen'),
|
||||
|
||||
'allow_additional_accounts' => array(true, ''),
|
||||
'allow_additional_identities' => array(true, ''),
|
||||
|
||||
'messages_per_page' => array(20, ' Number of messages displayed on page by default'),
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class Capa
|
|||
const FILTERS = 'FILTERS';
|
||||
const ATTACHMENT_THUMBNAILS = 'ATTACHMENT_THUMBNAILS';
|
||||
const ADDITIONAL_ACCOUNTS = 'ADDITIONAL_ACCOUNTS';
|
||||
const IDENTITIES = 'IDENTITIES';
|
||||
const TEMPLATES = 'TEMPLATES';
|
||||
const AUTOLOGOUT = 'AUTOLOGOUT';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -366,6 +366,26 @@ class Account extends \RainLoop\Account // for backward compatibility
|
|||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetAuthTokenQ()
|
||||
{
|
||||
return \RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||
'token', // 0
|
||||
$this->sEmail, // 1
|
||||
$this->sLogin, // 2
|
||||
$this->sPassword, // 3
|
||||
\RainLoop\Utils::Fingerprint(), // 4
|
||||
$this->sSignMeToken, // 5
|
||||
$this->sParentEmail, // 6
|
||||
\RainLoop\Utils::GetShortToken(), // 7
|
||||
$this->sProxyAuthUser, // 8
|
||||
$this->sProxyAuthPassword, // 9
|
||||
0 // 10 // timelife
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Plugins\Manager $oPlugins
|
||||
* @param \MailSo\Mail\MailClient $oMailClient
|
||||
|
|
|
|||
|
|
@ -75,11 +75,13 @@ class Identity
|
|||
}
|
||||
|
||||
/**
|
||||
* @param bool $bFillOnEmpty = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function Id()
|
||||
public function Id($bFillOnEmpty = false)
|
||||
{
|
||||
return $this->sId;
|
||||
return $bFillOnEmpty ? ('' === $this->sId ? '---' : $this->sId) : $this->sId;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -192,4 +194,12 @@ class Identity
|
|||
{
|
||||
return !empty($this->sEmail);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAccountIdentities()
|
||||
{
|
||||
return '' === $this->Id();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@ class ServiceActions
|
|||
{
|
||||
$this->oActions->verifyCacheByKey($sData);
|
||||
|
||||
$aData = \RainLoop\Utils::DecodeKeyValues($sData);
|
||||
$aData = \RainLoop\Utils::DecodeKeyValuesQ($sData);
|
||||
if (\is_array($aData) && !empty($aData['Token']) && !empty($aData['Url']) && $aData['Token'] === \RainLoop\Utils::GetConnectionToken())
|
||||
{
|
||||
$iCode = 404;
|
||||
|
|
@ -892,7 +892,7 @@ class ServiceActions
|
|||
$sSsoSubData = $this->Cacher()->Get(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash));
|
||||
if (!empty($sSsoSubData))
|
||||
{
|
||||
$mData = \RainLoop\Utils::DecodeKeyValues($sSsoSubData);
|
||||
$mData = \RainLoop\Utils::DecodeKeyValuesQ($sSsoSubData);
|
||||
$this->Cacher()->Delete(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash));
|
||||
|
||||
if (\is_array($mData) && !empty($mData['Email']) && isset($mData['Password'], $mData['Time']) &&
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ class Utils
|
|||
{
|
||||
static $Cookies = null;
|
||||
|
||||
static $RSA = null;
|
||||
|
||||
static $RsaKey = null;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
|
|
@ -31,6 +35,145 @@ class Utils
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Crypt_RSA|null
|
||||
*/
|
||||
static public function CryptRSA()
|
||||
{
|
||||
if (null === \RainLoop\Utils::$RSA)
|
||||
{
|
||||
if (!\defined('_phpseclib_'))
|
||||
{
|
||||
\set_include_path(\get_include_path().PATH_SEPARATOR.APP_VERSION_ROOT_PATH.'app/libraries/phpseclib');
|
||||
define('_phpseclib_', true);
|
||||
}
|
||||
|
||||
if (!\class_exists('Crypt_RSA'))
|
||||
{
|
||||
include_once 'Crypt/RSA.php';
|
||||
\defined('CRYPT_RSA_MODE') || \define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
|
||||
}
|
||||
|
||||
if (\class_exists('Crypt_RSA'))
|
||||
{
|
||||
$oRsa = new \Crypt_RSA();
|
||||
|
||||
$oRsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
|
||||
$oRsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
|
||||
$oRsa->setPrivateKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
|
||||
|
||||
$sPrivateKey = \file_exists(APP_PRIVATE_DATA.'rsa/private') ?
|
||||
\file_get_contents(APP_PRIVATE_DATA.'rsa/private') : '';
|
||||
|
||||
if (!empty($sPrivateKey))
|
||||
{
|
||||
$oRsa->loadKey($sPrivateKey, CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
|
||||
$oRsa->loadKey($oRsa->getPublicKey(), CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
|
||||
|
||||
\RainLoop\Utils::$RSA = $oRsa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return \RainLoop\Utils::$RSA;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
static public function RsaPrivateKey()
|
||||
{
|
||||
if (!empty(\RainLoop\Utils::$RsaKey))
|
||||
{
|
||||
return \RainLoop\Utils::$RsaKey;
|
||||
}
|
||||
|
||||
\RainLoop\Utils::$RsaKey = \file_exists(APP_PRIVATE_DATA.'rsa/private') ?
|
||||
\file_get_contents(APP_PRIVATE_DATA.'rsa/private') : '';
|
||||
|
||||
\RainLoop\Utils::$RsaKey = \is_string(\RainLoop\Utils::$RsaKey) ? \RainLoop\Utils::$RsaKey : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sString
|
||||
* @param string $sKey = ''
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
static public function EncryptStringRSA($sString, $sKey = '')
|
||||
{
|
||||
$sResult = '';
|
||||
$sKey = \md5($sKey);
|
||||
|
||||
$sPrivateKey = \RainLoop\Utils::RsaPrivateKey();
|
||||
if (!empty($sPrivateKey))
|
||||
{
|
||||
$oPrivKey = \openssl_pkey_get_private($sPrivateKey);
|
||||
$oKeyDetails = \openssl_pkey_get_details($oPrivKey);
|
||||
|
||||
if (!empty($oKeyDetails['key']) && !empty($oKeyDetails['bits']))
|
||||
{
|
||||
$oPubKey = \openssl_pkey_get_public($oKeyDetails['key']);
|
||||
|
||||
$iC = (($oKeyDetails['bits'] / 8) - 15);
|
||||
$aString = \str_split($sString, $iC);
|
||||
|
||||
foreach ($aString as $iIndex => $sLine)
|
||||
{
|
||||
$sEncrypted = '';
|
||||
\openssl_public_encrypt($sLine, $sEncrypted, $oPubKey);
|
||||
$aString[$iIndex] = $sEncrypted;
|
||||
}
|
||||
|
||||
$aString[] = $sKey;
|
||||
$sResult = @\serialize($aString);
|
||||
|
||||
\openssl_free_key($oPubKey);
|
||||
}
|
||||
|
||||
\openssl_free_key($oPrivKey);
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sString
|
||||
* @param string $sKey = ''
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
static public function DecryptStringRSA($sString, $sKey = '')
|
||||
{
|
||||
$sResult = '';
|
||||
$sKey = \md5($sKey);
|
||||
|
||||
$sPrivateKey = \RainLoop\Utils::RsaPrivateKey();
|
||||
if (!empty($sPrivateKey) && !empty($sString))
|
||||
{
|
||||
$oPrivKey = \openssl_pkey_get_private($sPrivateKey);
|
||||
|
||||
$aString = @\unserialize($sString);
|
||||
if (\is_array($aString))
|
||||
{
|
||||
if ($sKey === \array_pop($aString))
|
||||
{
|
||||
foreach ($aString as $iIndex => $sLine)
|
||||
{
|
||||
$sDecrypted = '';
|
||||
\openssl_private_decrypt($sLine, $sDecrypted, $oPrivKey);
|
||||
$aString[$iIndex] = $sDecrypted;
|
||||
}
|
||||
|
||||
$sResult = \implode('', $aString);
|
||||
}
|
||||
}
|
||||
|
||||
\openssl_free_key($oPrivKey);
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sString
|
||||
|
|
@ -54,6 +197,42 @@ class Utils
|
|||
return \MailSo\Base\Crypt::XxteaDecrypt($sEncriptedString, $sKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sString
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function EncryptStringQ($sString, $sKey)
|
||||
{
|
||||
// if (\MailSo\Base\Utils::FunctionExistsAndEnabled('openssl_pkey_get_private'))
|
||||
// {
|
||||
// return \RainLoop\Utils::EncryptStringRSA($sString,
|
||||
// $sKey.'Q'.\RainLoop\Utils::GetShortToken());
|
||||
// }
|
||||
|
||||
return \MailSo\Base\Crypt::XxteaEncrypt($sString,
|
||||
$sKey.'Q'.\RainLoop\Utils::GetShortToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEncriptedString
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function DecryptStringQ($sEncriptedString, $sKey)
|
||||
{
|
||||
// if (\MailSo\Base\Utils::FunctionExistsAndEnabled('openssl_pkey_get_private'))
|
||||
// {
|
||||
// return \RainLoop\Utils::DecryptStringRSA($sEncriptedString,
|
||||
// $sKey.'Q'.\RainLoop\Utils::GetShortToken());
|
||||
// }
|
||||
|
||||
return \MailSo\Base\Crypt::XxteaDecrypt($sEncriptedString,
|
||||
$sKey.'Q'.\RainLoop\Utils::GetShortToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aValues
|
||||
* @param string $sCustomKey = ''
|
||||
|
|
@ -63,7 +242,7 @@ class Utils
|
|||
static public function EncodeKeyValues(array $aValues, $sCustomKey = '')
|
||||
{
|
||||
return \MailSo\Base\Utils::UrlSafeBase64Encode(
|
||||
\RainLoop\Utils::EncryptString(\serialize($aValues), \md5(APP_SALT.$sCustomKey)));
|
||||
\RainLoop\Utils::EncryptString(@\serialize($aValues), \md5(APP_SALT.$sCustomKey)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -74,13 +253,41 @@ class Utils
|
|||
*/
|
||||
static public function DecodeKeyValues($sEncodedValues, $sCustomKey = '')
|
||||
{
|
||||
$aResult = \unserialize(
|
||||
$aResult = @\unserialize(
|
||||
\RainLoop\Utils::DecryptString(
|
||||
\MailSo\Base\Utils::UrlSafeBase64Decode($sEncodedValues), \md5(APP_SALT.$sCustomKey)));
|
||||
|
||||
return \is_array($aResult) ? $aResult : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aValues
|
||||
* @param string $sCustomKey = ''
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function EncodeKeyValuesQ(array $aValues, $sCustomKey = '')
|
||||
{
|
||||
return \MailSo\Base\Utils::UrlSafeBase64Encode(
|
||||
\RainLoop\Utils::EncryptStringQ(
|
||||
@\serialize($aValues), \md5(APP_SALT.$sCustomKey)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEncodedValues
|
||||
* @param string $sCustomKey = ''
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function DecodeKeyValuesQ($sEncodedValues, $sCustomKey = '')
|
||||
{
|
||||
$aResult = @\unserialize(
|
||||
\RainLoop\Utils::DecryptStringQ(
|
||||
\MailSo\Base\Utils::UrlSafeBase64Decode($sEncodedValues), \md5(APP_SALT.$sCustomKey)));
|
||||
|
||||
return \is_array($aResult) ? $aResult : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
|
@ -296,33 +503,33 @@ class Utils
|
|||
*/
|
||||
public static function GetCookie($sName, $mDefault = null)
|
||||
{
|
||||
if (null === self::$Cookies)
|
||||
if (null === \RainLoop\Utils::$Cookies)
|
||||
{
|
||||
self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array();
|
||||
\RainLoop\Utils::$Cookies = is_array($_COOKIE) ? $_COOKIE : array();
|
||||
}
|
||||
|
||||
return isset(self::$Cookies[$sName]) ? self::$Cookies[$sName] : $mDefault;
|
||||
return isset(\RainLoop\Utils::$Cookies[$sName]) ? \RainLoop\Utils::$Cookies[$sName] : $mDefault;
|
||||
}
|
||||
|
||||
public static function SetCookie($sName, $sValue = '', $iExpire = 0, $sPath = '/', $sDomain = '', $sSecure = false, $bHttpOnly = false)
|
||||
{
|
||||
if (null === self::$Cookies)
|
||||
if (null === \RainLoop\Utils::$Cookies)
|
||||
{
|
||||
self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array();
|
||||
\RainLoop\Utils::$Cookies = is_array($_COOKIE) ? $_COOKIE : array();
|
||||
}
|
||||
|
||||
self::$Cookies[$sName] = $sValue;
|
||||
\RainLoop\Utils::$Cookies[$sName] = $sValue;
|
||||
@\setcookie($sName, $sValue, $iExpire, $sPath, $sDomain, $sSecure, $bHttpOnly);
|
||||
}
|
||||
|
||||
public static function ClearCookie($sName)
|
||||
{
|
||||
if (null === self::$Cookies)
|
||||
if (null === \RainLoop\Utils::$Cookies)
|
||||
{
|
||||
self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array();
|
||||
\RainLoop\Utils::$Cookies = is_array($_COOKIE) ? $_COOKIE : array();
|
||||
}
|
||||
|
||||
unset(self::$Cookies[$sName]);
|
||||
unset(\RainLoop\Utils::$Cookies[$sName]);
|
||||
@\setcookie($sName, '', \time() - 3600 * 24 * 30, '/');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_AES
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVIII Jim Wigginton
|
||||
* @copyright 2008 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
@ -152,4 +152,56 @@ class Crypt_AES extends Crypt_Rijndael
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key length
|
||||
*
|
||||
* Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to
|
||||
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
|
||||
*
|
||||
* @see Crypt_Rijndael:setKeyLength()
|
||||
* @access public
|
||||
* @param Integer $length
|
||||
*/
|
||||
function setKeyLength($length)
|
||||
{
|
||||
switch ($length) {
|
||||
case 160:
|
||||
$length = 192;
|
||||
break;
|
||||
case 224:
|
||||
$length = 256;
|
||||
}
|
||||
parent::setKeyLength($length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
* Rijndael supports five different key lengths, AES only supports three.
|
||||
*
|
||||
* @see Crypt_Rijndael:setKey()
|
||||
* @see setKeyLength()
|
||||
* @access public
|
||||
* @param String $key
|
||||
*/
|
||||
function setKey($key)
|
||||
{
|
||||
parent::setKey($key);
|
||||
|
||||
if (!$this->explicit_key_length) {
|
||||
$length = strlen($key);
|
||||
switch (true) {
|
||||
case $length <= 16:
|
||||
$this->key_size = 16;
|
||||
break;
|
||||
case $length <= 24:
|
||||
$this->key_size = 24;
|
||||
break;
|
||||
default:
|
||||
$this->key_size = 32;
|
||||
}
|
||||
$this->_setupEngine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
* @package Crypt_Base
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
* @package Crypt_Blowfish
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_DES
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
|
||||
*
|
||||
* md2, md5, md5-96, sha1, sha1-96, sha256, sha384, and sha512
|
||||
* md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
|
||||
*
|
||||
* If {@link Crypt_Hash::setKey() setKey()} is called, {@link Crypt_Hash::hash() hash()} will return the HMAC as opposed to
|
||||
* the hash. If no valid algorithm is provided, sha1 will be used.
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_Hash
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
@ -207,6 +207,9 @@ class Crypt_Hash
|
|||
switch ($hash) {
|
||||
case 'md5-96':
|
||||
case 'sha1-96':
|
||||
case 'sha256-96':
|
||||
case 'sha512-96':
|
||||
$hash = substr($hash, 0, -3);
|
||||
$this->l = 12; // 96 / 8 = 12
|
||||
break;
|
||||
case 'md2':
|
||||
|
|
@ -243,14 +246,12 @@ class Crypt_Hash
|
|||
case CRYPT_HASH_MODE_MHASH:
|
||||
switch ($hash) {
|
||||
case 'md5':
|
||||
case 'md5-96':
|
||||
$this->hash = MHASH_MD5;
|
||||
break;
|
||||
case 'sha256':
|
||||
$this->hash = MHASH_SHA256;
|
||||
break;
|
||||
case 'sha1':
|
||||
case 'sha1-96':
|
||||
default:
|
||||
$this->hash = MHASH_SHA1;
|
||||
}
|
||||
|
|
@ -258,7 +259,6 @@ class Crypt_Hash
|
|||
case CRYPT_HASH_MODE_HASH:
|
||||
switch ($hash) {
|
||||
case 'md5':
|
||||
case 'md5-96':
|
||||
$this->hash = 'md5';
|
||||
return;
|
||||
case 'md2':
|
||||
|
|
@ -268,7 +268,6 @@ class Crypt_Hash
|
|||
$this->hash = $hash;
|
||||
return;
|
||||
case 'sha1':
|
||||
case 'sha1-96':
|
||||
default:
|
||||
$this->hash = 'sha1';
|
||||
}
|
||||
|
|
@ -281,7 +280,6 @@ class Crypt_Hash
|
|||
$this->hash = array($this, '_md2');
|
||||
break;
|
||||
case 'md5':
|
||||
case 'md5-96':
|
||||
$this->b = 64;
|
||||
$this->hash = array($this, '_md5');
|
||||
break;
|
||||
|
|
@ -295,7 +293,6 @@ class Crypt_Hash
|
|||
$this->hash = array($this, '_sha512');
|
||||
break;
|
||||
case 'sha1':
|
||||
case 'sha1-96':
|
||||
default:
|
||||
$this->b = 64;
|
||||
$this->hash = array($this, '_sha1');
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_RC4
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_RSA
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMIX Jim Wigginton
|
||||
* @copyright 2009 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
@ -493,14 +493,13 @@ class Crypt_RSA
|
|||
$this->configFile = CRYPT_RSA_OPENSSL_CONFIG;
|
||||
|
||||
if ( !defined('CRYPT_RSA_MODE') ) {
|
||||
switch (true) {
|
||||
// Math/BigInteger's openssl requirements are a little less stringent than Crypt/RSA's. in particular,
|
||||
// Math/BigInteger doesn't require an openssl.cfg file whereas Crypt/RSA does. so if Math/BigInteger
|
||||
// can't use OpenSSL it can be pretty trivially assumed, then, that Crypt/RSA can't either.
|
||||
if ( defined('MATH_BIGINTEGER_OPENSSL_DISABLE') ) {
|
||||
case defined('MATH_BIGINTEGER_OPENSSL_DISABLE'):
|
||||
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
|
||||
}
|
||||
|
||||
switch ( !defined('CRYPT_RSA_MODE') ) { // ie. only run this if the above didn't set CRYPT_RSA_MODE already
|
||||
break;
|
||||
// openssl_pkey_get_details - which is used in the only place Crypt/RSA.php uses OpenSSL - was introduced in PHP 5.2.0
|
||||
case !function_exists('openssl_pkey_get_details'):
|
||||
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
|
||||
|
|
@ -517,7 +516,14 @@ class Crypt_RSA
|
|||
$versions = array();
|
||||
if (!empty($matches[1])) {
|
||||
for ($i = 0; $i < count($matches[1]); $i++) {
|
||||
$versions[$matches[1][$i]] = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
|
||||
$fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
|
||||
|
||||
// Remove letter part in OpenSSL version
|
||||
if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
|
||||
$versions[$matches[1][$i]] = $fullVersion;
|
||||
} else {
|
||||
$versions[$matches[1][$i]] = $m[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -533,7 +539,7 @@ class Crypt_RSA
|
|||
define('MATH_BIGINTEGER_OPENSSL_DISABLE', true);
|
||||
}
|
||||
break;
|
||||
case true:
|
||||
default:
|
||||
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
|
@ -743,17 +749,18 @@ class Crypt_RSA
|
|||
*/
|
||||
function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients)
|
||||
{
|
||||
$signed = $this->privateKeyFormat != CRYPT_RSA_PRIVATE_FORMAT_XML;
|
||||
$num_primes = count($primes);
|
||||
$raw = array(
|
||||
'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
|
||||
'modulus' => $n->toBytes(true),
|
||||
'publicExponent' => $e->toBytes(true),
|
||||
'privateExponent' => $d->toBytes(true),
|
||||
'prime1' => $primes[1]->toBytes(true),
|
||||
'prime2' => $primes[2]->toBytes(true),
|
||||
'exponent1' => $exponents[1]->toBytes(true),
|
||||
'exponent2' => $exponents[2]->toBytes(true),
|
||||
'coefficient' => $coefficients[2]->toBytes(true)
|
||||
'modulus' => $n->toBytes($signed),
|
||||
'publicExponent' => $e->toBytes($signed),
|
||||
'privateExponent' => $d->toBytes($signed),
|
||||
'prime1' => $primes[1]->toBytes($signed),
|
||||
'prime2' => $primes[2]->toBytes($signed),
|
||||
'exponent1' => $exponents[1]->toBytes($signed),
|
||||
'exponent2' => $exponents[2]->toBytes($signed),
|
||||
'coefficient' => $coefficients[2]->toBytes($signed)
|
||||
);
|
||||
|
||||
// if the format in question does not support multi-prime rsa and multi-prime rsa was used,
|
||||
|
|
@ -942,8 +949,10 @@ class Crypt_RSA
|
|||
*/
|
||||
function _convertPublicKey($n, $e)
|
||||
{
|
||||
$modulus = $n->toBytes(true);
|
||||
$publicExponent = $e->toBytes(true);
|
||||
$signed = $this->publicKeyFormat != CRYPT_RSA_PUBLIC_FORMAT_XML;
|
||||
|
||||
$modulus = $n->toBytes($signed);
|
||||
$publicExponent = $e->toBytes($signed);
|
||||
|
||||
switch ($this->publicKeyFormat) {
|
||||
case CRYPT_RSA_PUBLIC_FORMAT_RAW:
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_Random
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_Rijndael
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVIII Jim Wigginton
|
||||
* @copyright 2008 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
@ -702,9 +702,15 @@ class Crypt_Rijndael extends Crypt_Base
|
|||
case $length <= 16:
|
||||
$this->key_size = 16;
|
||||
break;
|
||||
case $length <= 20:
|
||||
$this->key_size = 20;
|
||||
break;
|
||||
case $length <= 24:
|
||||
$this->key_size = 24;
|
||||
break;
|
||||
case $length <= 28:
|
||||
$this->key_size = 28;
|
||||
break;
|
||||
default:
|
||||
$this->key_size = 32;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_TripleDES
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
* @package Crypt_Twofish
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
* @category File
|
||||
* @package File_ANSI
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMXII Jim Wigginton
|
||||
* @copyright 2012 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
* @category File
|
||||
* @package File_ASN1
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMXII Jim Wigginton
|
||||
* @copyright 2012 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
@ -272,7 +272,8 @@ class File_ASN1
|
|||
}
|
||||
|
||||
$this->encoded = $encoded;
|
||||
return $this->_decode_ber($encoded);
|
||||
// encapsulate in an array for BC with the old decodeBER
|
||||
return array($this->_decode_ber($encoded));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -287,11 +288,8 @@ class File_ASN1
|
|||
* @return Array
|
||||
* @access private
|
||||
*/
|
||||
function _decode_ber(&$encoded, $start = 0)
|
||||
function _decode_ber($encoded, $start = 0)
|
||||
{
|
||||
$decoded = array();
|
||||
|
||||
while ( strlen($encoded) ) {
|
||||
$current = array('start' => $start);
|
||||
|
||||
$type = ord($this->_string_shift($encoded));
|
||||
|
|
@ -317,16 +315,13 @@ class File_ASN1
|
|||
if ( $length == 0x80 ) { // indefinite length
|
||||
// "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all
|
||||
// immediately available." -- paragraph 8.1.3.2.c
|
||||
//if ( !$constructed ) {
|
||||
// return false;
|
||||
//}
|
||||
$length = strlen($encoded);
|
||||
} elseif ( $length & 0x80 ) { // definite length, long form
|
||||
// technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only
|
||||
// support it up to four.
|
||||
$length&= 0x7F;
|
||||
$temp = $this->_string_shift($encoded, $length);
|
||||
// tags of indefinite length don't really have a header length; this length includes the tag
|
||||
// tags of indefinte length don't really have a header length; this length includes the tag
|
||||
$current+= array('headerlength' => $length + 2);
|
||||
$start+= $length;
|
||||
extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)));
|
||||
|
|
@ -334,12 +329,10 @@ class File_ASN1
|
|||
$current+= array('headerlength' => 2);
|
||||
}
|
||||
|
||||
// End-of-content, see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2
|
||||
if (!$type && !$length) {
|
||||
return $decoded;
|
||||
}
|
||||
$content = $this->_string_shift($encoded, $length);
|
||||
|
||||
// at this point $length can be overwritten. it's only accurate for definite length things as is
|
||||
|
||||
/* Class is UNIVERSAL, APPLICATION, PRIVATE, or CONTEXT-SPECIFIC. The UNIVERSAL class is restricted to the ASN.1
|
||||
built-in types. It defines an application-independent data type that must be distinguishable from all other
|
||||
data types. The other three classes are user defined. The APPLICATION class distinguishes data types that
|
||||
|
|
@ -354,14 +347,36 @@ class File_ASN1
|
|||
case FILE_ASN1_CLASS_APPLICATION:
|
||||
case FILE_ASN1_CLASS_PRIVATE:
|
||||
case FILE_ASN1_CLASS_CONTEXT_SPECIFIC:
|
||||
$decoded[] = array(
|
||||
if (!$constructed) {
|
||||
return array(
|
||||
'type' => $class,
|
||||
'constant' => $tag,
|
||||
'content' => $constructed ? $this->_decode_ber($content, $start) : $content,
|
||||
'content' => $content,
|
||||
'length' => $length + $start - $current['start']
|
||||
) + $current;
|
||||
);
|
||||
}
|
||||
|
||||
$newcontent = array();
|
||||
if (strlen($content)) {
|
||||
$newcontent = $this->_decode_ber($content, $start);
|
||||
$length = $newcontent['length'];
|
||||
if (substr($content, $length, 2) == "\0\0") {
|
||||
$length+= 2;
|
||||
}
|
||||
$start+= $length;
|
||||
continue 2;
|
||||
$newcontent = array($newcontent);
|
||||
}
|
||||
|
||||
return array(
|
||||
'type' => $class,
|
||||
'constant' => $tag,
|
||||
// the array encapsulation is for BC with the old format
|
||||
'content' => $newcontent,
|
||||
// the only time when $content['headerlength'] isn't defined is when the length is indefinite.
|
||||
// the absence of $content['headerlength'] is how we know if something is indefinite or not.
|
||||
// technically, it could be defined to be 2 and then another indicator could be used but whatever.
|
||||
'length' => $start - $current['start']
|
||||
) + $current;
|
||||
}
|
||||
|
||||
$current+= array('type' => $tag);
|
||||
|
|
@ -409,16 +424,21 @@ class File_ASN1
|
|||
if (!$constructed) {
|
||||
$current['content'] = $content;
|
||||
} else {
|
||||
$temp = $this->_decode_ber($content, $start);
|
||||
$length-= strlen($content);
|
||||
for ($i = 0, $size = count($temp); $i < $size; $i++) {
|
||||
$current['content'] = '';
|
||||
$length = 0;
|
||||
while (substr($content, 0, 2) != "\0\0") {
|
||||
$temp = $this->_decode_ber($content, $length + $start);
|
||||
$this->_string_shift($content, $temp['length']);
|
||||
// all subtags should be octet strings
|
||||
//if ($temp[$i]['type'] != FILE_ASN1_TYPE_OCTET_STRING) {
|
||||
//if ($temp['type'] != FILE_ASN1_TYPE_OCTET_STRING) {
|
||||
// return false;
|
||||
//}
|
||||
$current['content'].= $temp[$i]['content'];
|
||||
$current['content'].= $temp['content'];
|
||||
$length+= $temp['length'];
|
||||
}
|
||||
if (substr($content, 0, 2) == "\0\0") {
|
||||
$length+= 2; // +2 for the EOC
|
||||
}
|
||||
// $length =
|
||||
}
|
||||
break;
|
||||
case FILE_ASN1_TYPE_NULL:
|
||||
|
|
@ -429,7 +449,20 @@ class File_ASN1
|
|||
break;
|
||||
case FILE_ASN1_TYPE_SEQUENCE:
|
||||
case FILE_ASN1_TYPE_SET:
|
||||
$current['content'] = $this->_decode_ber($content, $start);
|
||||
$offset = 0;
|
||||
$current['content'] = array();
|
||||
while (strlen($content)) {
|
||||
// if indefinite length construction was used and we have an end-of-content string next
|
||||
// see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2
|
||||
if (!isset($current['headerlength']) && substr($content, 0, 2) == "\0\0") {
|
||||
$length = $offset + 2; // +2 for the EOC
|
||||
break 2;
|
||||
}
|
||||
$temp = $this->_decode_ber($content, $start + $offset);
|
||||
$this->_string_shift($content, $temp['length']);
|
||||
$current['content'][] = $temp;
|
||||
$offset+= $temp['length'];
|
||||
}
|
||||
break;
|
||||
case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
|
||||
$temp = ord($this->_string_shift($content));
|
||||
|
|
@ -484,18 +517,16 @@ class File_ASN1
|
|||
case FILE_ASN1_TYPE_GENERALIZED_TIME:
|
||||
$current['content'] = $this->_decodeTime($content, $tag);
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
$start+= $length;
|
||||
$decoded[] = $current + array('length' => $start - $current['start']);
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
// ie. length is the length of the full TLV encoding - it's not just the length of the value
|
||||
return $current + array('length' => $start - $current['start']);
|
||||
}
|
||||
|
||||
/**
|
||||
* ASN.1 Decode
|
||||
* ASN.1 Map
|
||||
*
|
||||
* Provides an ASN.1 semantic mapping ($mapping) from a parsed BER-encoding to a human readable format.
|
||||
*
|
||||
|
|
@ -805,16 +836,6 @@ class File_ASN1
|
|||
return $this->_encode_der($source, $mapping, null, $special);
|
||||
}
|
||||
|
||||
/**
|
||||
* ASN.1 Encode (Helper function)
|
||||
*
|
||||
* @param String $source
|
||||
* @param Array $mapping
|
||||
* @param Integer $idx
|
||||
* @param Array $special
|
||||
* @return String
|
||||
* @access private
|
||||
*/
|
||||
/**
|
||||
* ASN.1 Encode (Helper function)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
* @category File
|
||||
* @package File_X509
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMXII Jim Wigginton
|
||||
* @copyright 2012 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
* @category Math
|
||||
* @package Math_BigInteger
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVI Jim Wigginton
|
||||
* @copyright 2006 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://pear.php.net/package/Math_BigInteger
|
||||
*/
|
||||
|
|
@ -278,7 +278,14 @@ class Math_BigInteger
|
|||
$versions = array();
|
||||
if (!empty($matches[1])) {
|
||||
for ($i = 0; $i < count($matches[1]); $i++) {
|
||||
$versions[$matches[1][$i]] = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
|
||||
$fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
|
||||
|
||||
// Remove letter part in OpenSSL version
|
||||
if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
|
||||
$versions[$matches[1][$i]] = $fullVersion;
|
||||
} else {
|
||||
$versions[$matches[1][$i]] = $m[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -329,7 +336,10 @@ class Math_BigInteger
|
|||
|
||||
switch ( MATH_BIGINTEGER_MODE ) {
|
||||
case MATH_BIGINTEGER_MODE_GMP:
|
||||
if (is_resource($x) && get_resource_type($x) == 'GMP integer') {
|
||||
switch (true) {
|
||||
case is_resource($x) && get_resource_type($x) == 'GMP integer':
|
||||
// PHP 5.6 switched GMP from using resources to objects
|
||||
case is_object($x) && get_class($x) == 'GMP':
|
||||
$this->value = $x;
|
||||
return;
|
||||
}
|
||||
|
|
@ -912,7 +922,7 @@ class Math_BigInteger
|
|||
$value = $x_value;
|
||||
}
|
||||
|
||||
$value[] = 0; // just in case the carry adds an extra digit
|
||||
$value[count($value)] = 0; // just in case the carry adds an extra digit
|
||||
|
||||
$carry = 0;
|
||||
for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) {
|
||||
|
|
@ -2134,7 +2144,7 @@ class Math_BigInteger
|
|||
|
||||
if ($this->_compare($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]) < 0) {
|
||||
$corrector_value = $this->_array_repeat(0, $n_length + 1);
|
||||
$corrector_value[] = 1;
|
||||
$corrector_value[count($corrector_value)] = 1;
|
||||
$result = $this->_add($result, false, $corrector_value, false);
|
||||
$result = $result[MATH_BIGINTEGER_VALUE];
|
||||
}
|
||||
|
|
@ -2904,7 +2914,7 @@ class Math_BigInteger
|
|||
$leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3);
|
||||
$this->_base256_lshift($leading_ones, $current_bits);
|
||||
|
||||
$temp = str_pad($temp, ceil($this->bits / 8), chr(0), STR_PAD_LEFT);
|
||||
$temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT);
|
||||
|
||||
return $this->_normalize(new Math_BigInteger($leading_ones | $temp, 256));
|
||||
}
|
||||
|
|
@ -3479,7 +3489,7 @@ class Math_BigInteger
|
|||
}
|
||||
|
||||
if ( $carry ) {
|
||||
$this->value[] = $carry;
|
||||
$this->value[count($this->value)] = $carry;
|
||||
}
|
||||
|
||||
while ($num_digits--) {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
* @category Net
|
||||
* @package Net_SCP
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMX Jim Wigginton
|
||||
* @copyright 2010 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
@ -170,7 +170,7 @@ class Net_SCP
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!$this->ssh->exec('scp -t "' . $remote_file . '"', false)) { // -t = to
|
||||
if (!$this->ssh->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +195,6 @@ class Net_SCP
|
|||
|
||||
$fp = @fopen($data, 'rb');
|
||||
if (!$fp) {
|
||||
fclose($fp);
|
||||
return false;
|
||||
}
|
||||
$size = filesize($data);
|
||||
|
|
@ -245,7 +244,7 @@ class Net_SCP
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!$this->ssh->exec('scp -f "' . $remote_file . '"', false)) { // -f = from
|
||||
if (!$this->ssh->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
* @category Net
|
||||
* @package Net_SFTP
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMIX Jim Wigginton
|
||||
* @copyright 2009 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
@ -1061,12 +1061,14 @@ class Net_SFTP extends Net_SSH2
|
|||
$dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
|
||||
|
||||
$temp = &$this->stat_cache;
|
||||
foreach ($dirs as $dir) {
|
||||
$max = count($dirs) - 1;
|
||||
foreach ($dirs as $i=>$dir) {
|
||||
if (!isset($temp[$dir])) {
|
||||
$temp[$dir] = array();
|
||||
}
|
||||
if ($dir == end($dirs)) {
|
||||
if ($i === $max) {
|
||||
$temp[$dir] = $value;
|
||||
break;
|
||||
}
|
||||
$temp = &$temp[$dir];
|
||||
}
|
||||
|
|
@ -1084,8 +1086,9 @@ class Net_SFTP extends Net_SSH2
|
|||
$dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
|
||||
|
||||
$temp = &$this->stat_cache;
|
||||
foreach ($dirs as $dir) {
|
||||
if ($dir == end($dirs)) {
|
||||
$max = count($dirs) - 1;
|
||||
foreach ($dirs as $i=>$dir) {
|
||||
if ($i === $max) {
|
||||
unset($temp[$dir]);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1501,7 +1504,7 @@ class Net_SFTP extends Net_SSH2
|
|||
return false;
|
||||
}
|
||||
$i = 0;
|
||||
$entries = $this->_list($path, true, false);
|
||||
$entries = $this->_list($path, true);
|
||||
|
||||
if ($entries === false) {
|
||||
return $this->_setstat($path, $attr, false);
|
||||
|
|
@ -1513,11 +1516,8 @@ class Net_SFTP extends Net_SSH2
|
|||
return false;
|
||||
}
|
||||
|
||||
unset($entries['.'], $entries['..']);
|
||||
foreach ($entries as $filename=>$props) {
|
||||
if ($filename == '.' || $filename == '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($props['type'])) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1757,6 +1757,8 @@ class Net_SFTP extends Net_SSH2
|
|||
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
|
||||
* large $remote_file will be, as well.
|
||||
*
|
||||
* If $data is a resource then it'll be used as a resource instead.
|
||||
*
|
||||
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
|
||||
* care of that, yourself.
|
||||
*
|
||||
|
|
@ -1778,7 +1780,7 @@ class Net_SFTP extends Net_SSH2
|
|||
* Setting $local_start to > 0 or $mode | NET_SFTP_RESUME_START doesn't do anything unless $mode | NET_SFTP_LOCAL_FILE.
|
||||
*
|
||||
* @param String $remote_file
|
||||
* @param String $data
|
||||
* @param String|resource $data
|
||||
* @param optional Integer $mode
|
||||
* @param optional Integer $start
|
||||
* @param optional Integer $local_start
|
||||
|
|
@ -1834,7 +1836,12 @@ class Net_SFTP extends Net_SSH2
|
|||
}
|
||||
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
|
||||
if ($mode & NET_SFTP_LOCAL_FILE) {
|
||||
switch (true) {
|
||||
case is_resource($data):
|
||||
$mode = $mode & ~NET_SFTP_LOCAL_FILE;
|
||||
$fp = $data;
|
||||
break;
|
||||
case $mode & NET_SFTP_LOCAL_FILE:
|
||||
if (!is_file($data)) {
|
||||
user_error("$data is not a valid file");
|
||||
return false;
|
||||
|
|
@ -1843,7 +1850,11 @@ class Net_SFTP extends Net_SSH2
|
|||
if (!$fp) {
|
||||
return false;
|
||||
}
|
||||
$size = filesize($data);
|
||||
}
|
||||
|
||||
if (isset($fp)) {
|
||||
$stat = fstat($fp);
|
||||
$size = $stat['size'];
|
||||
|
||||
if ($local_start >= 0) {
|
||||
fseek($fp, $local_start);
|
||||
|
|
@ -1864,11 +1875,13 @@ class Net_SFTP extends Net_SSH2
|
|||
$sftp_packet_size-= strlen($handle) + 25;
|
||||
$i = 0;
|
||||
while ($sent < $size) {
|
||||
$temp = $mode & NET_SFTP_LOCAL_FILE ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size);
|
||||
$temp = isset($fp) ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size);
|
||||
$subtemp = $offset + $sent;
|
||||
$packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp);
|
||||
if (!$this->_send_sftp_packet(NET_SFTP_WRITE, $packet)) {
|
||||
if ($mode & NET_SFTP_LOCAL_FILE) {
|
||||
fclose($fp);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
$sent+= strlen($temp);
|
||||
|
|
@ -2003,6 +2016,12 @@ class Net_SFTP extends Net_SSH2
|
|||
return false;
|
||||
}
|
||||
|
||||
if (is_resource($local_file)) {
|
||||
$fp = $local_file;
|
||||
$stat = fstat($fp);
|
||||
$res_offset = $stat['size'];
|
||||
} else {
|
||||
$res_offset = 0;
|
||||
if ($local_file !== false) {
|
||||
$fp = fopen($local_file, 'wb');
|
||||
if (!$fp) {
|
||||
|
|
@ -2011,13 +2030,16 @@ class Net_SFTP extends Net_SSH2
|
|||
} else {
|
||||
$content = '';
|
||||
}
|
||||
}
|
||||
|
||||
$fclose_check = $local_file !== false && !is_resource($local_file);
|
||||
|
||||
$start = $offset;
|
||||
$size = $this->max_sftp_packet < $length || $length < 0 ? $this->max_sftp_packet : $length;
|
||||
while (true) {
|
||||
$packet = pack('Na*N3', strlen($handle), $handle, $offset / 4294967296, $offset, $size);
|
||||
if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) {
|
||||
if ($local_file !== false) {
|
||||
if ($fclose_check) {
|
||||
fclose($fp);
|
||||
}
|
||||
return false;
|
||||
|
|
@ -2040,7 +2062,7 @@ class Net_SFTP extends Net_SSH2
|
|||
break 2;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_DATA or SSH_FXP_STATUS');
|
||||
if ($local_file !== false) {
|
||||
if ($fclose_check) {
|
||||
fclose($fp);
|
||||
}
|
||||
return false;
|
||||
|
|
@ -2055,11 +2077,11 @@ class Net_SFTP extends Net_SSH2
|
|||
if ($local_file === false) {
|
||||
$content = substr($content, 0, $length);
|
||||
} else {
|
||||
ftruncate($fp, $length);
|
||||
ftruncate($fp, $length + $res_offset);
|
||||
}
|
||||
}
|
||||
|
||||
if ($local_file !== false) {
|
||||
if ($fclose_check) {
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
|
|
@ -2135,7 +2157,7 @@ class Net_SFTP extends Net_SSH2
|
|||
return false;
|
||||
}
|
||||
$i = 0;
|
||||
$entries = $this->_list($path, true, false);
|
||||
$entries = $this->_list($path, true);
|
||||
|
||||
// normally $entries would have at least . and .. but it might not if the directories
|
||||
// permissions didn't allow reading
|
||||
|
|
@ -2143,11 +2165,8 @@ class Net_SFTP extends Net_SSH2
|
|||
return false;
|
||||
}
|
||||
|
||||
unset($entries['.'], $entries['..']);
|
||||
foreach ($entries as $filename=>$props) {
|
||||
if ($filename == '.' || $filename == '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($props['type'])) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2205,7 +2224,7 @@ class Net_SFTP extends Net_SSH2
|
|||
$result = $this->_query_stat_cache($path);
|
||||
|
||||
if (isset($result)) {
|
||||
// return true if $result is an array or if it's int(1)
|
||||
// return true if $result is an array or if it's an stdClass object
|
||||
return $result !== false;
|
||||
}
|
||||
}
|
||||
|
|
@ -2348,7 +2367,7 @@ class Net_SFTP extends Net_SSH2
|
|||
}
|
||||
|
||||
switch ($type) {
|
||||
case NET_SFTP_BLOCK_DEVICE: return 'block';
|
||||
case NET_SFTP_TYPE_BLOCK_DEVICE: return 'block';
|
||||
case NET_SFTP_TYPE_CHAR_DEVICE: return 'char';
|
||||
case NET_SFTP_TYPE_DIRECTORY: return 'dir';
|
||||
case NET_SFTP_TYPE_FIFO: return 'fifo';
|
||||
|
|
@ -2454,14 +2473,13 @@ class Net_SFTP extends Net_SSH2
|
|||
foreach ($this->attributes as $key => $value) {
|
||||
switch ($flags & $key) {
|
||||
case NET_SFTP_ATTR_SIZE: // 0x00000001
|
||||
// size is represented by a 64-bit integer, so we perhaps ought to be doing the following:
|
||||
// $attr['size'] = new Math_BigInteger($this->_string_shift($response, 8), 256);
|
||||
// of course, you shouldn't be using Net_SFTP to transfer files that are in excess of 4GB
|
||||
// (0xFFFFFFFF bytes), anyway. as such, we'll just represent all file sizes that are bigger than
|
||||
// 4GB as being 4GB.
|
||||
extract(unpack('Nupper/Nsize', $this->_string_shift($response, 8)));
|
||||
$attr['size'] = $upper ? 4294967296 * $upper : 0;
|
||||
$attr['size']+= $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size;
|
||||
// The size attribute is defined as an unsigned 64-bit integer.
|
||||
// The following will use floats on 32-bit platforms, if necessary.
|
||||
// As can be seen in the BigInteger class, floats are generally
|
||||
// IEEE 754 binary64 "double precision" on such platforms and
|
||||
// as such can represent integers of at least 2^50 without loss
|
||||
// of precision. Interpreted in filesize, 2^50 bytes = 1024 TiB.
|
||||
$attr['size'] = hexdec(bin2hex($this->_string_shift($response, 8)));
|
||||
break;
|
||||
case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only)
|
||||
$attr+= unpack('Nuid/Ngid', $this->_string_shift($response, 8));
|
||||
|
|
@ -2521,7 +2539,7 @@ class Net_SFTP extends Net_SSH2
|
|||
case 0020000: // character special
|
||||
return NET_SFTP_TYPE_CHAR_DEVICE;
|
||||
case 0060000: // block special
|
||||
return NET_SFTP_BLOCK_DEVICE;
|
||||
return NET_SFTP_TYPE_BLOCK_DEVICE;
|
||||
case 0140000: // socket
|
||||
return NET_SFTP_TYPE_SOCKET;
|
||||
case 0160000: // whiteout
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
* @category Net
|
||||
* @package Net_SFTP_Stream
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMXIII Jim Wigginton
|
||||
* @copyright 2013 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
@ -48,7 +48,6 @@ class Net_SFTP_Stream
|
|||
* Rather than re-create the connection we re-use instances if possible
|
||||
*
|
||||
* @var Array
|
||||
* @access static
|
||||
*/
|
||||
static $instances;
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
* @category Net
|
||||
* @package Net_SSH1
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
@ -1128,6 +1128,7 @@ class Net_SSH1
|
|||
|
||||
$padding_length = 8 - ($temp['length'] & 7);
|
||||
$length = $temp['length'] + $padding_length;
|
||||
$raw = '';
|
||||
|
||||
while ($length > 0) {
|
||||
$temp = fread($this->fsock, $length);
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
* @category Net
|
||||
* @package Net_SSH2
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
|
@ -77,7 +77,7 @@ define('NET_SSH2_MASK_CONNECTED', 0x00000002);
|
|||
define('NET_SSH2_MASK_LOGIN_REQ', 0x00000004);
|
||||
define('NET_SSH2_MASK_LOGIN', 0x00000008);
|
||||
define('NET_SSH2_MASK_SHELL', 0x00000010);
|
||||
define('NET_SSH2_MASK_WINDOW_ADJUST', 0X00000020);
|
||||
define('NET_SSH2_MASK_WINDOW_ADJUST', 0x00000020);
|
||||
/**#@-*/
|
||||
|
||||
/**#@+
|
||||
|
|
@ -191,100 +191,100 @@ class Net_SSH2
|
|||
* Server Identifier
|
||||
*
|
||||
* @see Net_SSH2::getServerIdentification()
|
||||
* @var String
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $server_identifier = '';
|
||||
var $server_identifier = false;
|
||||
|
||||
/**
|
||||
* Key Exchange Algorithms
|
||||
*
|
||||
* @see Net_SSH2::getKexAlgorithims()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $kex_algorithms;
|
||||
var $kex_algorithms = false;
|
||||
|
||||
/**
|
||||
* Server Host Key Algorithms
|
||||
*
|
||||
* @see Net_SSH2::getServerHostKeyAlgorithms()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $server_host_key_algorithms;
|
||||
var $server_host_key_algorithms = false;
|
||||
|
||||
/**
|
||||
* Encryption Algorithms: Client to Server
|
||||
*
|
||||
* @see Net_SSH2::getEncryptionAlgorithmsClient2Server()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $encryption_algorithms_client_to_server;
|
||||
var $encryption_algorithms_client_to_server = false;
|
||||
|
||||
/**
|
||||
* Encryption Algorithms: Server to Client
|
||||
*
|
||||
* @see Net_SSH2::getEncryptionAlgorithmsServer2Client()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $encryption_algorithms_server_to_client;
|
||||
var $encryption_algorithms_server_to_client = false;
|
||||
|
||||
/**
|
||||
* MAC Algorithms: Client to Server
|
||||
*
|
||||
* @see Net_SSH2::getMACAlgorithmsClient2Server()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $mac_algorithms_client_to_server;
|
||||
var $mac_algorithms_client_to_server = false;
|
||||
|
||||
/**
|
||||
* MAC Algorithms: Server to Client
|
||||
*
|
||||
* @see Net_SSH2::getMACAlgorithmsServer2Client()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $mac_algorithms_server_to_client;
|
||||
var $mac_algorithms_server_to_client = false;
|
||||
|
||||
/**
|
||||
* Compression Algorithms: Client to Server
|
||||
*
|
||||
* @see Net_SSH2::getCompressionAlgorithmsClient2Server()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $compression_algorithms_client_to_server;
|
||||
var $compression_algorithms_client_to_server = false;
|
||||
|
||||
/**
|
||||
* Compression Algorithms: Server to Client
|
||||
*
|
||||
* @see Net_SSH2::getCompressionAlgorithmsServer2Client()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $compression_algorithms_server_to_client;
|
||||
var $compression_algorithms_server_to_client = false;
|
||||
|
||||
/**
|
||||
* Languages: Server to Client
|
||||
*
|
||||
* @see Net_SSH2::getLanguagesServer2Client()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $languages_server_to_client;
|
||||
var $languages_server_to_client = false;
|
||||
|
||||
/**
|
||||
* Languages: Client to Server
|
||||
*
|
||||
* @see Net_SSH2::getLanguagesClient2Server()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $languages_client_to_server;
|
||||
var $languages_client_to_server = false;
|
||||
|
||||
/**
|
||||
* Block Size for Server to Client Encryption
|
||||
|
|
@ -949,6 +949,12 @@ class Net_SSH2
|
|||
*/
|
||||
function _connect()
|
||||
{
|
||||
if ($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->bitmap |= NET_SSH2_MASK_CONSTRUCTOR;
|
||||
|
||||
$timeout = $this->connectionTimeout;
|
||||
$host = $this->host . ':' . $this->port;
|
||||
|
||||
|
|
@ -965,7 +971,7 @@ class Net_SSH2
|
|||
$timeout-= $elapsed;
|
||||
|
||||
if ($timeout <= 0) {
|
||||
user_error(rtrim("Cannot connect to $host. Timeout error"));
|
||||
user_error("Cannot connect to $host. Timeout error");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -978,7 +984,7 @@ class Net_SSH2
|
|||
// on windows this returns a "Warning: Invalid CRT parameters detected" error
|
||||
// the !count() is done as a workaround for <https://bugs.php.net/42682>
|
||||
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
|
||||
user_error(rtrim("Cannot connect to $host. Banner timeout"));
|
||||
user_error("Cannot connect to $host. Banner timeout");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1038,7 +1044,7 @@ class Net_SSH2
|
|||
return false;
|
||||
}
|
||||
|
||||
$this->bitmap = NET_SSH2_MASK_CONNECTED;
|
||||
$this->bitmap|= NET_SSH2_MASK_CONNECTED;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1098,7 +1104,7 @@ class Net_SSH2
|
|||
'arcfour256',
|
||||
'arcfour128',
|
||||
|
||||
'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
|
||||
//'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
|
||||
|
||||
// CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
|
||||
'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
|
||||
|
|
@ -1126,7 +1132,7 @@ class Net_SSH2
|
|||
'3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
|
||||
|
||||
'3des-cbc', // REQUIRED three-key 3DES in CBC mode
|
||||
'none' // OPTIONAL no encryption; NOT RECOMMENDED
|
||||
//'none' // OPTIONAL no encryption; NOT RECOMMENDED
|
||||
);
|
||||
|
||||
if (phpseclib_resolve_include_path('Crypt/RC4.php') === false) {
|
||||
|
|
@ -1163,11 +1169,14 @@ class Net_SSH2
|
|||
}
|
||||
|
||||
$mac_algorithms = array(
|
||||
// from <http://www.ietf.org/rfc/rfc6668.txt>:
|
||||
'hmac-sha2-256',// RECOMMENDED HMAC-SHA256 (digest length = key length = 32)
|
||||
|
||||
'hmac-sha1-96', // RECOMMENDED first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20)
|
||||
'hmac-sha1', // REQUIRED HMAC-SHA1 (digest length = key length = 20)
|
||||
'hmac-md5-96', // OPTIONAL first 96 bits of HMAC-MD5 (digest length = 12, key length = 16)
|
||||
'hmac-md5', // OPTIONAL HMAC-MD5 (digest length = key length = 16)
|
||||
'none' // OPTIONAL no MAC; NOT RECOMMENDED
|
||||
//'none' // OPTIONAL no MAC; NOT RECOMMENDED
|
||||
);
|
||||
|
||||
static $compression_algorithms = array(
|
||||
|
|
@ -1692,6 +1701,10 @@ class Net_SSH2
|
|||
|
||||
$createKeyLength = 0; // ie. $mac_algorithms[$i] == 'none'
|
||||
switch ($mac_algorithms[$i]) {
|
||||
case 'hmac-sha2-256':
|
||||
$this->hmac_create = new Crypt_Hash('sha256');
|
||||
$createKeyLength = 32;
|
||||
break;
|
||||
case 'hmac-sha1':
|
||||
$this->hmac_create = new Crypt_Hash('sha1');
|
||||
$createKeyLength = 20;
|
||||
|
|
@ -1718,6 +1731,11 @@ class Net_SSH2
|
|||
$checkKeyLength = 0;
|
||||
$this->hmac_size = 0;
|
||||
switch ($mac_algorithms[$i]) {
|
||||
case 'hmac-sha2-256':
|
||||
$this->hmac_check = new Crypt_Hash('sha256');
|
||||
$checkKeyLength = 32;
|
||||
$this->hmac_size = 32;
|
||||
break;
|
||||
case 'hmac-sha1':
|
||||
$this->hmac_check = new Crypt_Hash('sha1');
|
||||
$checkKeyLength = 20;
|
||||
|
|
@ -1799,7 +1817,6 @@ class Net_SSH2
|
|||
function _login($username)
|
||||
{
|
||||
if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) {
|
||||
$this->bitmap |= NET_SSH2_MASK_CONSTRUCTOR;
|
||||
if (!$this->_connect()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2062,7 +2079,6 @@ class Net_SSH2
|
|||
|
||||
if (!count($responses) && $num_prompts) {
|
||||
$this->last_interactive_response = $orig;
|
||||
$this->bitmap |= NET_SSH_MASK_LOGIN_INTERACTIVE;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2245,7 +2261,7 @@ class Net_SSH2
|
|||
/**
|
||||
* Execute Command
|
||||
*
|
||||
* If $block is set to false then Net_SSH2::_get_channel_packet(NET_SSH2_CHANNEL_EXEC) will need to be called manually.
|
||||
* If $callback is set to false then Net_SSH2::_get_channel_packet(NET_SSH2_CHANNEL_EXEC) will need to be called manually.
|
||||
* In all likelihood, this is not a feature you want to be taking advantage of.
|
||||
*
|
||||
* @param String $command
|
||||
|
|
@ -2654,11 +2670,12 @@ class Net_SSH2
|
|||
/**
|
||||
* Is the connection still active?
|
||||
*
|
||||
* @return boolean
|
||||
* @access public
|
||||
*/
|
||||
function isConnected()
|
||||
{
|
||||
return $this->bitmap & NET_SSH2_MASK_LOGIN;
|
||||
return (bool) ($this->bitmap & NET_SSH2_MASK_CONNECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2968,7 +2985,7 @@ class Net_SSH2
|
|||
|
||||
extract(unpack('Ctype/Nchannel', $this->_string_shift($response, 5)));
|
||||
|
||||
$this->window_size_server_to_client[$channel]-= strlen($response) + 4;
|
||||
$this->window_size_server_to_client[$channel]-= strlen($response);
|
||||
|
||||
// resize the window, if appropriate
|
||||
if ($this->window_size_server_to_client[$channel] < 0) {
|
||||
|
|
@ -3258,26 +3275,22 @@ class Net_SSH2
|
|||
*/
|
||||
function _send_channel_packet($client_channel, $data)
|
||||
{
|
||||
while (strlen($data)) {
|
||||
if (!$this->window_size_client_to_server[$client_channel]) {
|
||||
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
|
||||
// using an invalid channel will let the buffers be built up for the valid channels
|
||||
$this->_get_channel_packet(-1);
|
||||
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
|
||||
}
|
||||
|
||||
/* The maximum amount of data allowed is determined by the maximum
|
||||
packet size for the channel, and the current window size, whichever
|
||||
is smaller.
|
||||
|
||||
-- http://tools.ietf.org/html/rfc4254#section-5.2 */
|
||||
$max_size = min(
|
||||
$this->packet_size_client_to_server[$client_channel],
|
||||
$this->window_size_client_to_server[$client_channel]
|
||||
) - 4;
|
||||
while (strlen($data) > $max_size) {
|
||||
if (!$this->window_size_client_to_server[$client_channel]) {
|
||||
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
|
||||
// using an invalid channel will let the buffers be built up for the valid channels
|
||||
$output = $this->_get_channel_packet(-1);
|
||||
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
|
||||
$max_size = min(
|
||||
$this->packet_size_client_to_server[$client_channel],
|
||||
$this->window_size_client_to_server[$client_channel]
|
||||
) - 4;
|
||||
}
|
||||
);
|
||||
|
||||
$temp = $this->_string_shift($data, $max_size);
|
||||
$packet = pack('CN2a*',
|
||||
|
|
@ -3286,27 +3299,13 @@ class Net_SSH2
|
|||
strlen($temp),
|
||||
$temp
|
||||
);
|
||||
|
||||
$this->window_size_client_to_server[$client_channel]-= strlen($temp) + 4;
|
||||
|
||||
$this->window_size_client_to_server[$client_channel]-= strlen($temp);
|
||||
if (!$this->_send_binary_packet($packet)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen($data) >= $this->window_size_client_to_server[$client_channel] - 4) {
|
||||
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
|
||||
$this->_get_channel_packet(-1);
|
||||
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
|
||||
}
|
||||
|
||||
$this->window_size_client_to_server[$client_channel]-= strlen($data) + 4;
|
||||
|
||||
return $this->_send_binary_packet(pack('CN2a*',
|
||||
NET_SSH2_MSG_CHANNEL_DATA,
|
||||
$this->server_channels[$client_channel],
|
||||
strlen($data),
|
||||
$data));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3355,7 +3354,7 @@ class Net_SSH2
|
|||
*/
|
||||
function _disconnect($reason)
|
||||
{
|
||||
if ($this->bitmap) {
|
||||
if ($this->bitmap & NET_SSH2_MASK_CONNECTED) {
|
||||
$data = pack('CNNa*Na*', NET_SSH2_MSG_DISCONNECT, $reason, 0, '', 0, '');
|
||||
$this->_send_binary_packet($data);
|
||||
$this->bitmap = 0;
|
||||
|
|
@ -3509,6 +3508,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getServerIdentification()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->server_identifier;
|
||||
}
|
||||
|
||||
|
|
@ -3520,6 +3521,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getKexAlgorithms()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->kex_algorithms;
|
||||
}
|
||||
|
||||
|
|
@ -3531,6 +3534,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getServerHostKeyAlgorithms()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->server_host_key_algorithms;
|
||||
}
|
||||
|
||||
|
|
@ -3542,6 +3547,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getEncryptionAlgorithmsClient2Server()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->encryption_algorithms_client_to_server;
|
||||
}
|
||||
|
||||
|
|
@ -3553,6 +3560,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getEncryptionAlgorithmsServer2Client()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->encryption_algorithms_server_to_client;
|
||||
}
|
||||
|
||||
|
|
@ -3564,6 +3573,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getMACAlgorithmsClient2Server()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->mac_algorithms_client_to_server;
|
||||
}
|
||||
|
||||
|
|
@ -3575,6 +3586,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getMACAlgorithmsServer2Client()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->mac_algorithms_server_to_client;
|
||||
}
|
||||
|
||||
|
|
@ -3586,6 +3599,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getCompressionAlgorithmsClient2Server()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->compression_algorithms_client_to_server;
|
||||
}
|
||||
|
||||
|
|
@ -3597,6 +3612,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getCompressionAlgorithmsServer2Client()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->compression_algorithms_server_to_client;
|
||||
}
|
||||
|
||||
|
|
@ -3608,6 +3625,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getLanguagesServer2Client()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->languages_server_to_client;
|
||||
}
|
||||
|
||||
|
|
@ -3619,6 +3638,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getLanguagesClient2Server()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->languages_client_to_server;
|
||||
}
|
||||
|
||||
|
|
@ -3648,7 +3669,6 @@ class Net_SSH2
|
|||
function getServerPublicHostKey()
|
||||
{
|
||||
if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) {
|
||||
$this->bitmap |= NET_SSH2_MASK_CONSTRUCTOR;
|
||||
if (!$this->_connect()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -3731,8 +3751,9 @@ class Net_SSH2
|
|||
$e = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
|
||||
|
||||
$temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
|
||||
$n = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
|
||||
$nLength = $temp['length'];
|
||||
$rawN = $this->_string_shift($server_public_host_key, $temp['length']);
|
||||
$n = new Math_BigInteger($rawN, -256);
|
||||
$nLength = strlen(ltrim($rawN, "\0"));
|
||||
|
||||
/*
|
||||
$temp = unpack('Nlength', $this->_string_shift($signature, 4));
|
||||
|
|
@ -3769,7 +3790,7 @@ class Net_SSH2
|
|||
$s = $s->toBytes();
|
||||
|
||||
$h = pack('N4H*', 0x00302130, 0x0906052B, 0x0E03021A, 0x05000414, sha1($this->exchange_hash));
|
||||
$h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 3 - strlen($h)) . $h;
|
||||
$h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 2 - strlen($h)) . $h;
|
||||
|
||||
if ($s != $h) {
|
||||
user_error('Bad server signature');
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
* @category System
|
||||
* @package System_SSH_Agent
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMXIV Jim Wigginton
|
||||
* @copyright 2014 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
* @category System
|
||||
* @package System_SSH_Agent
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMXIV Jim Wigginton
|
||||
* @copyright 2014 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
|
||||
|
|
|
|||
|
|
@ -138,6 +138,13 @@
|
|||
value: capaAdditionalAccounts
|
||||
}
|
||||
}"></div>
|
||||
<div data-bind="component: {
|
||||
name: 'Checkbox',
|
||||
params: {
|
||||
label: 'TAB_GENERAL/LABEL_ALLOW_IDENTITIES',
|
||||
value: capaIdentities
|
||||
}
|
||||
}"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
|
|
|
|||
|
|
@ -3,6 +3,20 @@
|
|||
<div class="legend">
|
||||
<span class="i18n i18n-animation" data-i18n="SETTINGS_GENERAL/LEGEND_GENERAL"></span>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">
|
||||
<span class="i18n" data-i18n="SETTINGS_GENERAL/LABEL_IDENTITY"></span>
|
||||
</label>
|
||||
<div class="controls">
|
||||
<div style="display: inline-block; margin-top: 5px">
|
||||
<b data-bind="text: identityMainDesc"></b>
|
||||
|
||||
<span data-bind="click: editMainIdentity" style="cursor: pointer">
|
||||
<i class="icon-cog"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" data-bind="visible: allowLanguagesOnSettings">
|
||||
<label class="control-label">
|
||||
<span class="i18n" data-i18n="SETTINGS_GENERAL/LABEL_LANGUAGE"></span>
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ LABEL_ALLOW_GRAVATAR = "Gravatar erlauben"
|
|||
LEGEND_MAIN = "Haupt"
|
||||
LABEL_ATTACHMENT_SIZE_LIMIT = "Größenlimit für Anhänge"
|
||||
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Zusätzliche Konten erlauben"
|
||||
LABEL_ALLOW_IDENTITIES = "Allow multiple identities"
|
||||
LABEL_ALLOW_TEMPLATES = "Vorlagen erlauben"
|
||||
ALERT_WARNING = "Warnung!"
|
||||
HTML_ALERT_WEAK_PASSWORD = "Sie verwenden das Standard-Admin-Passwort.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ LABEL_ALLOW_GRAVATAR = "Allow Gravatar"
|
|||
LEGEND_MAIN = "Main"
|
||||
LABEL_ATTACHMENT_SIZE_LIMIT = "Attachment size limit"
|
||||
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Allow additional accounts"
|
||||
LABEL_ALLOW_IDENTITIES = "Allow multiple identities"
|
||||
LABEL_ALLOW_TEMPLATES = "Allow templates"
|
||||
ALERT_WARNING = "Warning!"
|
||||
HTML_ALERT_WEAK_PASSWORD = "You are using the default admin password.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ LABEL_ALLOW_GRAVATAR = "Permitir Gravatar"
|
|||
LEGEND_MAIN = "Principal"
|
||||
LABEL_ATTACHMENT_SIZE_LIMIT = "Tamanho limite de anexo"
|
||||
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Permitir contas adicionais"
|
||||
LABEL_ALLOW_IDENTITIES = "Allow multiple identities"
|
||||
LABEL_ALLOW_TEMPLATES = "Permitir templates"
|
||||
ALERT_WARNING = "Aviso!"
|
||||
HTML_ALERT_WEAK_PASSWORD = "Você está usando a senha administrativa padrão.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ LABEL_ALLOW_GRAVATAR = "Разрешить граватары"
|
|||
LEGEND_MAIN = "Основное"
|
||||
LABEL_ATTACHMENT_SIZE_LIMIT = "Предельный размер вложений"
|
||||
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Разрешить дополнительные аккаунты"
|
||||
LABEL_ALLOW_IDENTITIES = "Разрешить множественные профили"
|
||||
LABEL_ALLOW_TEMPLATES = "Разрешить шаблоны"
|
||||
ALERT_WARNING = "Внимание!"
|
||||
HTML_ALERT_WEAK_PASSWORD = "Вы используете пароль администратора по умолчанию.
|
||||
|
|
|
|||
|
|
@ -481,6 +481,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)"
|
|||
[SETTINGS_GENERAL]
|
||||
LEGEND_GENERAL = "General"
|
||||
LABEL_LANGUAGE = "Language"
|
||||
LABEL_IDENTITY = "Identity"
|
||||
LABEL_LAYOUT = "Layout"
|
||||
LABEL_LAYOUT_NO_SPLIT = "No Split"
|
||||
LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue