mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-04 15:07:02 +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
|
## License
|
||||||
|
|
||||||
RainLoop Webmail (**Community edition**) is released under
|
**RainLoop Webmail (Community edition)** is released under
|
||||||
**GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (AGPL)**.
|
**GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (AGPL)**.
|
||||||
http://www.gnu.org/licenses/agpl-3.0.html
|
http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,6 @@
|
||||||
{
|
{
|
||||||
var
|
var
|
||||||
kn = require('Knoin/Knoin'),
|
kn = require('Knoin/Knoin'),
|
||||||
sStartupUrl = Utils.pString(Settings.settingsGet('StartupUrl')),
|
|
||||||
sCustomLogoutLink = Utils.pString(Settings.settingsGet('CustomLogoutLink')),
|
sCustomLogoutLink = Utils.pString(Settings.settingsGet('CustomLogoutLink')),
|
||||||
bInIframe = !!Settings.settingsGet('InIframe')
|
bInIframe = !!Settings.settingsGet('InIframe')
|
||||||
;
|
;
|
||||||
|
|
@ -235,7 +234,6 @@
|
||||||
|
|
||||||
if (bLogout)
|
if (bLogout)
|
||||||
{
|
{
|
||||||
sStartupUrl = '';
|
|
||||||
this.clearClientSideToken();
|
this.clearClientSideToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,11 +242,6 @@
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bAdmin)
|
|
||||||
{
|
|
||||||
sStartupUrl = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
sCustomLogoutLink = sCustomLogoutLink || (bAdmin ? Links.rootAdmin() : Links.rootUser());
|
sCustomLogoutLink = sCustomLogoutLink || (bAdmin ? Links.rootAdmin() : Links.rootUser());
|
||||||
|
|
||||||
if (bLogout && window.location.href !== sCustomLogoutLink)
|
if (bLogout && window.location.href !== sCustomLogoutLink)
|
||||||
|
|
@ -267,7 +260,7 @@
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
kn.routeOff();
|
kn.routeOff();
|
||||||
kn.setHash(Links.root(sStartupUrl), true);
|
kn.setHash(Links.root(), true);
|
||||||
kn.routeOff();
|
kn.routeOff();
|
||||||
|
|
||||||
_.delay(function () {
|
_.delay(function () {
|
||||||
|
|
|
||||||
|
|
@ -1273,6 +1273,7 @@
|
||||||
self = this,
|
self = this,
|
||||||
$LAB = require('$LAB'),
|
$LAB = require('$LAB'),
|
||||||
sJsHash = Settings.settingsGet('JsHash'),
|
sJsHash = Settings.settingsGet('JsHash'),
|
||||||
|
sStartupUrl = Utils.pString(Settings.settingsGet('StartupUrl')),
|
||||||
iContactsSyncInterval = Utils.pInt(Settings.settingsGet('ContactsSyncInterval')),
|
iContactsSyncInterval = Utils.pInt(Settings.settingsGet('ContactsSyncInterval')),
|
||||||
bGoogle = Settings.settingsGet('AllowGoogleSocial'),
|
bGoogle = Settings.settingsGet('AllowGoogleSocial'),
|
||||||
bFacebook = Settings.settingsGet('AllowFacebookSocial'),
|
bFacebook = Settings.settingsGet('AllowFacebookSocial'),
|
||||||
|
|
@ -1314,6 +1315,13 @@
|
||||||
|
|
||||||
if (bValue)
|
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))
|
if ($LAB && window.crypto && window.crypto.getRandomValues && Settings.capa(Enums.Capa.OpenPGP))
|
||||||
{
|
{
|
||||||
var fOpenpgpCallback = function (openpgp) {
|
var fOpenpgpCallback = function (openpgp) {
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,8 @@
|
||||||
'AttachmentThumbnails': 'ATTACHMENT_THUMBNAILS',
|
'AttachmentThumbnails': 'ATTACHMENT_THUMBNAILS',
|
||||||
'Templates': 'TEMPLATES',
|
'Templates': 'TEMPLATES',
|
||||||
'AutoLogout': 'AUTOLOGOUT',
|
'AutoLogout': 'AUTOLOGOUT',
|
||||||
'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS'
|
'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS',
|
||||||
|
'Identities': 'IDENTITIES'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -56,9 +56,12 @@
|
||||||
'SettingsContacts', 'SETTINGS_LABELS/LABEL_CONTACTS_NAME', 'contacts');
|
'SettingsContacts', 'SETTINGS_LABELS/LABEL_CONTACTS_NAME', 'contacts');
|
||||||
}
|
}
|
||||||
|
|
||||||
kn.addSettingsViewModel(require('Settings/User/Accounts'), 'SettingsAccounts',
|
if (Settings.capa(Enums.Capa.AdditionalAccounts) || Settings.capa(Enums.Capa.Identities))
|
||||||
Settings.capa(Enums.Capa.AdditionalAccounts) ?
|
{
|
||||||
'SETTINGS_LABELS/LABEL_ACCOUNTS_NAME' : 'SETTINGS_LABELS/LABEL_IDENTITIES_NAME', 'accounts');
|
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))
|
if (Settings.capa(Enums.Capa.Sieve))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
this.capaUserBackground = CapaAdminStore.userBackground;
|
this.capaUserBackground = CapaAdminStore.userBackground;
|
||||||
this.capaGravatar = CapaAdminStore.gravatar;
|
this.capaGravatar = CapaAdminStore.gravatar;
|
||||||
this.capaAdditionalAccounts = CapaAdminStore.additionalAccounts;
|
this.capaAdditionalAccounts = CapaAdminStore.additionalAccounts;
|
||||||
|
this.capaIdentities = CapaAdminStore.identities;
|
||||||
this.capaAttachmentThumbnails = CapaAdminStore.attachmentThumbnails;
|
this.capaAttachmentThumbnails = CapaAdminStore.attachmentThumbnails;
|
||||||
this.capaTemplates = CapaAdminStore.templates;
|
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) {
|
self.capaTemplates.subscribe(function (bValue) {
|
||||||
Remote.saveAdminConfig(null, {
|
Remote.saveAdminConfig(null, {
|
||||||
'CapaTemplates': bValue ? '1' : '0'
|
'CapaTemplates': bValue ? '1' : '0'
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
function AccountsUserSettings()
|
function AccountsUserSettings()
|
||||||
{
|
{
|
||||||
this.allowAdditionalAccount = Settings.capa(Enums.Capa.AdditionalAccounts);
|
this.allowAdditionalAccount = Settings.capa(Enums.Capa.AdditionalAccounts);
|
||||||
this.allowIdentities = true;
|
this.allowIdentities = Settings.capa(Enums.Capa.Identities);;
|
||||||
|
|
||||||
this.accounts = AccountStore.accounts;
|
this.accounts = AccountStore.accounts;
|
||||||
this.identities = IdentityStore.identities;
|
this.identities = IdentityStore.identities;
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,12 @@
|
||||||
AppStore = require('Stores/User/App'),
|
AppStore = require('Stores/User/App'),
|
||||||
LanguageStore = require('Stores/Language'),
|
LanguageStore = require('Stores/Language'),
|
||||||
SettingsStore = require('Stores/User/Settings'),
|
SettingsStore = require('Stores/User/Settings'),
|
||||||
|
IdentityStore = require('Stores/User/Identity'),
|
||||||
NotificationStore = require('Stores/User/Notification'),
|
NotificationStore = require('Stores/User/Notification'),
|
||||||
MessageStore = require('Stores/User/Message'),
|
MessageStore = require('Stores/User/Message'),
|
||||||
|
|
||||||
|
Settings = require('Storage/Settings'),
|
||||||
|
|
||||||
Remote = require('Remote/User/Ajax')
|
Remote = require('Remote/User/Ajax')
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -62,6 +65,20 @@
|
||||||
|
|
||||||
this.isAnimationSupported = Globals.bAnimationSupported;
|
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 () {
|
this.editorDefaultTypes = ko.computed(function () {
|
||||||
Translator.trigger();
|
Translator.trigger();
|
||||||
return [
|
return [
|
||||||
|
|
@ -82,6 +99,15 @@
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GeneralUserSettings.prototype.editMainIdentity = function ()
|
||||||
|
{
|
||||||
|
var oIdentity = this.identityMain();
|
||||||
|
if (oIdentity)
|
||||||
|
{
|
||||||
|
require('Knoin/Knoin').showScreenPopup(require('View/Popup/Identity'), [oIdentity]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
GeneralUserSettings.prototype.testSoundNotification = function ()
|
GeneralUserSettings.prototype.testSoundNotification = function ()
|
||||||
{
|
{
|
||||||
NotificationStore.playSoundNotification(true);
|
NotificationStore.playSoundNotification(true);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
function CapaAdminStore()
|
function CapaAdminStore()
|
||||||
{
|
{
|
||||||
this.additionalAccounts = ko.observable(false);
|
this.additionalAccounts = ko.observable(false);
|
||||||
|
this.identities = ko.observable(false);
|
||||||
this.gravatar = ko.observable(false);
|
this.gravatar = ko.observable(false);
|
||||||
this.attachmentThumbnails = ko.observable(false);
|
this.attachmentThumbnails = ko.observable(false);
|
||||||
this.sieve = ko.observable(false);
|
this.sieve = ko.observable(false);
|
||||||
|
|
@ -32,6 +33,7 @@
|
||||||
CapaAdminStore.prototype.populate = function()
|
CapaAdminStore.prototype.populate = function()
|
||||||
{
|
{
|
||||||
this.additionalAccounts(Settings.capa(Enums.Capa.AdditionalAccounts));
|
this.additionalAccounts(Settings.capa(Enums.Capa.AdditionalAccounts));
|
||||||
|
this.identities(Settings.capa(Enums.Capa.Identities));
|
||||||
this.gravatar(Settings.capa(Enums.Capa.Gravatar));
|
this.gravatar(Settings.capa(Enums.Capa.Gravatar));
|
||||||
this.attachmentThumbnails(Settings.capa(Enums.Capa.AttachmentThumbnails));
|
this.attachmentThumbnails(Settings.capa(Enums.Capa.AttachmentThumbnails));
|
||||||
this.sieve(Settings.capa(Enums.Capa.Sieve));
|
this.sieve(Settings.capa(Enums.Capa.Sieve));
|
||||||
|
|
|
||||||
|
|
@ -899,6 +899,20 @@ END;
|
||||||
return $sResult;
|
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
|
* @param string $sFileName
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -194,9 +194,8 @@ class Actions
|
||||||
*/
|
*/
|
||||||
public function GetShortLifeSpecAuthToken($iLife = 60)
|
public function GetShortLifeSpecAuthToken($iLife = 60)
|
||||||
{
|
{
|
||||||
$sToken = $this->getAuthToken();
|
$aAccountHash = \RainLoop\Utils::DecodeKeyValues($this->getLocalAuthToken());
|
||||||
$aAccountHash = \RainLoop\Utils::DecodeKeyValues($sToken);
|
if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && \is_array($aAccountHash))
|
||||||
if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && is_array($aAccountHash))
|
|
||||||
{
|
{
|
||||||
$aAccountHash[10] = \time() + $iLife;
|
$aAccountHash[10] = \time() + $iLife;
|
||||||
return \RainLoop\Utils::EncodeKeyValues($aAccountHash);
|
return \RainLoop\Utils::EncodeKeyValues($aAccountHash);
|
||||||
|
|
@ -458,6 +457,18 @@ class Actions
|
||||||
$this->Config()->Get('labs', 'http_client_ip_check_proxy', false)), $sLine);
|
$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);
|
$sLine = \preg_replace('/\{request:([^}]*)\}/i', 'request', $sLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -489,8 +500,12 @@ class Actions
|
||||||
{
|
{
|
||||||
$sEmail = $oAccount->Email();
|
$sEmail = $oAccount->Email();
|
||||||
$sLine = \str_replace('{user:email}', $sEmail, $sLine);
|
$sLine = \str_replace('{user:email}', $sEmail, $sLine);
|
||||||
$sLine = \str_replace('{user:login}', \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail), $sLine);
|
$sLine = \str_replace('{user:login}',
|
||||||
$sLine = \str_replace('{user:domain}', \MailSo\Base\Utils::GetDomainFromEmail($sEmail), $sLine);
|
\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)
|
if ($oAccount)
|
||||||
{
|
{
|
||||||
$sSpecAuthToken = '_'.$oAccount->GetAuthToken();
|
$sSpecAuthToken = '_'.$oAccount->GetAuthTokenQ();
|
||||||
|
|
||||||
$this->SetSpecAuthToken($sSpecAuthToken);
|
$this->SetSpecAuthToken($sSpecAuthToken);
|
||||||
\RainLoop\Utils::SetCookie(self::AUTH_SPEC_TOKEN_KEY, $sSpecAuthToken, 0, '/', null, null, true);
|
\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()))
|
if ($oAccount->SignMe() && 0 < \strlen($oAccount->SignMeToken()))
|
||||||
{
|
{
|
||||||
\RainLoop\Utils::SetCookie(self::AUTH_SIGN_ME_TOKEN_KEY,
|
\RainLoop\Utils::SetCookie(self::AUTH_SIGN_ME_TOKEN_KEY,
|
||||||
\RainLoop\Utils::EncodeKeyValues(array(
|
\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||||
'e' => $oAccount->Email(),
|
'e' => $oAccount->Email(),
|
||||||
't' => $oAccount->SignMeToken()
|
't' => $oAccount->SignMeToken()
|
||||||
)),
|
)),
|
||||||
|
|
@ -569,9 +584,9 @@ class Actions
|
||||||
$this->StorageProvider()->Put($oAccount,
|
$this->StorageProvider()->Put($oAccount,
|
||||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
||||||
'sign_me',
|
'sign_me',
|
||||||
\RainLoop\Utils::EncodeKeyValues(array(
|
\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||||
'Time' => \time(),
|
'Time' => \time(),
|
||||||
'AuthToken' => $oAccount->GetAuthToken(),
|
'AuthToken' => $oAccount->GetAuthTokenQ(),
|
||||||
'SignMetToken' => $oAccount->SignMeToken()
|
'SignMetToken' => $oAccount->SignMeToken()
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
|
@ -618,7 +633,7 @@ class Actions
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function getAuthToken()
|
private function getLocalAuthToken()
|
||||||
{
|
{
|
||||||
$sToken = $this->GetSpecAuthToken();
|
$sToken = $this->GetSpecAuthToken();
|
||||||
return !empty($sToken) && '_' === \substr($sToken, 0, 1) ? \substr($sToken, 1) : '';
|
return !empty($sToken) && '_' === \substr($sToken, 0, 1) ? \substr($sToken, 1) : '';
|
||||||
|
|
@ -637,7 +652,7 @@ class Actions
|
||||||
*/
|
*/
|
||||||
public function ClearAdminAuthToken()
|
public function ClearAdminAuthToken()
|
||||||
{
|
{
|
||||||
$aAdminHash = \RainLoop\Utils::DecodeKeyValues($this->getAdminAuthToken());
|
$aAdminHash = \RainLoop\Utils::DecodeKeyValuesQ($this->getAdminAuthToken());
|
||||||
if (
|
if (
|
||||||
!empty($aAdminHash[0]) && !empty($aAdminHash[1]) && !empty($aAdminHash[2]) &&
|
!empty($aAdminHash[0]) && !empty($aAdminHash[1]) && !empty($aAdminHash[2]) &&
|
||||||
'token' === $aAdminHash[0] && \md5(APP_SALT) === $aAdminHash[1]
|
'token' === $aAdminHash[0] && \md5(APP_SALT) === $aAdminHash[1]
|
||||||
|
|
@ -1085,7 +1100,7 @@ class Actions
|
||||||
$sRand = '';
|
$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;
|
$bResult = false;
|
||||||
if ($this->Config()->Get('security', 'allow_admin_panel', true))
|
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]) &&
|
if (!empty($aAdminHash[0]) && !empty($aAdminHash[1]) && !empty($aAdminHash[2]) &&
|
||||||
'token' === $aAdminHash[0] && \md5(APP_SALT) === $aAdminHash[1] &&
|
'token' === $aAdminHash[0] && \md5(APP_SALT) === $aAdminHash[1] &&
|
||||||
'' !== $this->Cacher(null, true)->Get(\RainLoop\KeyPathHelper::SessionAdminKey($aAdminHash[2]), '')
|
'' !== $this->Cacher(null, true)->Get(\RainLoop\KeyPathHelper::SessionAdminKey($aAdminHash[2]), '')
|
||||||
|
|
@ -1124,7 +1139,7 @@ class Actions
|
||||||
if (!empty($sTo))
|
if (!empty($sTo))
|
||||||
{
|
{
|
||||||
\RainLoop\Utils::SetCookie(self::AUTH_MAILTO_TOKEN_KEY,
|
\RainLoop\Utils::SetCookie(self::AUTH_MAILTO_TOKEN_KEY,
|
||||||
\RainLoop\Utils::EncodeKeyValues(array(
|
\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||||
'Time' => \microtime(true),
|
'Time' => \microtime(true),
|
||||||
'MailTo' => 'MailTo',
|
'MailTo' => 'MailTo',
|
||||||
'To' => $sTo
|
'To' => $sTo
|
||||||
|
|
@ -1177,16 +1192,17 @@ class Actions
|
||||||
* @param string $sToken
|
* @param string $sToken
|
||||||
* @param bool $bThrowExceptionOnFalse = true
|
* @param bool $bThrowExceptionOnFalse = true
|
||||||
* @param bool $bValidateShortToken = true
|
* @param bool $bValidateShortToken = true
|
||||||
|
* @param bool $bQ = false
|
||||||
*
|
*
|
||||||
* @return \RainLoop\Model\Account|bool
|
* @return \RainLoop\Model\Account|bool
|
||||||
* @throws \RainLoop\Exceptions\ClientException
|
* @throws \RainLoop\Exceptions\ClientException
|
||||||
*/
|
*/
|
||||||
public function GetAccountFromCustomToken($sToken, $bThrowExceptionOnFalse = true, $bValidateShortToken = true)
|
public function GetAccountFromCustomToken($sToken, $bThrowExceptionOnFalse = true, $bValidateShortToken = true, $bQ = false)
|
||||||
{
|
{
|
||||||
$oResult = false;
|
$oResult = false;
|
||||||
if (!empty($sToken))
|
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
|
if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && // simple token validation
|
||||||
8 <= \count($aAccountHash) && // length checking
|
8 <= \count($aAccountHash) && // length checking
|
||||||
!empty($aAccountHash[7]) && // does short token exist
|
!empty($aAccountHash[7]) && // does short token exist
|
||||||
|
|
@ -1236,7 +1252,7 @@ class Actions
|
||||||
$sSignMeToken = \RainLoop\Utils::GetCookie(\RainLoop\Actions::AUTH_SIGN_ME_TOKEN_KEY, '');
|
$sSignMeToken = \RainLoop\Utils::GetCookie(\RainLoop\Actions::AUTH_SIGN_ME_TOKEN_KEY, '');
|
||||||
if (!empty($sSignMeToken))
|
if (!empty($sSignMeToken))
|
||||||
{
|
{
|
||||||
$aTokenData = \RainLoop\Utils::DecodeKeyValues($sSignMeToken);
|
$aTokenData = \RainLoop\Utils::DecodeKeyValuesQ($sSignMeToken);
|
||||||
if (\is_array($aTokenData) && !empty($aTokenData['e']) && !empty($aTokenData['t']))
|
if (\is_array($aTokenData) && !empty($aTokenData['e']) && !empty($aTokenData['t']))
|
||||||
{
|
{
|
||||||
$sTokenSettings = $this->StorageProvider()->Get($aTokenData['e'],
|
$sTokenSettings = $this->StorageProvider()->Get($aTokenData['e'],
|
||||||
|
|
@ -1246,13 +1262,13 @@ class Actions
|
||||||
|
|
||||||
if (!empty($sTokenSettings))
|
if (!empty($sTokenSettings))
|
||||||
{
|
{
|
||||||
$aSignMeData = \RainLoop\Utils::DecodeKeyValues($sTokenSettings);
|
$aSignMeData = \RainLoop\Utils::DecodeKeyValuesQ($sTokenSettings);
|
||||||
if (\is_array($aSignMeData) &&
|
if (\is_array($aSignMeData) &&
|
||||||
!empty($aSignMeData['AuthToken']) &&
|
!empty($aSignMeData['AuthToken']) &&
|
||||||
!empty($aSignMeData['SignMetToken']) &&
|
!empty($aSignMeData['SignMetToken']) &&
|
||||||
$aSignMeData['SignMetToken'] === $aTokenData['t'])
|
$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)
|
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)
|
if (null !== $sToken)
|
||||||
{
|
{
|
||||||
\RainLoop\Utils::ClearCookie(self::AUTH_MAILTO_TOKEN_KEY);
|
\RainLoop\Utils::ClearCookie(self::AUTH_MAILTO_TOKEN_KEY);
|
||||||
$mMailToData = \RainLoop\Utils::DecodeKeyValues($sToken);
|
|
||||||
if (\is_array($mMailToData) && !empty($mMailToData['MailTo']) && 'MailTo' === $mMailToData['MailTo'] &&
|
$mMailToData = \RainLoop\Utils::DecodeKeyValuesQ($sToken);
|
||||||
!empty($mMailToData['To']))
|
if (\is_array($mMailToData) && !empty($mMailToData['MailTo']) &&
|
||||||
|
'MailTo' === $mMailToData['MailTo'] && !empty($mMailToData['To']))
|
||||||
{
|
{
|
||||||
$aResult['MailToEmail'] = $mMailToData['To'];
|
$aResult['MailToEmail'] = $mMailToData['To'];
|
||||||
}
|
}
|
||||||
|
|
@ -1496,6 +1513,8 @@ class Actions
|
||||||
$aResult['WelcomePageUrl'] = '';
|
$aResult['WelcomePageUrl'] = '';
|
||||||
$aResult['WelcomePageDisplay'] = '';
|
$aResult['WelcomePageDisplay'] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$aResult['StartupUrl'] = $this->compileLogParams($aResult['StartupUrl'], $oAccount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1509,6 +1528,8 @@ class Actions
|
||||||
|
|
||||||
$aResult['WelcomePageUrl'] = '';
|
$aResult['WelcomePageUrl'] = '';
|
||||||
$aResult['WelcomePageDisplay'] = '';
|
$aResult['WelcomePageDisplay'] = '';
|
||||||
|
|
||||||
|
$aResult['StartupUrl'] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$aResult['AllowGoogleSocial'] = (bool) $oConfig->Get('social', 'google_enable', false);
|
$aResult['AllowGoogleSocial'] = (bool) $oConfig->Get('social', 'google_enable', false);
|
||||||
|
|
@ -2109,51 +2130,27 @@ class Actions
|
||||||
*/
|
*/
|
||||||
private function clientRsaDecryptHelper($sEncryptedData)
|
private function clientRsaDecryptHelper($sEncryptedData)
|
||||||
{
|
{
|
||||||
$aMatch = array();
|
// $aMatch = array();
|
||||||
if ('rsa:xxx:' === substr($sEncryptedData, 0, 8) && $this->Config()->Get('security', 'use_rsa_encryption', false))
|
// if ('rsa:xxx:' === \substr($sEncryptedData, 0, 8) && $this->Config()->Get('security', 'use_rsa_encryption', false))
|
||||||
{
|
// {
|
||||||
$oLogger = $this->Logger();
|
// $oLogger = $this->Logger();
|
||||||
$oLogger->Write('Trying to decode encrypted data', \MailSo\Log\Enumerations\Type::INFO, 'RSA');
|
// $oLogger->Write('Trying to decode encrypted data', \MailSo\Log\Enumerations\Type::INFO, 'RSA');
|
||||||
|
// $oLogger->HideErrorNotices(true);
|
||||||
$sPrivateKey = file_exists(APP_PRIVATE_DATA.'rsa/private') ?
|
//
|
||||||
\file_get_contents(APP_PRIVATE_DATA.'rsa/private') : '';
|
// $sData = \trim(\substr($sEncryptedData, 8));
|
||||||
|
// $sData = \RainLoop\Utils::DecryptStringRSA(\base64_decode($sData));
|
||||||
if (!empty($sPrivateKey))
|
//
|
||||||
{
|
// if (false !== $sData && \preg_match('/^[a-z0-9]{32}:(.+):[a-z0-9]{32}$/', $sData, $aMatch) && isset($aMatch[1]))
|
||||||
$sData = \trim(\substr($sEncryptedData, 8));
|
// {
|
||||||
|
// $sEncryptedData = $aMatch[1];
|
||||||
if (!\class_exists('Crypt_RSA'))
|
// }
|
||||||
{
|
// else
|
||||||
\set_include_path(\get_include_path().PATH_SEPARATOR.APP_VERSION_ROOT_PATH.'app/libraries/phpseclib');
|
// {
|
||||||
include_once 'Crypt/RSA.php';
|
// $oLogger->Write('Invalid decrypted data', \MailSo\Log\Enumerations\Type::WARNING, 'RSA');
|
||||||
\defined('CRYPT_RSA_MODE') || \define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
|
// }
|
||||||
}
|
//
|
||||||
|
// $oLogger->HideErrorNotices(false);
|
||||||
$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');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sEncryptedData;
|
return $sEncryptedData;
|
||||||
}
|
}
|
||||||
|
|
@ -2290,6 +2287,7 @@ class Actions
|
||||||
1 < \count($aOrder['Accounts']))
|
1 < \count($aOrder['Accounts']))
|
||||||
{
|
{
|
||||||
$aAccounts = \array_merge(\array_flip($aOrder['Accounts']), $aAccounts);
|
$aAccounts = \array_merge(\array_flip($aOrder['Accounts']), $aAccounts);
|
||||||
|
|
||||||
$aAccounts = \array_filter($aAccounts, function ($sHash) {
|
$aAccounts = \array_filter($aAccounts, function ($sHash) {
|
||||||
return 5 < \strlen($sHash);
|
return 5 < \strlen($sHash);
|
||||||
});
|
});
|
||||||
|
|
@ -2390,10 +2388,11 @@ class Actions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \RainLoop\Model\Account $oAccount
|
* @param \RainLoop\Model\Account $oAccount
|
||||||
|
* @param bool $bAllowIdentities = false
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function GetIdentities($oAccount)
|
public function GetIdentities($oAccount, $bAllowIdentities = false)
|
||||||
{
|
{
|
||||||
$aIdentities = array();
|
$aIdentities = array();
|
||||||
if ($oAccount)
|
if ($oAccount)
|
||||||
|
|
@ -2421,14 +2420,14 @@ class Actions
|
||||||
|
|
||||||
if ($oItem && $oItem->Validate())
|
if ($oItem && $oItem->Validate())
|
||||||
{
|
{
|
||||||
if ('' === $oItem->Id())
|
if ($oItem->IsAccountIdentities())
|
||||||
{
|
{
|
||||||
$oItem->SetEmail($oAccount->Email());
|
$oItem->SetEmail($oAccount->Email());
|
||||||
$bHasAccountIdentity = true;
|
$bHasAccountIdentity = true;
|
||||||
|
|
||||||
\array_unshift($aIdentities, $oItem);
|
\array_push($aIdentities, $oItem);
|
||||||
}
|
}
|
||||||
else
|
else if ($bAllowIdentities)
|
||||||
{
|
{
|
||||||
\array_push($aIdentities, $oItem);
|
\array_push($aIdentities, $oItem);
|
||||||
}
|
}
|
||||||
|
|
@ -2442,7 +2441,7 @@ class Actions
|
||||||
\RainLoop\Model\Identity::NewInstanceFromAccount($oAccount));
|
\RainLoop\Model\Identity::NewInstanceFromAccount($oAccount));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1 < \count($aIdentities))
|
if (1 < \count($aIdentities) && $bAllowIdentities)
|
||||||
{
|
{
|
||||||
$sOrder = $this->StorageProvider()->Get($oAccount,
|
$sOrder = $this->StorageProvider()->Get($oAccount,
|
||||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
||||||
|
|
@ -2454,8 +2453,16 @@ class Actions
|
||||||
1 < \count($aOrder['Identities']))
|
1 < \count($aOrder['Identities']))
|
||||||
{
|
{
|
||||||
$aList = $aOrder['Identities'];
|
$aList = $aOrder['Identities'];
|
||||||
|
foreach ($aList as $iIndex => $sItem)
|
||||||
|
{
|
||||||
|
if ('' === $sItem)
|
||||||
|
{
|
||||||
|
$aList[$iIndex] = '---';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
\usort($aIdentities, function ($a, $b) use ($aList) {
|
\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 \RainLoop\Model\Account $oAccount
|
||||||
* @param array $aIdentities = array()
|
* @param array $aIdentities = array()
|
||||||
|
* @param bool $bAllowIdentities = false
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function SetIdentities($oAccount, $aIdentities = array())
|
public function SetIdentities($oAccount, $aIdentities = array(), $bAllowIdentities = false)
|
||||||
{
|
{
|
||||||
$aResult = array();
|
$aResult = array();
|
||||||
foreach ($aIdentities as $oItem)
|
foreach ($aIdentities as $oItem)
|
||||||
{
|
{
|
||||||
|
if (!$bAllowIdentities && $oItem && !$oItem->IsAccountIdentities())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$aResult[] = $oItem->ToSimpleJSON(false);
|
$aResult[] = $oItem->ToSimpleJSON(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2675,7 +2688,7 @@ class Actions
|
||||||
$oNewAccount->SetParentEmail($sParentEmail);
|
$oNewAccount->SetParentEmail($sParentEmail);
|
||||||
|
|
||||||
$aAccounts[$oNewAccount->Email()] = $oNewAccount->GetAuthToken();
|
$aAccounts[$oNewAccount->Email()] = $oNewAccount->GetAuthToken();
|
||||||
if (0 === \strlen($oAccount->ParentEmail()))
|
if (!$oAccount->IsAdditionalAccount())
|
||||||
{
|
{
|
||||||
$aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken();
|
$aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken();
|
||||||
}
|
}
|
||||||
|
|
@ -2824,7 +2837,7 @@ class Actions
|
||||||
$mResult = array(
|
$mResult = array(
|
||||||
'Files' => array(array(
|
'Files' => array(array(
|
||||||
'FileName' => 'attachments.zip',
|
'FileName' => 'attachments.zip',
|
||||||
'Hash' => \RainLoop\Utils::EncodeKeyValues(array(
|
'Hash' => \RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||||
'V' => APP_VERSION,
|
'V' => APP_VERSION,
|
||||||
'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
|
'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
|
||||||
'FileName' => 'attachments.zip',
|
'FileName' => 'attachments.zip',
|
||||||
|
|
@ -2912,7 +2925,7 @@ class Actions
|
||||||
{
|
{
|
||||||
$mResult['Files'][] = array(
|
$mResult['Files'][] = array(
|
||||||
'FileName' => isset($aItem['FileName']) ? $aItem['FileName'] : 'file.dat',
|
'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);
|
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)
|
foreach ($aIdentities as $oItem)
|
||||||
{
|
{
|
||||||
if ($oItem && $oItem->Id() !== $oIdentity->Id())
|
if ($oItem)
|
||||||
{
|
{
|
||||||
$aIdentitiesForSave[] = $oItem;
|
if ($oItem->Id() === $oIdentity->Id())
|
||||||
|
{
|
||||||
|
$aIdentitiesForSave[] = $oIdentity;
|
||||||
|
$bAdded = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$aIdentitiesForSave[] = $oItem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$aIdentitiesForSave[] = $oIdentity;
|
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();
|
$oAccount = $this->getAccountFromToken();
|
||||||
|
|
||||||
|
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::IDENTITIES, $oAccount))
|
||||||
|
{
|
||||||
|
return $this->FalseResponse(__FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
$sId = \trim($this->GetActionParam('IdToDelete', ''));
|
$sId = \trim($this->GetActionParam('IdToDelete', ''));
|
||||||
if (empty($sId))
|
if (empty($sId))
|
||||||
{
|
{
|
||||||
|
|
@ -2975,7 +3007,7 @@ class Actions
|
||||||
}
|
}
|
||||||
|
|
||||||
$aNew = array();
|
$aNew = array();
|
||||||
$aIdentities = $this->GetIdentities($oAccount);
|
$aIdentities = $this->GetIdentities($oAccount, $this->GetCapa(false, \RainLoop\Enumerations\Capa::IDENTITIES, $oAccount));
|
||||||
foreach ($aIdentities as $oItem)
|
foreach ($aIdentities as $oItem)
|
||||||
{
|
{
|
||||||
if ($oItem && $sId !== $oItem->Id())
|
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);
|
$aAccounts = $this->GetActionParam('Accounts', null);
|
||||||
$aIdentities = $this->GetActionParam('Identities', null);
|
$aIdentities = $this->GetActionParam('Identities', null);
|
||||||
|
|
||||||
if (!\is_array($aAccounts) || !\is_array($aIdentities))
|
if (!\is_array($aAccounts) && !\is_array($aIdentities))
|
||||||
{
|
{
|
||||||
return $this->FalseResponse(__FUNCTION__);
|
return $this->FalseResponse(__FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
@ -3118,8 +3151,8 @@ class Actions
|
||||||
return $this->DefaultResponse(__FUNCTION__, $this->StorageProvider()->Put($oAccount,
|
return $this->DefaultResponse(__FUNCTION__, $this->StorageProvider()->Put($oAccount,
|
||||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'accounts_identities_order',
|
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'accounts_identities_order',
|
||||||
\json_encode(array(
|
\json_encode(array(
|
||||||
'Accounts' => $aAccounts,
|
'Accounts' => \is_array($aAccounts) ? $aAccounts : array(),
|
||||||
'Identities' => $aIdentities
|
'Identities' => \is_array($aIdentities) ? $aIdentities : array()
|
||||||
))
|
))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
@ -3134,6 +3167,7 @@ class Actions
|
||||||
$oAccount = $this->getAccountFromToken();
|
$oAccount = $this->getAccountFromToken();
|
||||||
|
|
||||||
$mAccounts = false;
|
$mAccounts = false;
|
||||||
|
|
||||||
if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount))
|
if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount))
|
||||||
{
|
{
|
||||||
$mAccounts = $this->GetAccounts($oAccount);
|
$mAccounts = $this->GetAccounts($oAccount);
|
||||||
|
|
@ -3147,7 +3181,8 @@ class Actions
|
||||||
|
|
||||||
return $this->DefaultResponse(__FUNCTION__, array(
|
return $this->DefaultResponse(__FUNCTION__, array(
|
||||||
'Accounts' => $mAccounts,
|
'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:
|
case \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS:
|
||||||
$this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_additional_accounts', 'bool');
|
$this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_additional_accounts', 'bool');
|
||||||
break;
|
break;
|
||||||
|
case \RainLoop\Enumerations\Capa::IDENTITIES:
|
||||||
|
$this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_additional_identities', 'bool');
|
||||||
|
break;
|
||||||
case \RainLoop\Enumerations\Capa::TEMPLATES:
|
case \RainLoop\Enumerations\Capa::TEMPLATES:
|
||||||
$this->setConfigFromParams($oConfig, $sParamName, 'capa', 'templates', 'bool');
|
$this->setConfigFromParams($oConfig, $sParamName, 'capa', 'templates', 'bool');
|
||||||
break;
|
break;
|
||||||
|
|
@ -3560,6 +3598,7 @@ class Actions
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->setCapaFromParams($oConfig, 'CapaAdditionalAccounts', \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS);
|
$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, 'CapaTemplates', \RainLoop\Enumerations\Capa::TEMPLATES);
|
||||||
$this->setCapaFromParams($oConfig, 'CapaTwoFactorAuth', \RainLoop\Enumerations\Capa::TWO_FACTOR);
|
$this->setCapaFromParams($oConfig, 'CapaTwoFactorAuth', \RainLoop\Enumerations\Capa::TWO_FACTOR);
|
||||||
$this->setCapaFromParams($oConfig, 'CapaTwoFactorAuthForce', \RainLoop\Enumerations\Capa::TWO_FACTOR_FORCE);
|
$this->setCapaFromParams($oConfig, 'CapaTwoFactorAuthForce', \RainLoop\Enumerations\Capa::TWO_FACTOR_FORCE);
|
||||||
|
|
@ -7128,19 +7167,19 @@ class Actions
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$aAttachments = $this->GetActionParam('Attachments', array());
|
$aAttachments = $this->GetActionParam('Attachments', array());
|
||||||
if (is_array($aAttachments) && 0 < count($aAttachments))
|
if (\is_array($aAttachments) && 0 < \count($aAttachments))
|
||||||
{
|
{
|
||||||
$mResult = array();
|
$mResult = array();
|
||||||
foreach ($aAttachments as $sAttachment)
|
foreach ($aAttachments as $sAttachment)
|
||||||
{
|
{
|
||||||
$aValues = \RainLoop\Utils::DecodeKeyValues($sAttachment);
|
$aValues = \RainLoop\Utils::DecodeKeyValuesQ($sAttachment);
|
||||||
if (is_array($aValues))
|
if (\is_array($aValues))
|
||||||
{
|
{
|
||||||
$sFolder = isset($aValues['Folder']) ? $aValues['Folder'] : '';
|
$sFolder = isset($aValues['Folder']) ? $aValues['Folder'] : '';
|
||||||
$iUid = (int) isset($aValues['Uid']) ? $aValues['Uid'] : 0;
|
$iUid = (int) isset($aValues['Uid']) ? $aValues['Uid'] : 0;
|
||||||
$sMimeIndex = (string) isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : '';
|
$sMimeIndex = (string) isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : '';
|
||||||
|
|
||||||
$sTempName = md5($sAttachment);
|
$sTempName = \md5($sAttachment);
|
||||||
if (!$this->FilesProvider()->FileExists($oAccount, $sTempName))
|
if (!$this->FilesProvider()->FileExists($oAccount, $sTempName))
|
||||||
{
|
{
|
||||||
$this->MailClient()->MessageMimeStream(
|
$this->MailClient()->MessageMimeStream(
|
||||||
|
|
@ -7738,7 +7777,7 @@ class Actions
|
||||||
$aParams = $this->GetActionParam('Params', null);
|
$aParams = $this->GetActionParam('Params', null);
|
||||||
$this->Http()->ServerNoCache();
|
$this->Http()->ServerNoCache();
|
||||||
|
|
||||||
$aData = \RainLoop\Utils::DecodeKeyValues($sRawKey);
|
$aData = \RainLoop\Utils::DecodeKeyValuesQ($sRawKey);
|
||||||
if (isset($aParams[0], $aParams[1], $aParams[2]) &&
|
if (isset($aParams[0], $aParams[1], $aParams[2]) &&
|
||||||
'Raw' === $aParams[0] && 'FramedView' === $aParams[2] && isset($aData['Framed']) && $aData['Framed'] && $aData['FileName'])
|
'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;
|
$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) &&
|
if ($oConfig->Get('security', 'allow_two_factor_auth', false) &&
|
||||||
($bAdmin || ($oAccount && !$oAccount->IsAdditionalAccount())))
|
($bAdmin || ($oAccount && !$oAccount->IsAdditionalAccount())))
|
||||||
{
|
{
|
||||||
|
|
@ -8399,7 +8443,7 @@ class Actions
|
||||||
$bResult = false;
|
$bResult = false;
|
||||||
if (!empty($sRawKey))
|
if (!empty($sRawKey))
|
||||||
{
|
{
|
||||||
$aValues = \RainLoop\Utils::DecodeKeyValues($sRawKey);
|
$aValues = \RainLoop\Utils::DecodeKeyValuesQ($sRawKey);
|
||||||
if (is_array($aValues))
|
if (is_array($aValues))
|
||||||
{
|
{
|
||||||
$bResult = $aValues;
|
$bResult = $aValues;
|
||||||
|
|
@ -9205,7 +9249,7 @@ class Actions
|
||||||
|
|
||||||
$sSubject = $mResult['Subject'];
|
$sSubject = $mResult['Subject'];
|
||||||
$mResult['Hash'] = \md5($mResult['Folder'].$mResult['Uid']);
|
$mResult['Hash'] = \md5($mResult['Folder'].$mResult['Uid']);
|
||||||
$mResult['RequestHash'] = \RainLoop\Utils::EncodeKeyValues(array(
|
$mResult['RequestHash'] = \RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||||
'V' => APP_VERSION,
|
'V' => APP_VERSION,
|
||||||
'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
|
'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
|
||||||
'Folder' => $mResult['Folder'],
|
'Folder' => $mResult['Folder'],
|
||||||
|
|
@ -9270,7 +9314,7 @@ class Actions
|
||||||
if (!!$this->Config()->Get('labs', 'use_local_proxy_for_external_images', false))
|
if (!!$this->Config()->Get('labs', 'use_local_proxy_for_external_images', false))
|
||||||
{
|
{
|
||||||
$fAdditionalExternalFilter = function ($sUrl) {
|
$fAdditionalExternalFilter = function ($sUrl) {
|
||||||
return './?/ProxyExternal/'.\RainLoop\Utils::EncodeKeyValues(array(
|
return './?/ProxyExternal/'.\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||||
'Rnd' => \md5(\microtime(true)),
|
'Rnd' => \md5(\microtime(true)),
|
||||||
'Token' => \RainLoop\Utils::GetConnectionToken(),
|
'Token' => \RainLoop\Utils::GetConnectionToken(),
|
||||||
'Url' => $sUrl
|
'Url' => $sUrl
|
||||||
|
|
@ -9421,7 +9465,7 @@ class Actions
|
||||||
$mResult['IsThumbnail'] = $this->isFileHasThumbnail($mResult['FileName']);
|
$mResult['IsThumbnail'] = $this->isFileHasThumbnail($mResult['FileName']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$mResult['Download'] = \RainLoop\Utils::EncodeKeyValues(array(
|
$mResult['Download'] = \RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||||
'V' => APP_VERSION,
|
'V' => APP_VERSION,
|
||||||
'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
|
'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
|
||||||
'Folder' => $mResult['Folder'],
|
'Folder' => $mResult['Folder'],
|
||||||
|
|
|
||||||
|
|
@ -139,12 +139,13 @@ class Api
|
||||||
{
|
{
|
||||||
$sSsoHash = \MailSo\Base\Utils::Sha1Rand($sEmail.$sPassword);
|
$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),
|
||||||
'Email' => $sEmail,
|
\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||||
'Password' => $sPassword,
|
'Email' => $sEmail,
|
||||||
'AdditionalOptions' => $aAdditionalOptions,
|
'Password' => $sPassword,
|
||||||
'Time' => $bUseTimeout ? \time() : 0
|
'AdditionalOptions' => $aAdditionalOptions,
|
||||||
))) ? $sSsoHash : '';
|
'Time' => $bUseTimeout ? \time() : 0
|
||||||
|
))) ? $sSsoHash : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ class Application extends \RainLoop\Config\AbstractConfig
|
||||||
'allow_languages_on_settings' => array(true, 'Allow language selection on settings screen'),
|
'allow_languages_on_settings' => array(true, 'Allow language selection on settings screen'),
|
||||||
|
|
||||||
'allow_additional_accounts' => array(true, ''),
|
'allow_additional_accounts' => array(true, ''),
|
||||||
|
'allow_additional_identities' => array(true, ''),
|
||||||
|
|
||||||
'messages_per_page' => array(20, ' Number of messages displayed on page by default'),
|
'messages_per_page' => array(20, ' Number of messages displayed on page by default'),
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ class Capa
|
||||||
const FILTERS = 'FILTERS';
|
const FILTERS = 'FILTERS';
|
||||||
const ATTACHMENT_THUMBNAILS = 'ATTACHMENT_THUMBNAILS';
|
const ATTACHMENT_THUMBNAILS = 'ATTACHMENT_THUMBNAILS';
|
||||||
const ADDITIONAL_ACCOUNTS = 'ADDITIONAL_ACCOUNTS';
|
const ADDITIONAL_ACCOUNTS = 'ADDITIONAL_ACCOUNTS';
|
||||||
|
const IDENTITIES = 'IDENTITIES';
|
||||||
const TEMPLATES = 'TEMPLATES';
|
const TEMPLATES = 'TEMPLATES';
|
||||||
const AUTOLOGOUT = 'AUTOLOGOUT';
|
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 \RainLoop\Plugins\Manager $oPlugins
|
||||||
* @param \MailSo\Mail\MailClient $oMailClient
|
* @param \MailSo\Mail\MailClient $oMailClient
|
||||||
|
|
|
||||||
|
|
@ -75,11 +75,13 @@ class Identity
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param bool $bFillOnEmpty = false
|
||||||
|
*
|
||||||
* @return string
|
* @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 !empty($this->sEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function IsAccountIdentities()
|
||||||
|
{
|
||||||
|
return '' === $this->Id();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -429,7 +429,7 @@ class ServiceActions
|
||||||
{
|
{
|
||||||
$this->oActions->verifyCacheByKey($sData);
|
$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())
|
if (\is_array($aData) && !empty($aData['Token']) && !empty($aData['Url']) && $aData['Token'] === \RainLoop\Utils::GetConnectionToken())
|
||||||
{
|
{
|
||||||
$iCode = 404;
|
$iCode = 404;
|
||||||
|
|
@ -892,7 +892,7 @@ class ServiceActions
|
||||||
$sSsoSubData = $this->Cacher()->Get(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash));
|
$sSsoSubData = $this->Cacher()->Get(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash));
|
||||||
if (!empty($sSsoSubData))
|
if (!empty($sSsoSubData))
|
||||||
{
|
{
|
||||||
$mData = \RainLoop\Utils::DecodeKeyValues($sSsoSubData);
|
$mData = \RainLoop\Utils::DecodeKeyValuesQ($sSsoSubData);
|
||||||
$this->Cacher()->Delete(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash));
|
$this->Cacher()->Delete(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash));
|
||||||
|
|
||||||
if (\is_array($mData) && !empty($mData['Email']) && isset($mData['Password'], $mData['Time']) &&
|
if (\is_array($mData) && !empty($mData['Email']) && isset($mData['Password'], $mData['Time']) &&
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,10 @@ class Utils
|
||||||
{
|
{
|
||||||
static $Cookies = null;
|
static $Cookies = null;
|
||||||
|
|
||||||
|
static $RSA = null;
|
||||||
|
|
||||||
|
static $RsaKey = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
@ -31,6 +35,145 @@ class Utils
|
||||||
return false;
|
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
|
* @param string $sString
|
||||||
|
|
@ -54,6 +197,42 @@ class Utils
|
||||||
return \MailSo\Base\Crypt::XxteaDecrypt($sEncriptedString, $sKey);
|
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 array $aValues
|
||||||
* @param string $sCustomKey = ''
|
* @param string $sCustomKey = ''
|
||||||
|
|
@ -63,7 +242,7 @@ class Utils
|
||||||
static public function EncodeKeyValues(array $aValues, $sCustomKey = '')
|
static public function EncodeKeyValues(array $aValues, $sCustomKey = '')
|
||||||
{
|
{
|
||||||
return \MailSo\Base\Utils::UrlSafeBase64Encode(
|
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 = '')
|
static public function DecodeKeyValues($sEncodedValues, $sCustomKey = '')
|
||||||
{
|
{
|
||||||
$aResult = \unserialize(
|
$aResult = @\unserialize(
|
||||||
\RainLoop\Utils::DecryptString(
|
\RainLoop\Utils::DecryptString(
|
||||||
\MailSo\Base\Utils::UrlSafeBase64Decode($sEncodedValues), \md5(APP_SALT.$sCustomKey)));
|
\MailSo\Base\Utils::UrlSafeBase64Decode($sEncodedValues), \md5(APP_SALT.$sCustomKey)));
|
||||||
|
|
||||||
return \is_array($aResult) ? $aResult : array();
|
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
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
|
@ -296,33 +503,33 @@ class Utils
|
||||||
*/
|
*/
|
||||||
public static function GetCookie($sName, $mDefault = null)
|
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)
|
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);
|
@\setcookie($sName, $sValue, $iExpire, $sPath, $sDomain, $sSecure, $bHttpOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function ClearCookie($sName)
|
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, '/');
|
@\setcookie($sName, '', \time() - 3600 * 24 * 30, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,155 +1,207 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of AES.
|
* Pure-PHP implementation of AES.
|
||||||
*
|
*
|
||||||
* Uses mcrypt, if available/possible, and an internal implementation, otherwise.
|
* Uses mcrypt, if available/possible, and an internal implementation, otherwise.
|
||||||
*
|
*
|
||||||
* PHP versions 4 and 5
|
* PHP versions 4 and 5
|
||||||
*
|
*
|
||||||
* If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
|
* If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
|
||||||
* {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
|
* {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
|
||||||
* it'll be null-padded to 192-bits and 192 bits will be the key length until {@link Crypt_AES::setKey() setKey()}
|
* it'll be null-padded to 192-bits and 192 bits will be the key length until {@link Crypt_AES::setKey() setKey()}
|
||||||
* is called, again, at which point, it'll be recalculated.
|
* is called, again, at which point, it'll be recalculated.
|
||||||
*
|
*
|
||||||
* Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
|
* Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
|
||||||
* make a whole lot of sense. {@link Crypt_AES::setBlockLength() setBlockLength()}, for instance. Calling that function,
|
* make a whole lot of sense. {@link Crypt_AES::setBlockLength() setBlockLength()}, for instance. Calling that function,
|
||||||
* however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
|
* however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
|
||||||
*
|
*
|
||||||
* Here's a short example of how to use this library:
|
* Here's a short example of how to use this library:
|
||||||
* <code>
|
* <code>
|
||||||
* <?php
|
* <?php
|
||||||
* include 'Crypt/AES.php';
|
* include 'Crypt/AES.php';
|
||||||
*
|
*
|
||||||
* $aes = new Crypt_AES();
|
* $aes = new Crypt_AES();
|
||||||
*
|
*
|
||||||
* $aes->setKey('abcdefghijklmnop');
|
* $aes->setKey('abcdefghijklmnop');
|
||||||
*
|
*
|
||||||
* $size = 10 * 1024;
|
* $size = 10 * 1024;
|
||||||
* $plaintext = '';
|
* $plaintext = '';
|
||||||
* for ($i = 0; $i < $size; $i++) {
|
* for ($i = 0; $i < $size; $i++) {
|
||||||
* $plaintext.= 'a';
|
* $plaintext.= 'a';
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* echo $aes->decrypt($aes->encrypt($plaintext));
|
* echo $aes->decrypt($aes->encrypt($plaintext));
|
||||||
* ?>
|
* ?>
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* @category Crypt
|
* @category Crypt
|
||||||
* @package Crypt_AES
|
* @package Crypt_AES
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @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
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Include Crypt_Rijndael
|
* Include Crypt_Rijndael
|
||||||
*/
|
*/
|
||||||
if (!class_exists('Crypt_Rijndael')) {
|
if (!class_exists('Crypt_Rijndael')) {
|
||||||
include_once 'Rijndael.php';
|
include_once 'Rijndael.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
* @access public
|
* @access public
|
||||||
* @see Crypt_AES::encrypt()
|
* @see Crypt_AES::encrypt()
|
||||||
* @see Crypt_AES::decrypt()
|
* @see Crypt_AES::decrypt()
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Counter mode.
|
* Encrypt / decrypt using the Counter mode.
|
||||||
*
|
*
|
||||||
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
|
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
|
||||||
*
|
*
|
||||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
|
||||||
*/
|
*/
|
||||||
define('CRYPT_AES_MODE_CTR', CRYPT_MODE_CTR);
|
define('CRYPT_AES_MODE_CTR', CRYPT_MODE_CTR);
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Electronic Code Book mode.
|
* Encrypt / decrypt using the Electronic Code Book mode.
|
||||||
*
|
*
|
||||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
|
||||||
*/
|
*/
|
||||||
define('CRYPT_AES_MODE_ECB', CRYPT_MODE_ECB);
|
define('CRYPT_AES_MODE_ECB', CRYPT_MODE_ECB);
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Code Book Chaining mode.
|
* Encrypt / decrypt using the Code Book Chaining mode.
|
||||||
*
|
*
|
||||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
|
||||||
*/
|
*/
|
||||||
define('CRYPT_AES_MODE_CBC', CRYPT_MODE_CBC);
|
define('CRYPT_AES_MODE_CBC', CRYPT_MODE_CBC);
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Cipher Feedback mode.
|
* Encrypt / decrypt using the Cipher Feedback mode.
|
||||||
*
|
*
|
||||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
|
||||||
*/
|
*/
|
||||||
define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB);
|
define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB);
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Cipher Feedback mode.
|
* Encrypt / decrypt using the Cipher Feedback mode.
|
||||||
*
|
*
|
||||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
|
||||||
*/
|
*/
|
||||||
define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
|
define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
* @access private
|
* @access private
|
||||||
* @see Crypt_Base::Crypt_Base()
|
* @see Crypt_Base::Crypt_Base()
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Toggles the internal implementation
|
* Toggles the internal implementation
|
||||||
*/
|
*/
|
||||||
define('CRYPT_AES_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
|
define('CRYPT_AES_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
|
||||||
/**
|
/**
|
||||||
* Toggles the mcrypt implementation
|
* Toggles the mcrypt implementation
|
||||||
*/
|
*/
|
||||||
define('CRYPT_AES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
|
define('CRYPT_AES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of AES.
|
* Pure-PHP implementation of AES.
|
||||||
*
|
*
|
||||||
* @package Crypt_AES
|
* @package Crypt_AES
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
class Crypt_AES extends Crypt_Rijndael
|
class Crypt_AES extends Crypt_Rijndael
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The namespace used by the cipher for its constants.
|
* The namespace used by the cipher for its constants.
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::const_namespace
|
* @see Crypt_Base::const_namespace
|
||||||
* @var String
|
* @var String
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $const_namespace = 'AES';
|
var $const_namespace = 'AES';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dummy function
|
* Dummy function
|
||||||
*
|
*
|
||||||
* Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
|
* Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
|
||||||
*
|
*
|
||||||
* @see Crypt_Rijndael::setBlockLength()
|
* @see Crypt_Rijndael::setBlockLength()
|
||||||
* @access public
|
* @access public
|
||||||
* @param Integer $length
|
* @param Integer $length
|
||||||
*/
|
*/
|
||||||
function setBlockLength($length)
|
function setBlockLength($length)
|
||||||
{
|
{
|
||||||
return;
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,329 +1,329 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of RC4.
|
* Pure-PHP implementation of RC4.
|
||||||
*
|
*
|
||||||
* Uses mcrypt, if available, and an internal implementation, otherwise.
|
* Uses mcrypt, if available, and an internal implementation, otherwise.
|
||||||
*
|
*
|
||||||
* PHP versions 4 and 5
|
* PHP versions 4 and 5
|
||||||
*
|
*
|
||||||
* Useful resources are as follows:
|
* Useful resources are as follows:
|
||||||
*
|
*
|
||||||
* - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
|
* - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
|
||||||
* - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
|
* - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
|
||||||
*
|
*
|
||||||
* RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
|
* RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
|
||||||
* ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
|
* ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
|
||||||
*
|
*
|
||||||
* Here's a short example of how to use this library:
|
* Here's a short example of how to use this library:
|
||||||
* <code>
|
* <code>
|
||||||
* <?php
|
* <?php
|
||||||
* include 'Crypt/RC4.php';
|
* include 'Crypt/RC4.php';
|
||||||
*
|
*
|
||||||
* $rc4 = new Crypt_RC4();
|
* $rc4 = new Crypt_RC4();
|
||||||
*
|
*
|
||||||
* $rc4->setKey('abcdefgh');
|
* $rc4->setKey('abcdefgh');
|
||||||
*
|
*
|
||||||
* $size = 10 * 1024;
|
* $size = 10 * 1024;
|
||||||
* $plaintext = '';
|
* $plaintext = '';
|
||||||
* for ($i = 0; $i < $size; $i++) {
|
* for ($i = 0; $i < $size; $i++) {
|
||||||
* $plaintext.= 'a';
|
* $plaintext.= 'a';
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* echo $rc4->decrypt($rc4->encrypt($plaintext));
|
* echo $rc4->decrypt($rc4->encrypt($plaintext));
|
||||||
* ?>
|
* ?>
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* @category Crypt
|
* @category Crypt
|
||||||
* @package Crypt_RC4
|
* @package Crypt_RC4
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @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
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Include Crypt_Base
|
* Include Crypt_Base
|
||||||
*
|
*
|
||||||
* Base cipher class
|
* Base cipher class
|
||||||
*/
|
*/
|
||||||
if (!class_exists('Crypt_Base')) {
|
if (!class_exists('Crypt_Base')) {
|
||||||
include_once 'Base.php';
|
include_once 'Base.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
* @access private
|
* @access private
|
||||||
* @see Crypt_RC4::Crypt_RC4()
|
* @see Crypt_RC4::Crypt_RC4()
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Toggles the internal implementation
|
* Toggles the internal implementation
|
||||||
*/
|
*/
|
||||||
define('CRYPT_RC4_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
|
define('CRYPT_RC4_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
|
||||||
/**
|
/**
|
||||||
* Toggles the mcrypt implementation
|
* Toggles the mcrypt implementation
|
||||||
*/
|
*/
|
||||||
define('CRYPT_RC4_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
|
define('CRYPT_RC4_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
* @access private
|
* @access private
|
||||||
* @see Crypt_RC4::_crypt()
|
* @see Crypt_RC4::_crypt()
|
||||||
*/
|
*/
|
||||||
define('CRYPT_RC4_ENCRYPT', 0);
|
define('CRYPT_RC4_ENCRYPT', 0);
|
||||||
define('CRYPT_RC4_DECRYPT', 1);
|
define('CRYPT_RC4_DECRYPT', 1);
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of RC4.
|
* Pure-PHP implementation of RC4.
|
||||||
*
|
*
|
||||||
* @package Crypt_RC4
|
* @package Crypt_RC4
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
class Crypt_RC4 extends Crypt_Base
|
class Crypt_RC4 extends Crypt_Base
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Block Length of the cipher
|
* Block Length of the cipher
|
||||||
*
|
*
|
||||||
* RC4 is a stream cipher
|
* RC4 is a stream cipher
|
||||||
* so we the block_size to 0
|
* so we the block_size to 0
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::block_size
|
* @see Crypt_Base::block_size
|
||||||
* @var Integer
|
* @var Integer
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $block_size = 0;
|
var $block_size = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default password key_size used by setPassword()
|
* The default password key_size used by setPassword()
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::password_key_size
|
* @see Crypt_Base::password_key_size
|
||||||
* @see Crypt_Base::setPassword()
|
* @see Crypt_Base::setPassword()
|
||||||
* @var Integer
|
* @var Integer
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $password_key_size = 128; // = 1024 bits
|
var $password_key_size = 128; // = 1024 bits
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The namespace used by the cipher for its constants.
|
* The namespace used by the cipher for its constants.
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::const_namespace
|
* @see Crypt_Base::const_namespace
|
||||||
* @var String
|
* @var String
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $const_namespace = 'RC4';
|
var $const_namespace = 'RC4';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mcrypt specific name of the cipher
|
* The mcrypt specific name of the cipher
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::cipher_name_mcrypt
|
* @see Crypt_Base::cipher_name_mcrypt
|
||||||
* @var String
|
* @var String
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $cipher_name_mcrypt = 'arcfour';
|
var $cipher_name_mcrypt = 'arcfour';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds whether performance-optimized $inline_crypt() can/should be used.
|
* Holds whether performance-optimized $inline_crypt() can/should be used.
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::inline_crypt
|
* @see Crypt_Base::inline_crypt
|
||||||
* @var mixed
|
* @var mixed
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $use_inline_crypt = false; // currently not available
|
var $use_inline_crypt = false; // currently not available
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Key
|
* The Key
|
||||||
*
|
*
|
||||||
* @see Crypt_RC4::setKey()
|
* @see Crypt_RC4::setKey()
|
||||||
* @var String
|
* @var String
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $key = "\0";
|
var $key = "\0";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Key Stream for decryption and encryption
|
* The Key Stream for decryption and encryption
|
||||||
*
|
*
|
||||||
* @see Crypt_RC4::setKey()
|
* @see Crypt_RC4::setKey()
|
||||||
* @var Array
|
* @var Array
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $stream;
|
var $stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
* Determines whether or not the mcrypt extension should be used.
|
* Determines whether or not the mcrypt extension should be used.
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::Crypt_Base()
|
* @see Crypt_Base::Crypt_Base()
|
||||||
* @return Crypt_RC4
|
* @return Crypt_RC4
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function Crypt_RC4()
|
function Crypt_RC4()
|
||||||
{
|
{
|
||||||
parent::Crypt_Base(CRYPT_MODE_STREAM);
|
parent::Crypt_Base(CRYPT_MODE_STREAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dummy function.
|
* Dummy function.
|
||||||
*
|
*
|
||||||
* Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
|
* Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
|
||||||
* If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
|
* If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
|
||||||
* calling setKey().
|
* calling setKey().
|
||||||
*
|
*
|
||||||
* [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
|
* [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
|
||||||
* the IV's are relatively easy to predict, an attack described by
|
* the IV's are relatively easy to predict, an attack described by
|
||||||
* {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
|
* {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
|
||||||
* can be used to quickly guess at the rest of the key. The following links elaborate:
|
* can be used to quickly guess at the rest of the key. The following links elaborate:
|
||||||
*
|
*
|
||||||
* {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
|
* {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
|
||||||
* {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
|
* {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
|
||||||
*
|
*
|
||||||
* @param String $iv
|
* @param String $iv
|
||||||
* @see Crypt_RC4::setKey()
|
* @see Crypt_RC4::setKey()
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function setIV($iv)
|
function setIV($iv)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the key.
|
* Sets the key.
|
||||||
*
|
*
|
||||||
* Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will
|
* Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will
|
||||||
* be used. If no key is explicitly set, it'll be assumed to be a single null byte.
|
* be used. If no key is explicitly set, it'll be assumed to be a single null byte.
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @see Crypt_Base::setKey()
|
* @see Crypt_Base::setKey()
|
||||||
* @param String $key
|
* @param String $key
|
||||||
*/
|
*/
|
||||||
function setKey($key)
|
function setKey($key)
|
||||||
{
|
{
|
||||||
parent::setKey(substr($key, 0, 256));
|
parent::setKey(substr($key, 0, 256));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts a message.
|
* Encrypts a message.
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::decrypt()
|
* @see Crypt_Base::decrypt()
|
||||||
* @see Crypt_RC4::_crypt()
|
* @see Crypt_RC4::_crypt()
|
||||||
* @access public
|
* @access public
|
||||||
* @param String $plaintext
|
* @param String $plaintext
|
||||||
* @return String $ciphertext
|
* @return String $ciphertext
|
||||||
*/
|
*/
|
||||||
function encrypt($plaintext)
|
function encrypt($plaintext)
|
||||||
{
|
{
|
||||||
if ($this->engine == CRYPT_MODE_MCRYPT) {
|
if ($this->engine == CRYPT_MODE_MCRYPT) {
|
||||||
return parent::encrypt($plaintext);
|
return parent::encrypt($plaintext);
|
||||||
}
|
}
|
||||||
return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
|
return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts a message.
|
* Decrypts a message.
|
||||||
*
|
*
|
||||||
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
|
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
|
||||||
* At least if the continuous buffer is disabled.
|
* At least if the continuous buffer is disabled.
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::encrypt()
|
* @see Crypt_Base::encrypt()
|
||||||
* @see Crypt_RC4::_crypt()
|
* @see Crypt_RC4::_crypt()
|
||||||
* @access public
|
* @access public
|
||||||
* @param String $ciphertext
|
* @param String $ciphertext
|
||||||
* @return String $plaintext
|
* @return String $plaintext
|
||||||
*/
|
*/
|
||||||
function decrypt($ciphertext)
|
function decrypt($ciphertext)
|
||||||
{
|
{
|
||||||
if ($this->engine == CRYPT_MODE_MCRYPT) {
|
if ($this->engine == CRYPT_MODE_MCRYPT) {
|
||||||
return parent::decrypt($ciphertext);
|
return parent::decrypt($ciphertext);
|
||||||
}
|
}
|
||||||
return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
|
return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup the key (expansion)
|
* Setup the key (expansion)
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::_setupKey()
|
* @see Crypt_Base::_setupKey()
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _setupKey()
|
function _setupKey()
|
||||||
{
|
{
|
||||||
$key = $this->key;
|
$key = $this->key;
|
||||||
$keyLength = strlen($key);
|
$keyLength = strlen($key);
|
||||||
$keyStream = range(0, 255);
|
$keyStream = range(0, 255);
|
||||||
$j = 0;
|
$j = 0;
|
||||||
for ($i = 0; $i < 256; $i++) {
|
for ($i = 0; $i < 256; $i++) {
|
||||||
$j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
|
$j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
|
||||||
$temp = $keyStream[$i];
|
$temp = $keyStream[$i];
|
||||||
$keyStream[$i] = $keyStream[$j];
|
$keyStream[$i] = $keyStream[$j];
|
||||||
$keyStream[$j] = $temp;
|
$keyStream[$j] = $temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->stream = array();
|
$this->stream = array();
|
||||||
$this->stream[CRYPT_RC4_DECRYPT] = $this->stream[CRYPT_RC4_ENCRYPT] = array(
|
$this->stream[CRYPT_RC4_DECRYPT] = $this->stream[CRYPT_RC4_ENCRYPT] = array(
|
||||||
0, // index $i
|
0, // index $i
|
||||||
0, // index $j
|
0, // index $j
|
||||||
$keyStream
|
$keyStream
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts or decrypts a message.
|
* Encrypts or decrypts a message.
|
||||||
*
|
*
|
||||||
* @see Crypt_RC4::encrypt()
|
* @see Crypt_RC4::encrypt()
|
||||||
* @see Crypt_RC4::decrypt()
|
* @see Crypt_RC4::decrypt()
|
||||||
* @access private
|
* @access private
|
||||||
* @param String $text
|
* @param String $text
|
||||||
* @param Integer $mode
|
* @param Integer $mode
|
||||||
* @return String $text
|
* @return String $text
|
||||||
*/
|
*/
|
||||||
function _crypt($text, $mode)
|
function _crypt($text, $mode)
|
||||||
{
|
{
|
||||||
if ($this->changed) {
|
if ($this->changed) {
|
||||||
$this->_setup();
|
$this->_setup();
|
||||||
$this->changed = false;
|
$this->changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$stream = &$this->stream[$mode];
|
$stream = &$this->stream[$mode];
|
||||||
if ($this->continuousBuffer) {
|
if ($this->continuousBuffer) {
|
||||||
$i = &$stream[0];
|
$i = &$stream[0];
|
||||||
$j = &$stream[1];
|
$j = &$stream[1];
|
||||||
$keyStream = &$stream[2];
|
$keyStream = &$stream[2];
|
||||||
} else {
|
} else {
|
||||||
$i = $stream[0];
|
$i = $stream[0];
|
||||||
$j = $stream[1];
|
$j = $stream[1];
|
||||||
$keyStream = $stream[2];
|
$keyStream = $stream[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
$len = strlen($text);
|
$len = strlen($text);
|
||||||
for ($k = 0; $k < $len; ++$k) {
|
for ($k = 0; $k < $len; ++$k) {
|
||||||
$i = ($i + 1) & 255;
|
$i = ($i + 1) & 255;
|
||||||
$ksi = $keyStream[$i];
|
$ksi = $keyStream[$i];
|
||||||
$j = ($j + $ksi) & 255;
|
$j = ($j + $ksi) & 255;
|
||||||
$ksj = $keyStream[$j];
|
$ksj = $keyStream[$j];
|
||||||
|
|
||||||
$keyStream[$i] = $ksj;
|
$keyStream[$i] = $ksj;
|
||||||
$keyStream[$j] = $ksi;
|
$keyStream[$j] = $ksi;
|
||||||
$text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]);
|
$text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,300 +1,300 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Random Number Generator
|
* Random Number Generator
|
||||||
*
|
*
|
||||||
* The idea behind this function is that it can be easily replaced with your own crypt_random_string()
|
* The idea behind this function is that it can be easily replaced with your own crypt_random_string()
|
||||||
* function. eg. maybe you have a better source of entropy for creating the initial states or whatever.
|
* function. eg. maybe you have a better source of entropy for creating the initial states or whatever.
|
||||||
*
|
*
|
||||||
* PHP versions 4 and 5
|
* PHP versions 4 and 5
|
||||||
*
|
*
|
||||||
* Here's a short example of how to use this library:
|
* Here's a short example of how to use this library:
|
||||||
* <code>
|
* <code>
|
||||||
* <?php
|
* <?php
|
||||||
* include 'Crypt/Random.php';
|
* include 'Crypt/Random.php';
|
||||||
*
|
*
|
||||||
* echo bin2hex(crypt_random_string(8));
|
* echo bin2hex(crypt_random_string(8));
|
||||||
* ?>
|
* ?>
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* @category Crypt
|
* @category Crypt
|
||||||
* @package Crypt_Random
|
* @package Crypt_Random
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @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
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// laravel is a PHP framework that utilizes phpseclib. laravel workbenches may, independently,
|
// laravel is a PHP framework that utilizes phpseclib. laravel workbenches may, independently,
|
||||||
// have phpseclib as a requirement as well. if you're developing such a program you may encounter
|
// have phpseclib as a requirement as well. if you're developing such a program you may encounter
|
||||||
// a "Cannot redeclare crypt_random_string()" error.
|
// a "Cannot redeclare crypt_random_string()" error.
|
||||||
if (!function_exists('crypt_random_string')) {
|
if (!function_exists('crypt_random_string')) {
|
||||||
/**
|
/**
|
||||||
* "Is Windows" test
|
* "Is Windows" test
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
|
define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a random string.
|
* Generate a random string.
|
||||||
*
|
*
|
||||||
* Although microoptimizations are generally discouraged as they impair readability this function is ripe with
|
* Although microoptimizations are generally discouraged as they impair readability this function is ripe with
|
||||||
* microoptimizations because this function has the potential of being called a huge number of times.
|
* microoptimizations because this function has the potential of being called a huge number of times.
|
||||||
* eg. for RSA key generation.
|
* eg. for RSA key generation.
|
||||||
*
|
*
|
||||||
* @param Integer $length
|
* @param Integer $length
|
||||||
* @return String
|
* @return String
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function crypt_random_string($length)
|
function crypt_random_string($length)
|
||||||
{
|
{
|
||||||
if (CRYPT_RANDOM_IS_WINDOWS) {
|
if (CRYPT_RANDOM_IS_WINDOWS) {
|
||||||
// method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
|
// method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
|
||||||
// ie. class_alias is a function that was introduced in PHP 5.3
|
// ie. class_alias is a function that was introduced in PHP 5.3
|
||||||
if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) {
|
if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) {
|
||||||
return mcrypt_create_iv($length);
|
return mcrypt_create_iv($length);
|
||||||
}
|
}
|
||||||
// method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
|
// method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
|
||||||
// to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
|
// to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
|
||||||
// openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
|
// openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
|
||||||
// call php_win32_get_random_bytes():
|
// call php_win32_get_random_bytes():
|
||||||
//
|
//
|
||||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
|
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
|
||||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
|
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
|
||||||
//
|
//
|
||||||
// php_win32_get_random_bytes() is defined thusly:
|
// php_win32_get_random_bytes() is defined thusly:
|
||||||
//
|
//
|
||||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
|
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
|
||||||
//
|
//
|
||||||
// we're calling it, all the same, in the off chance that the mcrypt extension is not available
|
// we're calling it, all the same, in the off chance that the mcrypt extension is not available
|
||||||
if (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
|
if (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
|
||||||
return openssl_random_pseudo_bytes($length);
|
return openssl_random_pseudo_bytes($length);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// method 1. the fastest
|
// method 1. the fastest
|
||||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||||
return openssl_random_pseudo_bytes($length);
|
return openssl_random_pseudo_bytes($length);
|
||||||
}
|
}
|
||||||
// method 2
|
// method 2
|
||||||
static $fp = true;
|
static $fp = true;
|
||||||
if ($fp === true) {
|
if ($fp === true) {
|
||||||
// warning's will be output unles the error suppression operator is used. errors such as
|
// warning's will be output unles the error suppression operator is used. errors such as
|
||||||
// "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
|
// "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
|
||||||
$fp = @fopen('/dev/urandom', 'rb');
|
$fp = @fopen('/dev/urandom', 'rb');
|
||||||
}
|
}
|
||||||
if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
|
if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
|
||||||
return fread($fp, $length);
|
return fread($fp, $length);
|
||||||
}
|
}
|
||||||
// method 3. pretty much does the same thing as method 2 per the following url:
|
// method 3. pretty much does the same thing as method 2 per the following url:
|
||||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
|
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
|
||||||
// surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
|
// surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
|
||||||
// not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
|
// not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
|
||||||
// restrictions or some such
|
// restrictions or some such
|
||||||
if (function_exists('mcrypt_create_iv')) {
|
if (function_exists('mcrypt_create_iv')) {
|
||||||
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
|
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// at this point we have no choice but to use a pure-PHP CSPRNG
|
// at this point we have no choice but to use a pure-PHP CSPRNG
|
||||||
|
|
||||||
// cascade entropy across multiple PHP instances by fixing the session and collecting all
|
// cascade entropy across multiple PHP instances by fixing the session and collecting all
|
||||||
// environmental variables, including the previous session data and the current session
|
// environmental variables, including the previous session data and the current session
|
||||||
// data.
|
// data.
|
||||||
//
|
//
|
||||||
// mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
|
// mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
|
||||||
// easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
|
// easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
|
||||||
// PHP isn't low level to be able to use those as sources and on a web server there's not likely
|
// PHP isn't low level to be able to use those as sources and on a web server there's not likely
|
||||||
// going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
|
// going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
|
||||||
// however, a ton of people visiting the website. obviously you don't want to base your seeding
|
// however, a ton of people visiting the website. obviously you don't want to base your seeding
|
||||||
// soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
|
// soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
|
||||||
// by the user and (2) this isn't just looking at the data sent by the current user - it's based
|
// by the user and (2) this isn't just looking at the data sent by the current user - it's based
|
||||||
// on the data sent by all users. one user requests the page and a hash of their info is saved.
|
// on the data sent by all users. one user requests the page and a hash of their info is saved.
|
||||||
// another user visits the page and the serialization of their data is utilized along with the
|
// another user visits the page and the serialization of their data is utilized along with the
|
||||||
// server envirnment stuff and a hash of the previous http request data (which itself utilizes
|
// server envirnment stuff and a hash of the previous http request data (which itself utilizes
|
||||||
// a hash of the session data before that). certainly an attacker should be assumed to have
|
// a hash of the session data before that). certainly an attacker should be assumed to have
|
||||||
// full control over his own http requests. he, however, is not going to have control over
|
// full control over his own http requests. he, however, is not going to have control over
|
||||||
// everyone's http requests.
|
// everyone's http requests.
|
||||||
static $crypto = false, $v;
|
static $crypto = false, $v;
|
||||||
if ($crypto === false) {
|
if ($crypto === false) {
|
||||||
// save old session data
|
// save old session data
|
||||||
$old_session_id = session_id();
|
$old_session_id = session_id();
|
||||||
$old_use_cookies = ini_get('session.use_cookies');
|
$old_use_cookies = ini_get('session.use_cookies');
|
||||||
$old_session_cache_limiter = session_cache_limiter();
|
$old_session_cache_limiter = session_cache_limiter();
|
||||||
$_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
|
$_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
|
||||||
if ($old_session_id != '') {
|
if ($old_session_id != '') {
|
||||||
session_write_close();
|
session_write_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
session_id(1);
|
session_id(1);
|
||||||
ini_set('session.use_cookies', 0);
|
ini_set('session.use_cookies', 0);
|
||||||
session_cache_limiter('');
|
session_cache_limiter('');
|
||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
|
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
|
||||||
serialize($_SERVER) .
|
serialize($_SERVER) .
|
||||||
serialize($_POST) .
|
serialize($_POST) .
|
||||||
serialize($_GET) .
|
serialize($_GET) .
|
||||||
serialize($_COOKIE) .
|
serialize($_COOKIE) .
|
||||||
serialize($GLOBALS) .
|
serialize($GLOBALS) .
|
||||||
serialize($_SESSION) .
|
serialize($_SESSION) .
|
||||||
serialize($_OLD_SESSION)
|
serialize($_OLD_SESSION)
|
||||||
));
|
));
|
||||||
if (!isset($_SESSION['count'])) {
|
if (!isset($_SESSION['count'])) {
|
||||||
$_SESSION['count'] = 0;
|
$_SESSION['count'] = 0;
|
||||||
}
|
}
|
||||||
$_SESSION['count']++;
|
$_SESSION['count']++;
|
||||||
|
|
||||||
session_write_close();
|
session_write_close();
|
||||||
|
|
||||||
// restore old session data
|
// restore old session data
|
||||||
if ($old_session_id != '') {
|
if ($old_session_id != '') {
|
||||||
session_id($old_session_id);
|
session_id($old_session_id);
|
||||||
session_start();
|
session_start();
|
||||||
ini_set('session.use_cookies', $old_use_cookies);
|
ini_set('session.use_cookies', $old_use_cookies);
|
||||||
session_cache_limiter($old_session_cache_limiter);
|
session_cache_limiter($old_session_cache_limiter);
|
||||||
} else {
|
} else {
|
||||||
if ($_OLD_SESSION !== false) {
|
if ($_OLD_SESSION !== false) {
|
||||||
$_SESSION = $_OLD_SESSION;
|
$_SESSION = $_OLD_SESSION;
|
||||||
unset($_OLD_SESSION);
|
unset($_OLD_SESSION);
|
||||||
} else {
|
} else {
|
||||||
unset($_SESSION);
|
unset($_SESSION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
|
// in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
|
||||||
// the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
|
// the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
|
||||||
// if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
|
// if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
|
||||||
// original hash and the current hash. we'll be emulating that. for more info see the following URL:
|
// original hash and the current hash. we'll be emulating that. for more info see the following URL:
|
||||||
//
|
//
|
||||||
// http://tools.ietf.org/html/rfc4253#section-7.2
|
// http://tools.ietf.org/html/rfc4253#section-7.2
|
||||||
//
|
//
|
||||||
// see the is_string($crypto) part for an example of how to expand the keys
|
// see the is_string($crypto) part for an example of how to expand the keys
|
||||||
$key = pack('H*', sha1($seed . 'A'));
|
$key = pack('H*', sha1($seed . 'A'));
|
||||||
$iv = pack('H*', sha1($seed . 'C'));
|
$iv = pack('H*', sha1($seed . 'C'));
|
||||||
|
|
||||||
// ciphers are used as per the nist.gov link below. also, see this link:
|
// ciphers are used as per the nist.gov link below. also, see this link:
|
||||||
//
|
//
|
||||||
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
|
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case phpseclib_resolve_include_path('Crypt/AES.php'):
|
case phpseclib_resolve_include_path('Crypt/AES.php'):
|
||||||
if (!class_exists('Crypt_AES')) {
|
if (!class_exists('Crypt_AES')) {
|
||||||
include_once 'AES.php';
|
include_once 'AES.php';
|
||||||
}
|
}
|
||||||
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
|
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
|
||||||
break;
|
break;
|
||||||
case phpseclib_resolve_include_path('Crypt/Twofish.php'):
|
case phpseclib_resolve_include_path('Crypt/Twofish.php'):
|
||||||
if (!class_exists('Crypt_Twofish')) {
|
if (!class_exists('Crypt_Twofish')) {
|
||||||
include_once 'Twofish.php';
|
include_once 'Twofish.php';
|
||||||
}
|
}
|
||||||
$crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
|
$crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
|
||||||
break;
|
break;
|
||||||
case phpseclib_resolve_include_path('Crypt/Blowfish.php'):
|
case phpseclib_resolve_include_path('Crypt/Blowfish.php'):
|
||||||
if (!class_exists('Crypt_Blowfish')) {
|
if (!class_exists('Crypt_Blowfish')) {
|
||||||
include_once 'Blowfish.php';
|
include_once 'Blowfish.php';
|
||||||
}
|
}
|
||||||
$crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
|
$crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
|
||||||
break;
|
break;
|
||||||
case phpseclib_resolve_include_path('Crypt/TripleDES.php'):
|
case phpseclib_resolve_include_path('Crypt/TripleDES.php'):
|
||||||
if (!class_exists('Crypt_TripleDES')) {
|
if (!class_exists('Crypt_TripleDES')) {
|
||||||
include_once 'TripleDES.php';
|
include_once 'TripleDES.php';
|
||||||
}
|
}
|
||||||
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
|
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
|
||||||
break;
|
break;
|
||||||
case phpseclib_resolve_include_path('Crypt/DES.php'):
|
case phpseclib_resolve_include_path('Crypt/DES.php'):
|
||||||
if (!class_exists('Crypt_DES')) {
|
if (!class_exists('Crypt_DES')) {
|
||||||
include_once 'DES.php';
|
include_once 'DES.php';
|
||||||
}
|
}
|
||||||
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
|
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
|
||||||
break;
|
break;
|
||||||
case phpseclib_resolve_include_path('Crypt/RC4.php'):
|
case phpseclib_resolve_include_path('Crypt/RC4.php'):
|
||||||
if (!class_exists('Crypt_RC4')) {
|
if (!class_exists('Crypt_RC4')) {
|
||||||
include_once 'RC4.php';
|
include_once 'RC4.php';
|
||||||
}
|
}
|
||||||
$crypto = new Crypt_RC4();
|
$crypto = new Crypt_RC4();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
user_error('crypt_random_string requires at least one symmetric cipher be loaded');
|
user_error('crypt_random_string requires at least one symmetric cipher be loaded');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$crypto->setKey($key);
|
$crypto->setKey($key);
|
||||||
$crypto->setIV($iv);
|
$crypto->setIV($iv);
|
||||||
$crypto->enableContinuousBuffer();
|
$crypto->enableContinuousBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
//return $crypto->encrypt(str_repeat("\0", $length));
|
//return $crypto->encrypt(str_repeat("\0", $length));
|
||||||
|
|
||||||
// the following is based off of ANSI X9.31:
|
// the following is based off of ANSI X9.31:
|
||||||
//
|
//
|
||||||
// http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
|
// http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
|
||||||
//
|
//
|
||||||
// OpenSSL uses that same standard for it's random numbers:
|
// OpenSSL uses that same standard for it's random numbers:
|
||||||
//
|
//
|
||||||
// http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
|
// http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
|
||||||
// (do a search for "ANS X9.31 A.2.4")
|
// (do a search for "ANS X9.31 A.2.4")
|
||||||
$result = '';
|
$result = '';
|
||||||
while (strlen($result) < $length) {
|
while (strlen($result) < $length) {
|
||||||
$i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21
|
$i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21
|
||||||
$r = $crypto->encrypt($i ^ $v); // strlen($v) == 20
|
$r = $crypto->encrypt($i ^ $v); // strlen($v) == 20
|
||||||
$v = $crypto->encrypt($r ^ $i); // strlen($r) == 20
|
$v = $crypto->encrypt($r ^ $i); // strlen($r) == 20
|
||||||
$result.= $r;
|
$result.= $r;
|
||||||
}
|
}
|
||||||
return substr($result, 0, $length);
|
return substr($result, 0, $length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!function_exists('phpseclib_resolve_include_path')) {
|
if (!function_exists('phpseclib_resolve_include_path')) {
|
||||||
/**
|
/**
|
||||||
* Resolve filename against the include path.
|
* Resolve filename against the include path.
|
||||||
*
|
*
|
||||||
* Wrapper around stream_resolve_include_path() (which was introduced in
|
* Wrapper around stream_resolve_include_path() (which was introduced in
|
||||||
* PHP 5.3.2) with fallback implementation for earlier PHP versions.
|
* PHP 5.3.2) with fallback implementation for earlier PHP versions.
|
||||||
*
|
*
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @return mixed Filename (string) on success, false otherwise.
|
* @return mixed Filename (string) on success, false otherwise.
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function phpseclib_resolve_include_path($filename)
|
function phpseclib_resolve_include_path($filename)
|
||||||
{
|
{
|
||||||
if (function_exists('stream_resolve_include_path')) {
|
if (function_exists('stream_resolve_include_path')) {
|
||||||
return stream_resolve_include_path($filename);
|
return stream_resolve_include_path($filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle non-relative paths
|
// handle non-relative paths
|
||||||
if (file_exists($filename)) {
|
if (file_exists($filename)) {
|
||||||
return realpath($filename);
|
return realpath($filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
$paths = PATH_SEPARATOR == ':' ?
|
$paths = PATH_SEPARATOR == ':' ?
|
||||||
preg_split('#(?<!phar):#', get_include_path()) :
|
preg_split('#(?<!phar):#', get_include_path()) :
|
||||||
explode(PATH_SEPARATOR, get_include_path());
|
explode(PATH_SEPARATOR, get_include_path());
|
||||||
foreach ($paths as $prefix) {
|
foreach ($paths as $prefix) {
|
||||||
// path's specified in include_path don't always end in /
|
// path's specified in include_path don't always end in /
|
||||||
$ds = substr($prefix, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR;
|
$ds = substr($prefix, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR;
|
||||||
$file = $prefix . $ds . $filename;
|
$file = $prefix . $ds . $filename;
|
||||||
if (file_exists($file)) {
|
if (file_exists($file)) {
|
||||||
return realpath($file);
|
return realpath($file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,428 +1,428 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of Triple DES.
|
* Pure-PHP implementation of Triple DES.
|
||||||
*
|
*
|
||||||
* Uses mcrypt, if available, and an internal implementation, otherwise. Operates in the EDE3 mode (encrypt-decrypt-encrypt).
|
* Uses mcrypt, if available, and an internal implementation, otherwise. Operates in the EDE3 mode (encrypt-decrypt-encrypt).
|
||||||
*
|
*
|
||||||
* PHP versions 4 and 5
|
* PHP versions 4 and 5
|
||||||
*
|
*
|
||||||
* Here's a short example of how to use this library:
|
* Here's a short example of how to use this library:
|
||||||
* <code>
|
* <code>
|
||||||
* <?php
|
* <?php
|
||||||
* include 'Crypt/TripleDES.php';
|
* include 'Crypt/TripleDES.php';
|
||||||
*
|
*
|
||||||
* $des = new Crypt_TripleDES();
|
* $des = new Crypt_TripleDES();
|
||||||
*
|
*
|
||||||
* $des->setKey('abcdefghijklmnopqrstuvwx');
|
* $des->setKey('abcdefghijklmnopqrstuvwx');
|
||||||
*
|
*
|
||||||
* $size = 10 * 1024;
|
* $size = 10 * 1024;
|
||||||
* $plaintext = '';
|
* $plaintext = '';
|
||||||
* for ($i = 0; $i < $size; $i++) {
|
* for ($i = 0; $i < $size; $i++) {
|
||||||
* $plaintext.= 'a';
|
* $plaintext.= 'a';
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* echo $des->decrypt($des->encrypt($plaintext));
|
* echo $des->decrypt($des->encrypt($plaintext));
|
||||||
* ?>
|
* ?>
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* @category Crypt
|
* @category Crypt
|
||||||
* @package Crypt_TripleDES
|
* @package Crypt_TripleDES
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @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
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Include Crypt_DES
|
* Include Crypt_DES
|
||||||
*/
|
*/
|
||||||
if (!class_exists('Crypt_DES')) {
|
if (!class_exists('Crypt_DES')) {
|
||||||
include_once 'DES.php';
|
include_once 'DES.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using inner chaining
|
* Encrypt / decrypt using inner chaining
|
||||||
*
|
*
|
||||||
* Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).
|
* Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).
|
||||||
*/
|
*/
|
||||||
define('CRYPT_DES_MODE_3CBC', -2);
|
define('CRYPT_DES_MODE_3CBC', -2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using outer chaining
|
* Encrypt / decrypt using outer chaining
|
||||||
*
|
*
|
||||||
* Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.
|
* Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.
|
||||||
*/
|
*/
|
||||||
define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC);
|
define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of Triple DES.
|
* Pure-PHP implementation of Triple DES.
|
||||||
*
|
*
|
||||||
* @package Crypt_TripleDES
|
* @package Crypt_TripleDES
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
class Crypt_TripleDES extends Crypt_DES
|
class Crypt_TripleDES extends Crypt_DES
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The default password key_size used by setPassword()
|
* The default password key_size used by setPassword()
|
||||||
*
|
*
|
||||||
* @see Crypt_DES::password_key_size
|
* @see Crypt_DES::password_key_size
|
||||||
* @see Crypt_Base::password_key_size
|
* @see Crypt_Base::password_key_size
|
||||||
* @see Crypt_Base::setPassword()
|
* @see Crypt_Base::setPassword()
|
||||||
* @var Integer
|
* @var Integer
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $password_key_size = 24;
|
var $password_key_size = 24;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default salt used by setPassword()
|
* The default salt used by setPassword()
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::password_default_salt
|
* @see Crypt_Base::password_default_salt
|
||||||
* @see Crypt_Base::setPassword()
|
* @see Crypt_Base::setPassword()
|
||||||
* @var String
|
* @var String
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $password_default_salt = 'phpseclib';
|
var $password_default_salt = 'phpseclib';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The namespace used by the cipher for its constants.
|
* The namespace used by the cipher for its constants.
|
||||||
*
|
*
|
||||||
* @see Crypt_DES::const_namespace
|
* @see Crypt_DES::const_namespace
|
||||||
* @see Crypt_Base::const_namespace
|
* @see Crypt_Base::const_namespace
|
||||||
* @var String
|
* @var String
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $const_namespace = 'DES';
|
var $const_namespace = 'DES';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mcrypt specific name of the cipher
|
* The mcrypt specific name of the cipher
|
||||||
*
|
*
|
||||||
* @see Crypt_DES::cipher_name_mcrypt
|
* @see Crypt_DES::cipher_name_mcrypt
|
||||||
* @see Crypt_Base::cipher_name_mcrypt
|
* @see Crypt_Base::cipher_name_mcrypt
|
||||||
* @var String
|
* @var String
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $cipher_name_mcrypt = 'tripledes';
|
var $cipher_name_mcrypt = 'tripledes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimizing value while CFB-encrypting
|
* Optimizing value while CFB-encrypting
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::cfb_init_len
|
* @see Crypt_Base::cfb_init_len
|
||||||
* @var Integer
|
* @var Integer
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $cfb_init_len = 750;
|
var $cfb_init_len = 750;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* max possible size of $key
|
* max possible size of $key
|
||||||
*
|
*
|
||||||
* @see Crypt_TripleDES::setKey()
|
* @see Crypt_TripleDES::setKey()
|
||||||
* @see Crypt_DES::setKey()
|
* @see Crypt_DES::setKey()
|
||||||
* @var String
|
* @var String
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $key_size_max = 24;
|
var $key_size_max = 24;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal flag whether using CRYPT_DES_MODE_3CBC or not
|
* Internal flag whether using CRYPT_DES_MODE_3CBC or not
|
||||||
*
|
*
|
||||||
* @var Boolean
|
* @var Boolean
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $mode_3cbc;
|
var $mode_3cbc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Crypt_DES objects
|
* The Crypt_DES objects
|
||||||
*
|
*
|
||||||
* Used only if $mode_3cbc === true
|
* Used only if $mode_3cbc === true
|
||||||
*
|
*
|
||||||
* @var Array
|
* @var Array
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $des;
|
var $des;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
* Determines whether or not the mcrypt extension should be used.
|
* Determines whether or not the mcrypt extension should be used.
|
||||||
*
|
*
|
||||||
* $mode could be:
|
* $mode could be:
|
||||||
*
|
*
|
||||||
* - CRYPT_DES_MODE_ECB
|
* - CRYPT_DES_MODE_ECB
|
||||||
*
|
*
|
||||||
* - CRYPT_DES_MODE_CBC
|
* - CRYPT_DES_MODE_CBC
|
||||||
*
|
*
|
||||||
* - CRYPT_DES_MODE_CTR
|
* - CRYPT_DES_MODE_CTR
|
||||||
*
|
*
|
||||||
* - CRYPT_DES_MODE_CFB
|
* - CRYPT_DES_MODE_CFB
|
||||||
*
|
*
|
||||||
* - CRYPT_DES_MODE_OFB
|
* - CRYPT_DES_MODE_OFB
|
||||||
*
|
*
|
||||||
* - CRYPT_DES_MODE_3CBC
|
* - CRYPT_DES_MODE_3CBC
|
||||||
*
|
*
|
||||||
* If not explicitly set, CRYPT_DES_MODE_CBC will be used.
|
* If not explicitly set, CRYPT_DES_MODE_CBC will be used.
|
||||||
*
|
*
|
||||||
* @see Crypt_DES::Crypt_DES()
|
* @see Crypt_DES::Crypt_DES()
|
||||||
* @see Crypt_Base::Crypt_Base()
|
* @see Crypt_Base::Crypt_Base()
|
||||||
* @param optional Integer $mode
|
* @param optional Integer $mode
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function Crypt_TripleDES($mode = CRYPT_DES_MODE_CBC)
|
function Crypt_TripleDES($mode = CRYPT_DES_MODE_CBC)
|
||||||
{
|
{
|
||||||
switch ($mode) {
|
switch ($mode) {
|
||||||
// In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC
|
// In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC
|
||||||
// and additional flag us internally as 3CBC
|
// and additional flag us internally as 3CBC
|
||||||
case CRYPT_DES_MODE_3CBC:
|
case CRYPT_DES_MODE_3CBC:
|
||||||
parent::Crypt_Base(CRYPT_DES_MODE_CBC);
|
parent::Crypt_Base(CRYPT_DES_MODE_CBC);
|
||||||
$this->mode_3cbc = true;
|
$this->mode_3cbc = true;
|
||||||
|
|
||||||
// This three $des'es will do the 3CBC work (if $key > 64bits)
|
// This three $des'es will do the 3CBC work (if $key > 64bits)
|
||||||
$this->des = array(
|
$this->des = array(
|
||||||
new Crypt_DES(CRYPT_DES_MODE_CBC),
|
new Crypt_DES(CRYPT_DES_MODE_CBC),
|
||||||
new Crypt_DES(CRYPT_DES_MODE_CBC),
|
new Crypt_DES(CRYPT_DES_MODE_CBC),
|
||||||
new Crypt_DES(CRYPT_DES_MODE_CBC),
|
new Crypt_DES(CRYPT_DES_MODE_CBC),
|
||||||
);
|
);
|
||||||
|
|
||||||
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
|
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
|
||||||
$this->des[0]->disablePadding();
|
$this->des[0]->disablePadding();
|
||||||
$this->des[1]->disablePadding();
|
$this->des[1]->disablePadding();
|
||||||
$this->des[2]->disablePadding();
|
$this->des[2]->disablePadding();
|
||||||
break;
|
break;
|
||||||
// If not 3CBC, we init as usual
|
// If not 3CBC, we init as usual
|
||||||
default:
|
default:
|
||||||
parent::Crypt_Base($mode);
|
parent::Crypt_Base($mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the initialization vector. (optional)
|
* Sets the initialization vector. (optional)
|
||||||
*
|
*
|
||||||
* SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explicitly set, it'll be assumed
|
* SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explicitly set, it'll be assumed
|
||||||
* to be all zero's.
|
* to be all zero's.
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::setIV()
|
* @see Crypt_Base::setIV()
|
||||||
* @access public
|
* @access public
|
||||||
* @param String $iv
|
* @param String $iv
|
||||||
*/
|
*/
|
||||||
function setIV($iv)
|
function setIV($iv)
|
||||||
{
|
{
|
||||||
parent::setIV($iv);
|
parent::setIV($iv);
|
||||||
if ($this->mode_3cbc) {
|
if ($this->mode_3cbc) {
|
||||||
$this->des[0]->setIV($iv);
|
$this->des[0]->setIV($iv);
|
||||||
$this->des[1]->setIV($iv);
|
$this->des[1]->setIV($iv);
|
||||||
$this->des[2]->setIV($iv);
|
$this->des[2]->setIV($iv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the key.
|
* Sets the key.
|
||||||
*
|
*
|
||||||
* Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
|
* Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
|
||||||
* 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
|
* 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
|
||||||
*
|
*
|
||||||
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
||||||
*
|
*
|
||||||
* If the key is not explicitly set, it'll be assumed to be all null bytes.
|
* If the key is not explicitly set, it'll be assumed to be all null bytes.
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @see Crypt_DES::setKey()
|
* @see Crypt_DES::setKey()
|
||||||
* @see Crypt_Base::setKey()
|
* @see Crypt_Base::setKey()
|
||||||
* @param String $key
|
* @param String $key
|
||||||
*/
|
*/
|
||||||
function setKey($key)
|
function setKey($key)
|
||||||
{
|
{
|
||||||
$length = strlen($key);
|
$length = strlen($key);
|
||||||
if ($length > 8) {
|
if ($length > 8) {
|
||||||
$key = str_pad(substr($key, 0, 24), 24, chr(0));
|
$key = str_pad(substr($key, 0, 24), 24, chr(0));
|
||||||
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
|
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
|
||||||
// http://php.net/function.mcrypt-encrypt#47973
|
// http://php.net/function.mcrypt-encrypt#47973
|
||||||
//$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
|
//$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
|
||||||
} else {
|
} else {
|
||||||
$key = str_pad($key, 8, chr(0));
|
$key = str_pad($key, 8, chr(0));
|
||||||
}
|
}
|
||||||
parent::setKey($key);
|
parent::setKey($key);
|
||||||
|
|
||||||
// And in case of CRYPT_DES_MODE_3CBC:
|
// And in case of CRYPT_DES_MODE_3CBC:
|
||||||
// if key <= 64bits we not need the 3 $des to work,
|
// if key <= 64bits we not need the 3 $des to work,
|
||||||
// because we will then act as regular DES-CBC with just a <= 64bit key.
|
// because we will then act as regular DES-CBC with just a <= 64bit key.
|
||||||
// So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des.
|
// So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des.
|
||||||
if ($this->mode_3cbc && $length > 8) {
|
if ($this->mode_3cbc && $length > 8) {
|
||||||
$this->des[0]->setKey(substr($key, 0, 8));
|
$this->des[0]->setKey(substr($key, 0, 8));
|
||||||
$this->des[1]->setKey(substr($key, 8, 8));
|
$this->des[1]->setKey(substr($key, 8, 8));
|
||||||
$this->des[2]->setKey(substr($key, 16, 8));
|
$this->des[2]->setKey(substr($key, 16, 8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts a message.
|
* Encrypts a message.
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::encrypt()
|
* @see Crypt_Base::encrypt()
|
||||||
* @access public
|
* @access public
|
||||||
* @param String $plaintext
|
* @param String $plaintext
|
||||||
* @return String $cipertext
|
* @return String $cipertext
|
||||||
*/
|
*/
|
||||||
function encrypt($plaintext)
|
function encrypt($plaintext)
|
||||||
{
|
{
|
||||||
// parent::en/decrypt() is able to do all the work for all modes and keylengths,
|
// parent::en/decrypt() is able to do all the work for all modes and keylengths,
|
||||||
// except for: CRYPT_DES_MODE_3CBC (inner chaining CBC) with a key > 64bits
|
// except for: CRYPT_DES_MODE_3CBC (inner chaining CBC) with a key > 64bits
|
||||||
|
|
||||||
// if the key is smaller then 8, do what we'd normally do
|
// if the key is smaller then 8, do what we'd normally do
|
||||||
if ($this->mode_3cbc && strlen($this->key) > 8) {
|
if ($this->mode_3cbc && strlen($this->key) > 8) {
|
||||||
return $this->des[2]->encrypt(
|
return $this->des[2]->encrypt(
|
||||||
$this->des[1]->decrypt(
|
$this->des[1]->decrypt(
|
||||||
$this->des[0]->encrypt(
|
$this->des[0]->encrypt(
|
||||||
$this->_pad($plaintext)
|
$this->_pad($plaintext)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::encrypt($plaintext);
|
return parent::encrypt($plaintext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts a message.
|
* Decrypts a message.
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::decrypt()
|
* @see Crypt_Base::decrypt()
|
||||||
* @access public
|
* @access public
|
||||||
* @param String $ciphertext
|
* @param String $ciphertext
|
||||||
* @return String $plaintext
|
* @return String $plaintext
|
||||||
*/
|
*/
|
||||||
function decrypt($ciphertext)
|
function decrypt($ciphertext)
|
||||||
{
|
{
|
||||||
if ($this->mode_3cbc && strlen($this->key) > 8) {
|
if ($this->mode_3cbc && strlen($this->key) > 8) {
|
||||||
return $this->_unpad(
|
return $this->_unpad(
|
||||||
$this->des[0]->decrypt(
|
$this->des[0]->decrypt(
|
||||||
$this->des[1]->encrypt(
|
$this->des[1]->encrypt(
|
||||||
$this->des[2]->decrypt(
|
$this->des[2]->decrypt(
|
||||||
str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0")
|
str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::decrypt($ciphertext);
|
return parent::decrypt($ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Treat consecutive "packets" as if they are a continuous buffer.
|
* Treat consecutive "packets" as if they are a continuous buffer.
|
||||||
*
|
*
|
||||||
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
|
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
|
||||||
* will yield different outputs:
|
* will yield different outputs:
|
||||||
*
|
*
|
||||||
* <code>
|
* <code>
|
||||||
* echo $des->encrypt(substr($plaintext, 0, 8));
|
* echo $des->encrypt(substr($plaintext, 0, 8));
|
||||||
* echo $des->encrypt(substr($plaintext, 8, 8));
|
* echo $des->encrypt(substr($plaintext, 8, 8));
|
||||||
* </code>
|
* </code>
|
||||||
* <code>
|
* <code>
|
||||||
* echo $des->encrypt($plaintext);
|
* echo $des->encrypt($plaintext);
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
|
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
|
||||||
* another, as demonstrated with the following:
|
* another, as demonstrated with the following:
|
||||||
*
|
*
|
||||||
* <code>
|
* <code>
|
||||||
* $des->encrypt(substr($plaintext, 0, 8));
|
* $des->encrypt(substr($plaintext, 0, 8));
|
||||||
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
||||||
* </code>
|
* </code>
|
||||||
* <code>
|
* <code>
|
||||||
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
|
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
|
||||||
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
|
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
|
||||||
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
|
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
|
||||||
*
|
*
|
||||||
* Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
|
* Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
|
||||||
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
|
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
|
||||||
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
|
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
|
||||||
* however, they are also less intuitive and more likely to cause you problems.
|
* however, they are also less intuitive and more likely to cause you problems.
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::enableContinuousBuffer()
|
* @see Crypt_Base::enableContinuousBuffer()
|
||||||
* @see Crypt_TripleDES::disableContinuousBuffer()
|
* @see Crypt_TripleDES::disableContinuousBuffer()
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function enableContinuousBuffer()
|
function enableContinuousBuffer()
|
||||||
{
|
{
|
||||||
parent::enableContinuousBuffer();
|
parent::enableContinuousBuffer();
|
||||||
if ($this->mode_3cbc) {
|
if ($this->mode_3cbc) {
|
||||||
$this->des[0]->enableContinuousBuffer();
|
$this->des[0]->enableContinuousBuffer();
|
||||||
$this->des[1]->enableContinuousBuffer();
|
$this->des[1]->enableContinuousBuffer();
|
||||||
$this->des[2]->enableContinuousBuffer();
|
$this->des[2]->enableContinuousBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Treat consecutive packets as if they are a discontinuous buffer.
|
* Treat consecutive packets as if they are a discontinuous buffer.
|
||||||
*
|
*
|
||||||
* The default behavior.
|
* The default behavior.
|
||||||
*
|
*
|
||||||
* @see Crypt_Base::disableContinuousBuffer()
|
* @see Crypt_Base::disableContinuousBuffer()
|
||||||
* @see Crypt_TripleDES::enableContinuousBuffer()
|
* @see Crypt_TripleDES::enableContinuousBuffer()
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function disableContinuousBuffer()
|
function disableContinuousBuffer()
|
||||||
{
|
{
|
||||||
parent::disableContinuousBuffer();
|
parent::disableContinuousBuffer();
|
||||||
if ($this->mode_3cbc) {
|
if ($this->mode_3cbc) {
|
||||||
$this->des[0]->disableContinuousBuffer();
|
$this->des[0]->disableContinuousBuffer();
|
||||||
$this->des[1]->disableContinuousBuffer();
|
$this->des[1]->disableContinuousBuffer();
|
||||||
$this->des[2]->disableContinuousBuffer();
|
$this->des[2]->disableContinuousBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the key schedule
|
* Creates the key schedule
|
||||||
*
|
*
|
||||||
* @see Crypt_DES::_setupKey()
|
* @see Crypt_DES::_setupKey()
|
||||||
* @see Crypt_Base::_setupKey()
|
* @see Crypt_Base::_setupKey()
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _setupKey()
|
function _setupKey()
|
||||||
{
|
{
|
||||||
switch (true) {
|
switch (true) {
|
||||||
// if $key <= 64bits we configure our internal pure-php cipher engine
|
// if $key <= 64bits we configure our internal pure-php cipher engine
|
||||||
// to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same.
|
// to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same.
|
||||||
case strlen($this->key) <= 8:
|
case strlen($this->key) <= 8:
|
||||||
$this->des_rounds = 1;
|
$this->des_rounds = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// otherwise, if $key > 64bits, we configure our engine to work as 3DES.
|
// otherwise, if $key > 64bits, we configure our engine to work as 3DES.
|
||||||
default:
|
default:
|
||||||
$this->des_rounds = 3;
|
$this->des_rounds = 3;
|
||||||
|
|
||||||
// (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately.
|
// (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately.
|
||||||
if ($this->mode_3cbc) {
|
if ($this->mode_3cbc) {
|
||||||
$this->des[0]->_setupKey();
|
$this->des[0]->_setupKey();
|
||||||
$this->des[1]->_setupKey();
|
$this->des[1]->_setupKey();
|
||||||
$this->des[2]->_setupKey();
|
$this->des[2]->_setupKey();
|
||||||
|
|
||||||
// because $des[0-2] will, now, do all the work we can return here
|
// because $des[0-2] will, now, do all the work we can return here
|
||||||
// not need unnecessary stress parent::_setupKey() with our, now unused, $key.
|
// not need unnecessary stress parent::_setupKey() with our, now unused, $key.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// setup our key
|
// setup our key
|
||||||
parent::_setupKey();
|
parent::_setupKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,361 +1,360 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of SCP.
|
* Pure-PHP implementation of SCP.
|
||||||
*
|
*
|
||||||
* PHP versions 4 and 5
|
* PHP versions 4 and 5
|
||||||
*
|
*
|
||||||
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
|
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
|
||||||
*
|
*
|
||||||
* Here's a short example of how to use this library:
|
* Here's a short example of how to use this library:
|
||||||
* <code>
|
* <code>
|
||||||
* <?php
|
* <?php
|
||||||
* include 'Net/SCP.php';
|
* include 'Net/SCP.php';
|
||||||
* include 'Net/SSH2.php';
|
* include 'Net/SSH2.php';
|
||||||
*
|
*
|
||||||
* $ssh = new Net_SSH2('www.domain.tld');
|
* $ssh = new Net_SSH2('www.domain.tld');
|
||||||
* if (!$ssh->login('username', 'password')) {
|
* if (!$ssh->login('username', 'password')) {
|
||||||
* exit('bad login');
|
* exit('bad login');
|
||||||
* }
|
* }
|
||||||
|
|
||||||
* $scp = new Net_SCP($ssh);
|
* $scp = new Net_SCP($ssh);
|
||||||
* $scp->put('abcd', str_repeat('x', 1024*1024));
|
* $scp->put('abcd', str_repeat('x', 1024*1024));
|
||||||
* ?>
|
* ?>
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* @category Net
|
* @category Net
|
||||||
* @package Net_SCP
|
* @package Net_SCP
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @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
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
* @access public
|
* @access public
|
||||||
* @see Net_SCP::put()
|
* @see Net_SCP::put()
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Reads data from a local file.
|
* Reads data from a local file.
|
||||||
*/
|
*/
|
||||||
define('NET_SCP_LOCAL_FILE', 1);
|
define('NET_SCP_LOCAL_FILE', 1);
|
||||||
/**
|
/**
|
||||||
* Reads data from a string.
|
* Reads data from a string.
|
||||||
*/
|
*/
|
||||||
define('NET_SCP_STRING', 2);
|
define('NET_SCP_STRING', 2);
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
* @access private
|
* @access private
|
||||||
* @see Net_SCP::_send()
|
* @see Net_SCP::_send()
|
||||||
* @see Net_SCP::_receive()
|
* @see Net_SCP::_receive()
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* SSH1 is being used.
|
* SSH1 is being used.
|
||||||
*/
|
*/
|
||||||
define('NET_SCP_SSH1', 1);
|
define('NET_SCP_SSH1', 1);
|
||||||
/**
|
/**
|
||||||
* SSH2 is being used.
|
* SSH2 is being used.
|
||||||
*/
|
*/
|
||||||
define('NET_SCP_SSH2', 2);
|
define('NET_SCP_SSH2', 2);
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementations of SCP.
|
* Pure-PHP implementations of SCP.
|
||||||
*
|
*
|
||||||
* @package Net_SCP
|
* @package Net_SCP
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
class Net_SCP
|
class Net_SCP
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* SSH Object
|
* SSH Object
|
||||||
*
|
*
|
||||||
* @var Object
|
* @var Object
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $ssh;
|
var $ssh;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Packet Size
|
* Packet Size
|
||||||
*
|
*
|
||||||
* @var Integer
|
* @var Integer
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $packet_size;
|
var $packet_size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mode
|
* Mode
|
||||||
*
|
*
|
||||||
* @var Integer
|
* @var Integer
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $mode;
|
var $mode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
* Connects to an SSH server
|
* Connects to an SSH server
|
||||||
*
|
*
|
||||||
* @param String $host
|
* @param String $host
|
||||||
* @param optional Integer $port
|
* @param optional Integer $port
|
||||||
* @param optional Integer $timeout
|
* @param optional Integer $timeout
|
||||||
* @return Net_SCP
|
* @return Net_SCP
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function Net_SCP($ssh)
|
function Net_SCP($ssh)
|
||||||
{
|
{
|
||||||
if (!is_object($ssh)) {
|
if (!is_object($ssh)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (strtolower(get_class($ssh))) {
|
switch (strtolower(get_class($ssh))) {
|
||||||
case'net_ssh2':
|
case 'net_ssh2':
|
||||||
$this->mode = NET_SCP_SSH2;
|
$this->mode = NET_SCP_SSH2;
|
||||||
break;
|
break;
|
||||||
case 'net_ssh1':
|
case 'net_ssh1':
|
||||||
$this->packet_size = 50000;
|
$this->packet_size = 50000;
|
||||||
$this->mode = NET_SCP_SSH1;
|
$this->mode = NET_SCP_SSH1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->ssh = $ssh;
|
$this->ssh = $ssh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uploads a file to the SCP server.
|
* Uploads a file to the SCP server.
|
||||||
*
|
*
|
||||||
* By default, Net_SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
|
* By default, Net_SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
|
||||||
* So, for example, if you set $data to 'filename.ext' and then do Net_SCP::get(), you will get a file, twelve bytes
|
* So, for example, if you set $data to 'filename.ext' and then do Net_SCP::get(), you will get a file, twelve bytes
|
||||||
* long, containing 'filename.ext' as its contents.
|
* long, containing 'filename.ext' as its contents.
|
||||||
*
|
*
|
||||||
* Setting $mode to NET_SCP_LOCAL_FILE will change the above behavior. With NET_SCP_LOCAL_FILE, $remote_file will
|
* Setting $mode to NET_SCP_LOCAL_FILE will change the above behavior. With NET_SCP_LOCAL_FILE, $remote_file will
|
||||||
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
|
* 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.
|
* large $remote_file will be, as well.
|
||||||
*
|
*
|
||||||
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
|
* 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.
|
* care of that, yourself.
|
||||||
*
|
*
|
||||||
* @param String $remote_file
|
* @param String $remote_file
|
||||||
* @param String $data
|
* @param String $data
|
||||||
* @param optional Integer $mode
|
* @param optional Integer $mode
|
||||||
* @param optional Callable $callback
|
* @param optional Callable $callback
|
||||||
* @return Boolean
|
* @return Boolean
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function put($remote_file, $data, $mode = NET_SCP_STRING, $callback = null)
|
function put($remote_file, $data, $mode = NET_SCP_STRING, $callback = null)
|
||||||
{
|
{
|
||||||
if (!isset($this->ssh)) {
|
if (!isset($this->ssh)) {
|
||||||
return false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$temp = $this->_receive();
|
$temp = $this->_receive();
|
||||||
if ($temp !== chr(0)) {
|
if ($temp !== chr(0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->mode == NET_SCP_SSH2) {
|
if ($this->mode == NET_SCP_SSH2) {
|
||||||
$this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC] - 4;
|
$this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC] - 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
$remote_file = basename($remote_file);
|
$remote_file = basename($remote_file);
|
||||||
|
|
||||||
if ($mode == NET_SCP_STRING) {
|
if ($mode == NET_SCP_STRING) {
|
||||||
$size = strlen($data);
|
$size = strlen($data);
|
||||||
} else {
|
} else {
|
||||||
if (!is_file($data)) {
|
if (!is_file($data)) {
|
||||||
user_error("$data is not a valid file", E_USER_NOTICE);
|
user_error("$data is not a valid file", E_USER_NOTICE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$fp = @fopen($data, 'rb');
|
$fp = @fopen($data, 'rb');
|
||||||
if (!$fp) {
|
if (!$fp) {
|
||||||
fclose($fp);
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
$size = filesize($data);
|
||||||
$size = filesize($data);
|
}
|
||||||
}
|
|
||||||
|
$this->_send('C0644 ' . $size . ' ' . $remote_file . "\n");
|
||||||
$this->_send('C0644 ' . $size . ' ' . $remote_file . "\n");
|
|
||||||
|
$temp = $this->_receive();
|
||||||
$temp = $this->_receive();
|
if ($temp !== chr(0)) {
|
||||||
if ($temp !== chr(0)) {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
$sent = 0;
|
||||||
$sent = 0;
|
while ($sent < $size) {
|
||||||
while ($sent < $size) {
|
$temp = $mode & NET_SCP_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
|
||||||
$temp = $mode & NET_SCP_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
|
$this->_send($temp);
|
||||||
$this->_send($temp);
|
$sent+= strlen($temp);
|
||||||
$sent+= strlen($temp);
|
|
||||||
|
if (is_callable($callback)) {
|
||||||
if (is_callable($callback)) {
|
call_user_func($callback, $sent);
|
||||||
call_user_func($callback, $sent);
|
}
|
||||||
}
|
}
|
||||||
}
|
$this->_close();
|
||||||
$this->_close();
|
|
||||||
|
if ($mode != NET_SCP_STRING) {
|
||||||
if ($mode != NET_SCP_STRING) {
|
fclose($fp);
|
||||||
fclose($fp);
|
}
|
||||||
}
|
|
||||||
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Downloads a file from the SCP server.
|
||||||
* Downloads a file from the SCP server.
|
*
|
||||||
*
|
* Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
|
||||||
* Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
|
* the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
|
||||||
* the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
|
* operation
|
||||||
* operation
|
*
|
||||||
*
|
* @param String $remote_file
|
||||||
* @param String $remote_file
|
* @param optional String $local_file
|
||||||
* @param optional String $local_file
|
* @return Mixed
|
||||||
* @return Mixed
|
* @access public
|
||||||
* @access public
|
*/
|
||||||
*/
|
function get($remote_file, $local_file = false)
|
||||||
function get($remote_file, $local_file = false)
|
{
|
||||||
{
|
if (!isset($this->ssh)) {
|
||||||
if (!isset($this->ssh)) {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
if (!$this->ssh->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from
|
||||||
if (!$this->ssh->exec('scp -f "' . $remote_file . '"', false)) { // -f = from
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
$this->_send("\0");
|
||||||
$this->_send("\0");
|
|
||||||
|
if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
|
||||||
if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
$this->_send("\0");
|
||||||
$this->_send("\0");
|
|
||||||
|
$size = 0;
|
||||||
$size = 0;
|
|
||||||
|
if ($local_file !== false) {
|
||||||
if ($local_file !== false) {
|
$fp = @fopen($local_file, 'wb');
|
||||||
$fp = @fopen($local_file, 'wb');
|
if (!$fp) {
|
||||||
if (!$fp) {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
$content = '';
|
||||||
$content = '';
|
while ($size < $info['size']) {
|
||||||
while ($size < $info['size']) {
|
$data = $this->_receive();
|
||||||
$data = $this->_receive();
|
// SCP usually seems to split stuff out into 16k chunks
|
||||||
// SCP usually seems to split stuff out into 16k chunks
|
$size+= strlen($data);
|
||||||
$size+= strlen($data);
|
|
||||||
|
if ($local_file === false) {
|
||||||
if ($local_file === false) {
|
$content.= $data;
|
||||||
$content.= $data;
|
} else {
|
||||||
} else {
|
fputs($fp, $data);
|
||||||
fputs($fp, $data);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
$this->_close();
|
||||||
$this->_close();
|
|
||||||
|
if ($local_file !== false) {
|
||||||
if ($local_file !== false) {
|
fclose($fp);
|
||||||
fclose($fp);
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
return $content;
|
||||||
return $content;
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Sends a packet to an SSH server
|
||||||
* Sends a packet to an SSH server
|
*
|
||||||
*
|
* @param String $data
|
||||||
* @param String $data
|
* @access private
|
||||||
* @access private
|
*/
|
||||||
*/
|
function _send($data)
|
||||||
function _send($data)
|
{
|
||||||
{
|
switch ($this->mode) {
|
||||||
switch ($this->mode) {
|
case NET_SCP_SSH2:
|
||||||
case NET_SCP_SSH2:
|
$this->ssh->_send_channel_packet(NET_SSH2_CHANNEL_EXEC, $data);
|
||||||
$this->ssh->_send_channel_packet(NET_SSH2_CHANNEL_EXEC, $data);
|
break;
|
||||||
break;
|
case NET_SCP_SSH1:
|
||||||
case NET_SCP_SSH1:
|
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
|
||||||
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
|
$this->ssh->_send_binary_packet($data);
|
||||||
$this->ssh->_send_binary_packet($data);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Receives a packet from an SSH server
|
||||||
* Receives a packet from an SSH server
|
*
|
||||||
*
|
* @return String
|
||||||
* @return String
|
* @access private
|
||||||
* @access private
|
*/
|
||||||
*/
|
function _receive()
|
||||||
function _receive()
|
{
|
||||||
{
|
switch ($this->mode) {
|
||||||
switch ($this->mode) {
|
case NET_SCP_SSH2:
|
||||||
case NET_SCP_SSH2:
|
return $this->ssh->_get_channel_packet(NET_SSH2_CHANNEL_EXEC, true);
|
||||||
return $this->ssh->_get_channel_packet(NET_SSH2_CHANNEL_EXEC, true);
|
case NET_SCP_SSH1:
|
||||||
case NET_SCP_SSH1:
|
if (!$this->ssh->bitmap) {
|
||||||
if (!$this->ssh->bitmap) {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
while (true) {
|
||||||
while (true) {
|
$response = $this->ssh->_get_binary_packet();
|
||||||
$response = $this->ssh->_get_binary_packet();
|
switch ($response[NET_SSH1_RESPONSE_TYPE]) {
|
||||||
switch ($response[NET_SSH1_RESPONSE_TYPE]) {
|
case NET_SSH1_SMSG_STDOUT_DATA:
|
||||||
case NET_SSH1_SMSG_STDOUT_DATA:
|
extract(unpack('Nlength', $response[NET_SSH1_RESPONSE_DATA]));
|
||||||
extract(unpack('Nlength', $response[NET_SSH1_RESPONSE_DATA]));
|
return $this->ssh->_string_shift($response[NET_SSH1_RESPONSE_DATA], $length);
|
||||||
return $this->ssh->_string_shift($response[NET_SSH1_RESPONSE_DATA], $length);
|
case NET_SSH1_SMSG_STDERR_DATA:
|
||||||
case NET_SSH1_SMSG_STDERR_DATA:
|
break;
|
||||||
break;
|
case NET_SSH1_SMSG_EXITSTATUS:
|
||||||
case NET_SSH1_SMSG_EXITSTATUS:
|
$this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION));
|
||||||
$this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION));
|
fclose($this->ssh->fsock);
|
||||||
fclose($this->ssh->fsock);
|
$this->ssh->bitmap = 0;
|
||||||
$this->ssh->bitmap = 0;
|
return false;
|
||||||
return false;
|
default:
|
||||||
default:
|
user_error('Unknown packet received', E_USER_NOTICE);
|
||||||
user_error('Unknown packet received', E_USER_NOTICE);
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Closes the connection to an SSH server
|
||||||
* Closes the connection to an SSH server
|
*
|
||||||
*
|
* @access private
|
||||||
* @access private
|
*/
|
||||||
*/
|
function _close()
|
||||||
function _close()
|
{
|
||||||
{
|
switch ($this->mode) {
|
||||||
switch ($this->mode) {
|
case NET_SCP_SSH2:
|
||||||
case NET_SCP_SSH2:
|
$this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC, true);
|
||||||
$this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC, true);
|
break;
|
||||||
break;
|
case NET_SCP_SSH1:
|
||||||
case NET_SCP_SSH1:
|
$this->ssh->disconnect();
|
||||||
$this->ssh->disconnect();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,313 +1,313 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Pure-PHP ssh-agent client.
|
* Pure-PHP ssh-agent client.
|
||||||
*
|
*
|
||||||
* PHP versions 4 and 5
|
* PHP versions 4 and 5
|
||||||
*
|
*
|
||||||
* Here are some examples of how to use this library:
|
* Here are some examples of how to use this library:
|
||||||
* <code>
|
* <code>
|
||||||
* <?php
|
* <?php
|
||||||
* include 'System/SSH/Agent.php';
|
* include 'System/SSH/Agent.php';
|
||||||
* include 'Net/SSH2.php';
|
* include 'Net/SSH2.php';
|
||||||
*
|
*
|
||||||
* $agent = new System_SSH_Agent();
|
* $agent = new System_SSH_Agent();
|
||||||
*
|
*
|
||||||
* $ssh = new Net_SSH2('www.domain.tld');
|
* $ssh = new Net_SSH2('www.domain.tld');
|
||||||
* if (!$ssh->login('username', $agent)) {
|
* if (!$ssh->login('username', $agent)) {
|
||||||
* exit('Login Failed');
|
* exit('Login Failed');
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* echo $ssh->exec('pwd');
|
* echo $ssh->exec('pwd');
|
||||||
* echo $ssh->exec('ls -la');
|
* echo $ssh->exec('ls -la');
|
||||||
* ?>
|
* ?>
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* @category System
|
* @category System
|
||||||
* @package System_SSH_Agent
|
* @package System_SSH_Agent
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @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
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
|
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
* Message numbers
|
* Message numbers
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
// to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
|
// to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
|
||||||
define('SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES', 11);
|
define('SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES', 11);
|
||||||
// this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
|
// this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
|
||||||
define('SYSTEM_SSH_AGENT_IDENTITIES_ANSWER', 12);
|
define('SYSTEM_SSH_AGENT_IDENTITIES_ANSWER', 12);
|
||||||
define('SYSTEM_SSH_AGENT_FAILURE', 5);
|
define('SYSTEM_SSH_AGENT_FAILURE', 5);
|
||||||
// the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
|
// the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
|
||||||
define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13);
|
define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13);
|
||||||
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
|
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
|
||||||
define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14);
|
define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14);
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP ssh-agent client identity object
|
* Pure-PHP ssh-agent client identity object
|
||||||
*
|
*
|
||||||
* Instantiation should only be performed by System_SSH_Agent class.
|
* Instantiation should only be performed by System_SSH_Agent class.
|
||||||
* This could be thought of as implementing an interface that Crypt_RSA
|
* This could be thought of as implementing an interface that Crypt_RSA
|
||||||
* implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
|
* implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
|
||||||
* The methods in this interface would be getPublicKey, setSignatureMode
|
* The methods in this interface would be getPublicKey, setSignatureMode
|
||||||
* and sign since those are the methods phpseclib looks for to perform
|
* and sign since those are the methods phpseclib looks for to perform
|
||||||
* public key authentication.
|
* public key authentication.
|
||||||
*
|
*
|
||||||
* @package System_SSH_Agent
|
* @package System_SSH_Agent
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @access internal
|
* @access internal
|
||||||
*/
|
*/
|
||||||
class System_SSH_Agent_Identity
|
class System_SSH_Agent_Identity
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Key Object
|
* Key Object
|
||||||
*
|
*
|
||||||
* @var Crypt_RSA
|
* @var Crypt_RSA
|
||||||
* @access private
|
* @access private
|
||||||
* @see System_SSH_Agent_Identity::getPublicKey()
|
* @see System_SSH_Agent_Identity::getPublicKey()
|
||||||
*/
|
*/
|
||||||
var $key;
|
var $key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key Blob
|
* Key Blob
|
||||||
*
|
*
|
||||||
* @var String
|
* @var String
|
||||||
* @access private
|
* @access private
|
||||||
* @see System_SSH_Agent_Identity::sign()
|
* @see System_SSH_Agent_Identity::sign()
|
||||||
*/
|
*/
|
||||||
var $key_blob;
|
var $key_blob;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket Resource
|
* Socket Resource
|
||||||
*
|
*
|
||||||
* @var Resource
|
* @var Resource
|
||||||
* @access private
|
* @access private
|
||||||
* @see System_SSH_Agent_Identity::sign()
|
* @see System_SSH_Agent_Identity::sign()
|
||||||
*/
|
*/
|
||||||
var $fsock;
|
var $fsock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
* @param Resource $fsock
|
* @param Resource $fsock
|
||||||
* @return System_SSH_Agent_Identity
|
* @return System_SSH_Agent_Identity
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function System_SSH_Agent_Identity($fsock)
|
function System_SSH_Agent_Identity($fsock)
|
||||||
{
|
{
|
||||||
$this->fsock = $fsock;
|
$this->fsock = $fsock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set Public Key
|
* Set Public Key
|
||||||
*
|
*
|
||||||
* Called by System_SSH_Agent::requestIdentities()
|
* Called by System_SSH_Agent::requestIdentities()
|
||||||
*
|
*
|
||||||
* @param Crypt_RSA $key
|
* @param Crypt_RSA $key
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function setPublicKey($key)
|
function setPublicKey($key)
|
||||||
{
|
{
|
||||||
$this->key = $key;
|
$this->key = $key;
|
||||||
$this->key->setPublicKey();
|
$this->key->setPublicKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set Public Key
|
* Set Public Key
|
||||||
*
|
*
|
||||||
* Called by System_SSH_Agent::requestIdentities(). The key blob could be extracted from $this->key
|
* Called by System_SSH_Agent::requestIdentities(). The key blob could be extracted from $this->key
|
||||||
* but this saves a small amount of computation.
|
* but this saves a small amount of computation.
|
||||||
*
|
*
|
||||||
* @param String $key_blob
|
* @param String $key_blob
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function setPublicKeyBlob($key_blob)
|
function setPublicKeyBlob($key_blob)
|
||||||
{
|
{
|
||||||
$this->key_blob = $key_blob;
|
$this->key_blob = $key_blob;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Public Key
|
* Get Public Key
|
||||||
*
|
*
|
||||||
* Wrapper for $this->key->getPublicKey()
|
* Wrapper for $this->key->getPublicKey()
|
||||||
*
|
*
|
||||||
* @param Integer $format optional
|
* @param Integer $format optional
|
||||||
* @return Mixed
|
* @return Mixed
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function getPublicKey($format = null)
|
function getPublicKey($format = null)
|
||||||
{
|
{
|
||||||
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
|
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set Signature Mode
|
* Set Signature Mode
|
||||||
*
|
*
|
||||||
* Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie.
|
* Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie.
|
||||||
* ssh-agent's only supported mode is CRYPT_RSA_SIGNATURE_PKCS1
|
* ssh-agent's only supported mode is CRYPT_RSA_SIGNATURE_PKCS1
|
||||||
*
|
*
|
||||||
* @param Integer $mode
|
* @param Integer $mode
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function setSignatureMode($mode)
|
function setSignatureMode($mode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a signature
|
* Create a signature
|
||||||
*
|
*
|
||||||
* See "2.6.2 Protocol 2 private key signature request"
|
* See "2.6.2 Protocol 2 private key signature request"
|
||||||
*
|
*
|
||||||
* @param String $message
|
* @param String $message
|
||||||
* @return String
|
* @return String
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function sign($message)
|
function sign($message)
|
||||||
{
|
{
|
||||||
// the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
|
// the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
|
||||||
$packet = pack('CNa*Na*N', SYSTEM_SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0);
|
$packet = pack('CNa*Na*N', SYSTEM_SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0);
|
||||||
$packet = pack('Na*', strlen($packet), $packet);
|
$packet = pack('Na*', strlen($packet), $packet);
|
||||||
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
||||||
user_error('Connection closed during signing');
|
user_error('Connection closed during signing');
|
||||||
}
|
}
|
||||||
|
|
||||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||||
$type = ord(fread($this->fsock, 1));
|
$type = ord(fread($this->fsock, 1));
|
||||||
if ($type != SYSTEM_SSH_AGENT_SIGN_RESPONSE) {
|
if ($type != SYSTEM_SSH_AGENT_SIGN_RESPONSE) {
|
||||||
user_error('Unable to retreive signature');
|
user_error('Unable to retreive signature');
|
||||||
}
|
}
|
||||||
|
|
||||||
$signature_blob = fread($this->fsock, $length - 1);
|
$signature_blob = fread($this->fsock, $length - 1);
|
||||||
// the only other signature format defined - ssh-dss - is the same length as ssh-rsa
|
// the only other signature format defined - ssh-dss - is the same length as ssh-rsa
|
||||||
// the + 12 is for the other various SSH added length fields
|
// the + 12 is for the other various SSH added length fields
|
||||||
return substr($signature_blob, strlen('ssh-rsa') + 12);
|
return substr($signature_blob, strlen('ssh-rsa') + 12);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP ssh-agent client identity factory
|
* Pure-PHP ssh-agent client identity factory
|
||||||
*
|
*
|
||||||
* requestIdentities() method pumps out System_SSH_Agent_Identity objects
|
* requestIdentities() method pumps out System_SSH_Agent_Identity objects
|
||||||
*
|
*
|
||||||
* @package System_SSH_Agent
|
* @package System_SSH_Agent
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @access internal
|
* @access internal
|
||||||
*/
|
*/
|
||||||
class System_SSH_Agent
|
class System_SSH_Agent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Socket Resource
|
* Socket Resource
|
||||||
*
|
*
|
||||||
* @var Resource
|
* @var Resource
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $fsock;
|
var $fsock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor
|
* Default Constructor
|
||||||
*
|
*
|
||||||
* @return System_SSH_Agent
|
* @return System_SSH_Agent
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function System_SSH_Agent()
|
function System_SSH_Agent()
|
||||||
{
|
{
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case isset($_SERVER['SSH_AUTH_SOCK']):
|
case isset($_SERVER['SSH_AUTH_SOCK']):
|
||||||
$address = $_SERVER['SSH_AUTH_SOCK'];
|
$address = $_SERVER['SSH_AUTH_SOCK'];
|
||||||
break;
|
break;
|
||||||
case isset($_ENV['SSH_AUTH_SOCK']):
|
case isset($_ENV['SSH_AUTH_SOCK']):
|
||||||
$address = $_ENV['SSH_AUTH_SOCK'];
|
$address = $_ENV['SSH_AUTH_SOCK'];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
user_error('SSH_AUTH_SOCK not found');
|
user_error('SSH_AUTH_SOCK not found');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
|
$this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
|
||||||
if (!$this->fsock) {
|
if (!$this->fsock) {
|
||||||
user_error("Unable to connect to ssh-agent (Error $errno: $errstr)");
|
user_error("Unable to connect to ssh-agent (Error $errno: $errstr)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request Identities
|
* Request Identities
|
||||||
*
|
*
|
||||||
* See "2.5.2 Requesting a list of protocol 2 keys"
|
* See "2.5.2 Requesting a list of protocol 2 keys"
|
||||||
* Returns an array containing zero or more System_SSH_Agent_Identity objects
|
* Returns an array containing zero or more System_SSH_Agent_Identity objects
|
||||||
*
|
*
|
||||||
* @return Array
|
* @return Array
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function requestIdentities()
|
function requestIdentities()
|
||||||
{
|
{
|
||||||
if (!$this->fsock) {
|
if (!$this->fsock) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$packet = pack('NC', 1, SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES);
|
$packet = pack('NC', 1, SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES);
|
||||||
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
||||||
user_error('Connection closed while requesting identities');
|
user_error('Connection closed while requesting identities');
|
||||||
}
|
}
|
||||||
|
|
||||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||||
$type = ord(fread($this->fsock, 1));
|
$type = ord(fread($this->fsock, 1));
|
||||||
if ($type != SYSTEM_SSH_AGENT_IDENTITIES_ANSWER) {
|
if ($type != SYSTEM_SSH_AGENT_IDENTITIES_ANSWER) {
|
||||||
user_error('Unable to request identities');
|
user_error('Unable to request identities');
|
||||||
}
|
}
|
||||||
|
|
||||||
$identities = array();
|
$identities = array();
|
||||||
$keyCount = current(unpack('N', fread($this->fsock, 4)));
|
$keyCount = current(unpack('N', fread($this->fsock, 4)));
|
||||||
for ($i = 0; $i < $keyCount; $i++) {
|
for ($i = 0; $i < $keyCount; $i++) {
|
||||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||||
$key_blob = fread($this->fsock, $length);
|
$key_blob = fread($this->fsock, $length);
|
||||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||||
$key_comment = fread($this->fsock, $length);
|
$key_comment = fread($this->fsock, $length);
|
||||||
$length = current(unpack('N', substr($key_blob, 0, 4)));
|
$length = current(unpack('N', substr($key_blob, 0, 4)));
|
||||||
$key_type = substr($key_blob, 4, $length);
|
$key_type = substr($key_blob, 4, $length);
|
||||||
switch ($key_type) {
|
switch ($key_type) {
|
||||||
case 'ssh-rsa':
|
case 'ssh-rsa':
|
||||||
if (!class_exists('Crypt_RSA')) {
|
if (!class_exists('Crypt_RSA')) {
|
||||||
include_once 'Crypt/RSA.php';
|
include_once 'Crypt/RSA.php';
|
||||||
}
|
}
|
||||||
$key = new Crypt_RSA();
|
$key = new Crypt_RSA();
|
||||||
$key->loadKey('ssh-rsa ' . base64_encode($key_blob) . ' ' . $key_comment);
|
$key->loadKey('ssh-rsa ' . base64_encode($key_blob) . ' ' . $key_comment);
|
||||||
break;
|
break;
|
||||||
case 'ssh-dss':
|
case 'ssh-dss':
|
||||||
// not currently supported
|
// not currently supported
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// resources are passed by reference by default
|
// resources are passed by reference by default
|
||||||
if (isset($key)) {
|
if (isset($key)) {
|
||||||
$identity = new System_SSH_Agent_Identity($this->fsock);
|
$identity = new System_SSH_Agent_Identity($this->fsock);
|
||||||
$identity->setPublicKey($key);
|
$identity->setPublicKey($key);
|
||||||
$identity->setPublicKeyBlob($key_blob);
|
$identity->setPublicKeyBlob($key_blob);
|
||||||
$identities[] = $identity;
|
$identities[] = $identity;
|
||||||
unset($key);
|
unset($key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $identities;
|
return $identities;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,39 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Pure-PHP ssh-agent client wrapper
|
* Pure-PHP ssh-agent client wrapper
|
||||||
*
|
*
|
||||||
* PHP versions 4 and 5
|
* PHP versions 4 and 5
|
||||||
*
|
*
|
||||||
* Originally System_SSH_Agent was accessed as System/SSH_Agent.php instead of
|
* Originally System_SSH_Agent was accessed as System/SSH_Agent.php instead of
|
||||||
* System/SSH/Agent.php. The problem with this is that PSR0 compatible autoloaders
|
* System/SSH/Agent.php. The problem with this is that PSR0 compatible autoloaders
|
||||||
* don't support that kind of directory layout hence the package being moved and
|
* don't support that kind of directory layout hence the package being moved and
|
||||||
* this "alias" being created to maintain backwards compatibility.
|
* this "alias" being created to maintain backwards compatibility.
|
||||||
*
|
*
|
||||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
* @category System
|
* @category System
|
||||||
* @package System_SSH_Agent
|
* @package System_SSH_Agent
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @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
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
|
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once 'SSH/Agent.php';
|
require_once 'SSH/Agent.php';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# minimalist openssl.cnf file for use with phpseclib
|
# minimalist openssl.cnf file for use with phpseclib
|
||||||
|
|
||||||
HOME = .
|
HOME = .
|
||||||
RANDFILE = $ENV::HOME/.rnd
|
RANDFILE = $ENV::HOME/.rnd
|
||||||
|
|
||||||
[ v3_ca ]
|
[ v3_ca ]
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,13 @@
|
||||||
value: capaAdditionalAccounts
|
value: capaAdditionalAccounts
|
||||||
}
|
}
|
||||||
}"></div>
|
}"></div>
|
||||||
|
<div data-bind="component: {
|
||||||
|
name: 'Checkbox',
|
||||||
|
params: {
|
||||||
|
label: 'TAB_GENERAL/LABEL_ALLOW_IDENTITIES',
|
||||||
|
value: capaIdentities
|
||||||
|
}
|
||||||
|
}"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--
|
<!--
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,20 @@
|
||||||
<div class="legend">
|
<div class="legend">
|
||||||
<span class="i18n i18n-animation" data-i18n="SETTINGS_GENERAL/LEGEND_GENERAL"></span>
|
<span class="i18n i18n-animation" data-i18n="SETTINGS_GENERAL/LEGEND_GENERAL"></span>
|
||||||
</div>
|
</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">
|
<div class="control-group" data-bind="visible: allowLanguagesOnSettings">
|
||||||
<label class="control-label">
|
<label class="control-label">
|
||||||
<span class="i18n" data-i18n="SETTINGS_GENERAL/LABEL_LANGUAGE"></span>
|
<span class="i18n" data-i18n="SETTINGS_GENERAL/LABEL_LANGUAGE"></span>
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ LABEL_ALLOW_GRAVATAR = "Gravatar erlauben"
|
||||||
LEGEND_MAIN = "Haupt"
|
LEGEND_MAIN = "Haupt"
|
||||||
LABEL_ATTACHMENT_SIZE_LIMIT = "Größenlimit für Anhänge"
|
LABEL_ATTACHMENT_SIZE_LIMIT = "Größenlimit für Anhänge"
|
||||||
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Zusätzliche Konten erlauben"
|
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Zusätzliche Konten erlauben"
|
||||||
|
LABEL_ALLOW_IDENTITIES = "Allow multiple identities"
|
||||||
LABEL_ALLOW_TEMPLATES = "Vorlagen erlauben"
|
LABEL_ALLOW_TEMPLATES = "Vorlagen erlauben"
|
||||||
ALERT_WARNING = "Warnung!"
|
ALERT_WARNING = "Warnung!"
|
||||||
HTML_ALERT_WEAK_PASSWORD = "Sie verwenden das Standard-Admin-Passwort.
|
HTML_ALERT_WEAK_PASSWORD = "Sie verwenden das Standard-Admin-Passwort.
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ LABEL_ALLOW_GRAVATAR = "Allow Gravatar"
|
||||||
LEGEND_MAIN = "Main"
|
LEGEND_MAIN = "Main"
|
||||||
LABEL_ATTACHMENT_SIZE_LIMIT = "Attachment size limit"
|
LABEL_ATTACHMENT_SIZE_LIMIT = "Attachment size limit"
|
||||||
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Allow additional accounts"
|
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Allow additional accounts"
|
||||||
|
LABEL_ALLOW_IDENTITIES = "Allow multiple identities"
|
||||||
LABEL_ALLOW_TEMPLATES = "Allow templates"
|
LABEL_ALLOW_TEMPLATES = "Allow templates"
|
||||||
ALERT_WARNING = "Warning!"
|
ALERT_WARNING = "Warning!"
|
||||||
HTML_ALERT_WEAK_PASSWORD = "You are using the default admin password.
|
HTML_ALERT_WEAK_PASSWORD = "You are using the default admin password.
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ LABEL_ALLOW_GRAVATAR = "Permitir Gravatar"
|
||||||
LEGEND_MAIN = "Principal"
|
LEGEND_MAIN = "Principal"
|
||||||
LABEL_ATTACHMENT_SIZE_LIMIT = "Tamanho limite de anexo"
|
LABEL_ATTACHMENT_SIZE_LIMIT = "Tamanho limite de anexo"
|
||||||
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Permitir contas adicionais"
|
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Permitir contas adicionais"
|
||||||
|
LABEL_ALLOW_IDENTITIES = "Allow multiple identities"
|
||||||
LABEL_ALLOW_TEMPLATES = "Permitir templates"
|
LABEL_ALLOW_TEMPLATES = "Permitir templates"
|
||||||
ALERT_WARNING = "Aviso!"
|
ALERT_WARNING = "Aviso!"
|
||||||
HTML_ALERT_WEAK_PASSWORD = "Você está usando a senha administrativa padrão.
|
HTML_ALERT_WEAK_PASSWORD = "Você está usando a senha administrativa padrão.
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ LABEL_ALLOW_GRAVATAR = "Разрешить граватары"
|
||||||
LEGEND_MAIN = "Основное"
|
LEGEND_MAIN = "Основное"
|
||||||
LABEL_ATTACHMENT_SIZE_LIMIT = "Предельный размер вложений"
|
LABEL_ATTACHMENT_SIZE_LIMIT = "Предельный размер вложений"
|
||||||
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Разрешить дополнительные аккаунты"
|
LABEL_ALLOW_ADDITIONAL_ACCOUNTS = "Разрешить дополнительные аккаунты"
|
||||||
|
LABEL_ALLOW_IDENTITIES = "Разрешить множественные профили"
|
||||||
LABEL_ALLOW_TEMPLATES = "Разрешить шаблоны"
|
LABEL_ALLOW_TEMPLATES = "Разрешить шаблоны"
|
||||||
ALERT_WARNING = "Внимание!"
|
ALERT_WARNING = "Внимание!"
|
||||||
HTML_ALERT_WEAK_PASSWORD = "Вы используете пароль администратора по умолчанию.
|
HTML_ALERT_WEAK_PASSWORD = "Вы используете пароль администратора по умолчанию.
|
||||||
|
|
|
||||||
|
|
@ -481,6 +481,7 @@ AUTOLOGIN_MINUTES_OPTION_NAME = "%MINUTES% minute(s)"
|
||||||
[SETTINGS_GENERAL]
|
[SETTINGS_GENERAL]
|
||||||
LEGEND_GENERAL = "General"
|
LEGEND_GENERAL = "General"
|
||||||
LABEL_LANGUAGE = "Language"
|
LABEL_LANGUAGE = "Language"
|
||||||
|
LABEL_IDENTITY = "Identity"
|
||||||
LABEL_LAYOUT = "Layout"
|
LABEL_LAYOUT = "Layout"
|
||||||
LABEL_LAYOUT_NO_SPLIT = "No Split"
|
LABEL_LAYOUT_NO_SPLIT = "No Split"
|
||||||
LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split"
|
LABEL_LAYOUT_VERTICAL_SPLIT = "Vertical Split"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue