mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
OpenPGP first look (#53)
This commit is contained in:
parent
74991b16d9
commit
098a04eab6
15 changed files with 175 additions and 20 deletions
|
|
@ -112,6 +112,13 @@ module.exports = function (grunt) {
|
||||||
],
|
],
|
||||||
dest: 'rainloop/v/<%= cfg.devVersion %>/static/js/boot.js'
|
dest: 'rainloop/v/<%= cfg.devVersion %>/static/js/boot.js'
|
||||||
},
|
},
|
||||||
|
js_openpgp: {
|
||||||
|
nonull: true,
|
||||||
|
src: [
|
||||||
|
"vendors/openpgp.min.js",
|
||||||
|
],
|
||||||
|
dest: 'rainloop/v/<%= cfg.devVersion %>/static/js/openpgp.js'
|
||||||
|
},
|
||||||
js_libs: {
|
js_libs: {
|
||||||
nonull: true,
|
nonull: true,
|
||||||
options: {
|
options: {
|
||||||
|
|
@ -383,7 +390,7 @@ module.exports = function (grunt) {
|
||||||
nospawn: true
|
nospawn: true
|
||||||
},
|
},
|
||||||
files: ['dev/**/*.js', 'vendors/**/*.js'],
|
files: ['dev/**/*.js', 'vendors/**/*.js'],
|
||||||
tasks: ['concat:js_libs', 'concat:js_admin', 'concat:js_app']
|
tasks: ['concat:js_libs', 'concat:js_openpgp', 'concat:js_admin', 'concat:js_app']
|
||||||
},
|
},
|
||||||
styles: {
|
styles: {
|
||||||
options: {
|
options: {
|
||||||
|
|
|
||||||
|
|
@ -785,6 +785,18 @@ RainLoopApp.prototype.bootstart = function ()
|
||||||
|
|
||||||
if (bValue)
|
if (bValue)
|
||||||
{
|
{
|
||||||
|
// if (window.crypto && window.crypto.getRandomValues)
|
||||||
|
// {
|
||||||
|
// $.ajax({
|
||||||
|
// 'url': RL.link().openPgpJs(),
|
||||||
|
// 'dataType': 'script',
|
||||||
|
// 'cache': true,
|
||||||
|
// 'success': function () {
|
||||||
|
// window.console.log('openPgpJs');
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
kn.startScreens([MailBoxScreen, SettingsScreen]);
|
kn.startScreens([MailBoxScreen, SettingsScreen]);
|
||||||
|
|
||||||
// setup maito protocol
|
// setup maito protocol
|
||||||
|
|
@ -849,7 +861,6 @@ RainLoopApp.prototype.bootstart = function ()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Globals.bMobileDevice)
|
if (!Globals.bMobileDevice)
|
||||||
// if (false)
|
|
||||||
{
|
{
|
||||||
_.defer(function () {
|
_.defer(function () {
|
||||||
Utils.initLayoutResizer('#rl-left', '#rl-right', Enums.ClientSideKeyName.FolderListSize);
|
Utils.initLayoutResizer('#rl-left', '#rl-right', Enums.ClientSideKeyName.FolderListSize);
|
||||||
|
|
|
||||||
|
|
@ -257,6 +257,15 @@ LinkBuilder.prototype.notificationMailIcon = function ()
|
||||||
this.sVersion + '/static/css/images/icom-message-notification.png';
|
this.sVersion + '/static/css/images/icom-message-notification.png';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
LinkBuilder.prototype.openPgpJs = function ()
|
||||||
|
{
|
||||||
|
return ('' === this.sCdnStaticDomain ? 'rainloop/v/' : this.sCdnStaticDomain) +
|
||||||
|
this.sVersion + '/static/js/openpgp.js';
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "RainLoop",
|
"name": "RainLoop",
|
||||||
"title": "RainLoop Webmail",
|
"title": "RainLoop Webmail",
|
||||||
"version": "1.6.2",
|
"version": "1.6.2",
|
||||||
"release": "660",
|
"release": "661",
|
||||||
"description": "Simple, modern & fast web-based email client",
|
"description": "Simple, modern & fast web-based email client",
|
||||||
"homepage": "http://rainloop.net",
|
"homepage": "http://rainloop.net",
|
||||||
"main": "Gruntfile.js",
|
"main": "Gruntfile.js",
|
||||||
|
|
|
||||||
|
|
@ -248,6 +248,14 @@ class BodyStructure
|
||||||
return 'doc' === \MailSo\Base\Utils::ContentTypeType($this->ContentType(), $this->FileName());
|
return 'doc' === \MailSo\Base\Utils::ContentTypeType($this->ContentType(), $this->FileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function IsPgpSignature()
|
||||||
|
{
|
||||||
|
return 'application/pgp-signature' === \strtolower($this->ContentType());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array|null
|
* @return array|null
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -356,18 +356,30 @@ class MailClient
|
||||||
|
|
||||||
$oBodyStructure = null;
|
$oBodyStructure = null;
|
||||||
$oMessage = false;
|
$oMessage = false;
|
||||||
$aTextMimeIndexes = array();
|
$aBodyPeekMimeIndexes = array();
|
||||||
|
|
||||||
$aFetchResponse = $this->oImapClient->Fetch(array(\MailSo\Imap\Enumerations\FetchType::BODYSTRUCTURE), $iIndex, $bIndexIsUid);
|
$aFetchResponse = $this->oImapClient->Fetch(array(\MailSo\Imap\Enumerations\FetchType::BODYSTRUCTURE), $iIndex, $bIndexIsUid);
|
||||||
if (0 < \count($aFetchResponse))
|
if (0 < \count($aFetchResponse) && isset($aFetchResponse[0]))
|
||||||
{
|
{
|
||||||
$oBodyStructure = $aFetchResponse[0]->GetFetchBodyStructure();
|
$oBodyStructure = $aFetchResponse[0]->GetFetchBodyStructure();
|
||||||
$aTextParts = $oBodyStructure ? $oBodyStructure->SearchHtmlOrPlainParts() : null;
|
if ($oBodyStructure)
|
||||||
if (is_array($aTextParts) && 0 < \count($aTextParts))
|
|
||||||
{
|
{
|
||||||
foreach ($aTextParts as $oPart)
|
$aTextParts = $oBodyStructure->SearchHtmlOrPlainParts();
|
||||||
|
if (is_array($aTextParts) && 0 < \count($aTextParts))
|
||||||
{
|
{
|
||||||
$aTextMimeIndexes[] = $oPart->PartID();
|
foreach ($aTextParts as $oPart)
|
||||||
|
{
|
||||||
|
$aBodyPeekMimeIndexes[] = $oPart->PartID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$aSignatureParts = $oBodyStructure->SearchByContentType('application/pgp-signature');
|
||||||
|
if (is_array($aSignatureParts) && 0 < \count($aSignatureParts))
|
||||||
|
{
|
||||||
|
foreach ($aSignatureParts as $oPart)
|
||||||
|
{
|
||||||
|
$aBodyPeekMimeIndexes[] = $oPart->PartID();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -381,9 +393,9 @@ class MailClient
|
||||||
$this->getEnvelopeOrHeadersRequestString()
|
$this->getEnvelopeOrHeadersRequestString()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (0 < \count($aTextMimeIndexes))
|
if (0 < \count($aBodyPeekMimeIndexes))
|
||||||
{
|
{
|
||||||
foreach ($aTextMimeIndexes as $sTextMimeIndex)
|
foreach ($aBodyPeekMimeIndexes as $sTextMimeIndex)
|
||||||
{
|
{
|
||||||
$aFetchItems[] = \MailSo\Imap\Enumerations\FetchType::BODY_PEEK.'['.$sTextMimeIndex.']';
|
$aFetchItems[] = \MailSo\Imap\Enumerations\FetchType::BODY_PEEK.'['.$sTextMimeIndex.']';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,11 @@ class Message
|
||||||
*/
|
*/
|
||||||
private $sPlain;
|
private $sPlain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sPlainRaw;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
|
|
@ -158,6 +163,11 @@ class Message
|
||||||
*/
|
*/
|
||||||
private $iThreadsLen;
|
private $iThreadsLen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sPgpSignature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
|
|
@ -191,6 +201,7 @@ class Message
|
||||||
$this->oBcc = null;
|
$this->oBcc = null;
|
||||||
|
|
||||||
$this->sPlain = '';
|
$this->sPlain = '';
|
||||||
|
$this->sPlainRaw = '';
|
||||||
$this->sHtml = '';
|
$this->sHtml = '';
|
||||||
|
|
||||||
$this->oAttachments = null;
|
$this->oAttachments = null;
|
||||||
|
|
@ -208,6 +219,8 @@ class Message
|
||||||
$this->iThreadsLen = 0;
|
$this->iThreadsLen = 0;
|
||||||
$this->iParentThread = 0;
|
$this->iParentThread = 0;
|
||||||
|
|
||||||
|
$this->sPgpSignature = '';
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,6 +240,14 @@ class Message
|
||||||
return $this->sPlain;
|
return $this->sPlain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function PlainRaw()
|
||||||
|
{
|
||||||
|
return $this->sPlainRaw;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
|
@ -235,6 +256,14 @@ class Message
|
||||||
return $this->sHtml;
|
return $this->sHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function PgpSignature()
|
||||||
|
{
|
||||||
|
return $this->sPgpSignature;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sHtml
|
* @param string $sHtml
|
||||||
*
|
*
|
||||||
|
|
@ -527,8 +556,6 @@ class Message
|
||||||
$oBodyStructure = $oFetchResponse->GetFetchBodyStructure();
|
$oBodyStructure = $oFetchResponse->GetFetchBodyStructure();
|
||||||
}
|
}
|
||||||
|
|
||||||
$aTextParts = $oBodyStructure ? $oBodyStructure->SearchHtmlOrPlainParts() : array();
|
|
||||||
|
|
||||||
$sUid = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::UID);
|
$sUid = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::UID);
|
||||||
$sSize = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::RFC822_SIZE);
|
$sSize = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::RFC822_SIZE);
|
||||||
$sInternalDate = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::INTERNALDATE);
|
$sInternalDate = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::INTERNALDATE);
|
||||||
|
|
@ -704,6 +731,7 @@ class Message
|
||||||
$this->sInReplyTo = $oFetchResponse->GetFetchEnvelopeValue(8, '');
|
$this->sInReplyTo = $oFetchResponse->GetFetchEnvelopeValue(8, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$aTextParts = $oBodyStructure ? $oBodyStructure->SearchHtmlOrPlainParts() : null;
|
||||||
if (\is_array($aTextParts) && 0 < \count($aTextParts))
|
if (\is_array($aTextParts) && 0 < \count($aTextParts))
|
||||||
{
|
{
|
||||||
if (0 === \strlen($sCharset))
|
if (0 === \strlen($sCharset))
|
||||||
|
|
@ -749,9 +777,43 @@ class Message
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$this->sPlain = \implode("\n", $sPlainParts);
|
$this->sPlain = \implode("\n", $sPlainParts);
|
||||||
|
$this->sPlainRaw = $this->sPlain;
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($sHtmlParts, $sPlainParts);
|
$aMatch = array();
|
||||||
|
if (\preg_match('/-----BEGIN PGP SIGNATURE-----(.+)-----END PGP SIGNATURE-----/ism', $this->sPlain, $aMatch) && !empty($aMatch[0]))
|
||||||
|
{
|
||||||
|
$this->sPgpSignature = $aMatch[0];
|
||||||
|
$this->sPlain = \trim($this->sPlain);
|
||||||
|
}
|
||||||
|
|
||||||
|
$aMatch = array();
|
||||||
|
if (!empty($this->sPgpSignature) &&
|
||||||
|
\preg_match('/-----BEGIN PGP SIGNED MESSAGE-----(.+)-----BEGIN PGP SIGNATURE-----(.+)-----END PGP SIGNATURE-----/ism', $this->sPlain, $aMatch) &&
|
||||||
|
!empty($aMatch[0]) && isset($aMatch[1]))
|
||||||
|
{
|
||||||
|
$this->sPlain = \str_replace($aMatch[0], $aMatch[1], $this->sPlain);
|
||||||
|
$this->sPlain = \trim(\preg_replace('/^Hash: [^\s]+/i', '', \trim($this->sPlain)));
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($sHtmlParts, $sPlainParts, $aMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($this->sPgpSignature) && 'multipart/signed' === \strtolower($this->sContentType) &&
|
||||||
|
'application/pgp-signature' === \strtolower($oHeaders->ParameterValue(
|
||||||
|
\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
|
||||||
|
\MailSo\Mime\Enumerations\Parameter::PROTOCOL
|
||||||
|
)))
|
||||||
|
{
|
||||||
|
$aPgpSignatureParts = $oBodyStructure ? $oBodyStructure->SearchByContentType('application/pgp-signature') : null;
|
||||||
|
if (\is_array($aPgpSignatureParts) && 0 < \count($aPgpSignatureParts) && isset($aPgpSignatureParts[0]))
|
||||||
|
{
|
||||||
|
$sPgpSignatureText = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY.'['.$aPgpSignatureParts[0]->PartID().']');
|
||||||
|
if (\is_string($sPgpSignatureText) && 0 < \strlen($sPgpSignatureText) && 0 < \strpos($sPgpSignatureText, 'BEGIN PGP SIGNATURE'))
|
||||||
|
{
|
||||||
|
$this->sPgpSignature = \trim($sPgpSignatureText);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($oBodyStructure)
|
if ($oBodyStructure)
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,5 @@ class Parameter
|
||||||
const NAME = 'name';
|
const NAME = 'name';
|
||||||
const FILENAME = 'filename';
|
const FILENAME = 'filename';
|
||||||
const BOUNDARY = 'boundary';
|
const BOUNDARY = 'boundary';
|
||||||
|
const PROTOCOL = 'protocol';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6320,13 +6320,14 @@ class Actions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sPlain = '';
|
$sPlain = $sPlainRaw = '';
|
||||||
$sHtml = $mResponse->Html();
|
$sHtml = $mResponse->Html();
|
||||||
$bRtl = false;
|
$bRtl = false;
|
||||||
|
|
||||||
if (0 === \strlen($sHtml))
|
if (0 === \strlen($sHtml))
|
||||||
{
|
{
|
||||||
$sPlain = $mResponse->Plain();
|
$sPlain = $mResponse->Plain();
|
||||||
|
$sPlainRaw = $mResponse->PlainRaw();
|
||||||
$bRtl = \MailSo\Base\Utils::IsRTL($sPlain);
|
$bRtl = \MailSo\Base\Utils::IsRTL($sPlain);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -6341,9 +6342,12 @@ class Actions
|
||||||
$sHtml, $bHasExternals, $mFoundedCIDs, $aContentLocationUrls, $mFoundedContentLocationUrls);
|
$sHtml, $bHasExternals, $mFoundedCIDs, $aContentLocationUrls, $mFoundedContentLocationUrls);
|
||||||
|
|
||||||
$mResult['Plain'] = 0 === \strlen($sPlain) ? '' : \MailSo\Base\HtmlUtils::ConvertPlainToHtml($sPlain);
|
$mResult['Plain'] = 0 === \strlen($sPlain) ? '' : \MailSo\Base\HtmlUtils::ConvertPlainToHtml($sPlain);
|
||||||
|
$mResult['PlainRaw'] = $sPlainRaw;
|
||||||
$mResult['Rtl'] = $bRtl;
|
$mResult['Rtl'] = $bRtl;
|
||||||
|
|
||||||
unset($sHtml, $sPlain);
|
$mResult['PgpSignature'] = $mResponse->PgpSignature();
|
||||||
|
|
||||||
|
unset($sHtml, $sPlain, $sPlainRaw);
|
||||||
|
|
||||||
$mResult['HasExternals'] = $bHasExternals;
|
$mResult['HasExternals'] = $bHasExternals;
|
||||||
$mResult['HasInternals'] = (\is_array($mFoundedCIDs) && 0 < \count($mFoundedCIDs)) ||
|
$mResult['HasInternals'] = (\is_array($mFoundedCIDs) && 0 < \count($mFoundedCIDs)) ||
|
||||||
|
|
|
||||||
|
|
@ -3222,6 +3222,15 @@ LinkBuilder.prototype.notificationMailIcon = function ()
|
||||||
this.sVersion + '/static/css/images/icom-message-notification.png';
|
this.sVersion + '/static/css/images/icom-message-notification.png';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
LinkBuilder.prototype.openPgpJs = function ()
|
||||||
|
{
|
||||||
|
return ('' === this.sCdnStaticDomain ? 'rainloop/v/' : this.sCdnStaticDomain) +
|
||||||
|
this.sVersion + '/static/js/openpgp.js';
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
2
rainloop/v/0.0.0/static/js/admin.min.js
vendored
2
rainloop/v/0.0.0/static/js/admin.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -3222,6 +3222,15 @@ LinkBuilder.prototype.notificationMailIcon = function ()
|
||||||
this.sVersion + '/static/css/images/icom-message-notification.png';
|
this.sVersion + '/static/css/images/icom-message-notification.png';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
LinkBuilder.prototype.openPgpJs = function ()
|
||||||
|
{
|
||||||
|
return ('' === this.sCdnStaticDomain ? 'rainloop/v/' : this.sCdnStaticDomain) +
|
||||||
|
this.sVersion + '/static/js/openpgp.js';
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
|
|
@ -17362,6 +17371,18 @@ RainLoopApp.prototype.bootstart = function ()
|
||||||
|
|
||||||
if (bValue)
|
if (bValue)
|
||||||
{
|
{
|
||||||
|
// if (window.crypto && window.crypto.getRandomValues)
|
||||||
|
// {
|
||||||
|
// $.ajax({
|
||||||
|
// 'url': RL.link().openPgpJs(),
|
||||||
|
// 'dataType': 'script',
|
||||||
|
// 'cache': true,
|
||||||
|
// 'success': function () {
|
||||||
|
// window.console.log('openPgpJs');
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
kn.startScreens([MailBoxScreen, SettingsScreen]);
|
kn.startScreens([MailBoxScreen, SettingsScreen]);
|
||||||
|
|
||||||
// setup maito protocol
|
// setup maito protocol
|
||||||
|
|
@ -17426,7 +17447,6 @@ RainLoopApp.prototype.bootstart = function ()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Globals.bMobileDevice)
|
if (!Globals.bMobileDevice)
|
||||||
// if (false)
|
|
||||||
{
|
{
|
||||||
_.defer(function () {
|
_.defer(function () {
|
||||||
Utils.initLayoutResizer('#rl-left', '#rl-right', Enums.ClientSideKeyName.FolderListSize);
|
Utils.initLayoutResizer('#rl-left', '#rl-right', Enums.ClientSideKeyName.FolderListSize);
|
||||||
|
|
|
||||||
4
rainloop/v/0.0.0/static/js/app.min.js
vendored
4
rainloop/v/0.0.0/static/js/app.min.js
vendored
File diff suppressed because one or more lines are too long
6
rainloop/v/0.0.0/static/js/openpgp.js
Normal file
6
rainloop/v/0.0.0/static/js/openpgp.js
Normal file
File diff suppressed because one or more lines are too long
6
vendors/openpgp.min.js
vendored
Normal file
6
vendors/openpgp.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue