mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-08 17:07:03 +03:00
MailSo class properties to typed properties and clean up
This commit is contained in:
parent
22450e7430
commit
731ac52564
53 changed files with 677 additions and 1944 deletions
|
|
@ -23,8 +23,7 @@ abstract class DateTimeHelper
|
||||||
public static function GetUtcTimeZoneObject() : \DateTimeZone
|
public static function GetUtcTimeZoneObject() : \DateTimeZone
|
||||||
{
|
{
|
||||||
static $oDateTimeZone = null;
|
static $oDateTimeZone = null;
|
||||||
if (null === $oDateTimeZone)
|
if (null === $oDateTimeZone) {
|
||||||
{
|
|
||||||
$oDateTimeZone = new \DateTimeZone('UTC');
|
$oDateTimeZone = new \DateTimeZone('UTC');
|
||||||
}
|
}
|
||||||
return $oDateTimeZone;
|
return $oDateTimeZone;
|
||||||
|
|
@ -37,8 +36,7 @@ abstract class DateTimeHelper
|
||||||
public static function ParseRFC2822DateString(string $sDateTime) : int
|
public static function ParseRFC2822DateString(string $sDateTime) : int
|
||||||
{
|
{
|
||||||
$sDateTime = \trim($sDateTime);
|
$sDateTime = \trim($sDateTime);
|
||||||
if (empty($sDateTime))
|
if (empty($sDateTime)) {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,13 +52,12 @@ abstract class DateTimeHelper
|
||||||
public static function ParseInternalDateString(string $sDateTime) : int
|
public static function ParseInternalDateString(string $sDateTime) : int
|
||||||
{
|
{
|
||||||
$sDateTime = \trim($sDateTime);
|
$sDateTime = \trim($sDateTime);
|
||||||
if (empty($sDateTime))
|
if (empty($sDateTime)) {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\preg_match('/^[a-z]{2,4}, /i', $sDateTime)) // RFC2822 ~ "Thu, 10 Jun 2010 08:58:33 -0700 (PDT)"
|
// RFC2822 ~ "Thu, 10 Jun 2010 08:58:33 -0700 (PDT)"
|
||||||
{
|
if (\preg_match('/^[a-z]{2,4}, /i', $sDateTime)) {
|
||||||
return static::ParseRFC2822DateString($sDateTime);
|
return static::ParseRFC2822DateString($sDateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,8 +71,7 @@ abstract class DateTimeHelper
|
||||||
public static function ParseDateStringType1(string $sDateTime) : int
|
public static function ParseDateStringType1(string $sDateTime) : int
|
||||||
{
|
{
|
||||||
$sDateTime = \trim($sDateTime);
|
$sDateTime = \trim($sDateTime);
|
||||||
if (empty($sDateTime))
|
if (empty($sDateTime)) {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -201,87 +201,6 @@ abstract class HtmlUtils
|
||||||
. $oDoc->saveHTML($oBody) . '</html>';
|
. $oDoc->saveHTML($oBody) . '</html>';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function ConvertPlainToHtml(string $sText, bool $bLinksWithTargetBlank = true) : string
|
|
||||||
{
|
|
||||||
$sText = \trim($sText);
|
|
||||||
if (!\strlen($sText))
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$sText = (new \MailSo\Base\LinkFinder)
|
|
||||||
->Text($sText)
|
|
||||||
->UseDefaultWrappers($bLinksWithTargetBlank)
|
|
||||||
->CompileText()
|
|
||||||
;
|
|
||||||
|
|
||||||
$sText = \str_replace("\r", '', $sText);
|
|
||||||
|
|
||||||
$aText = \explode("\n", $sText);
|
|
||||||
unset($sText);
|
|
||||||
|
|
||||||
$bIn = false;
|
|
||||||
$bDo = true;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
$bDo = false;
|
|
||||||
$aNextText = array();
|
|
||||||
foreach ($aText as $sTextLine)
|
|
||||||
{
|
|
||||||
$bStart = 0 === \strpos(\ltrim($sTextLine), '>');
|
|
||||||
if ($bStart && !$bIn)
|
|
||||||
{
|
|
||||||
$bDo = true;
|
|
||||||
$bIn = true;
|
|
||||||
$aNextText[] = '<blockquote>';
|
|
||||||
$aNextText[] = \substr(\ltrim($sTextLine), 4);
|
|
||||||
}
|
|
||||||
else if (!$bStart && $bIn)
|
|
||||||
{
|
|
||||||
$bIn = false;
|
|
||||||
$aNextText[] = '</blockquote>';
|
|
||||||
$aNextText[] = $sTextLine;
|
|
||||||
}
|
|
||||||
else if ($bStart && $bIn)
|
|
||||||
{
|
|
||||||
$aNextText[] = \substr(\ltrim($sTextLine), 4);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$aNextText[] = $sTextLine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($bIn)
|
|
||||||
{
|
|
||||||
$bIn = false;
|
|
||||||
$aNextText[] = '</blockquote>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$aText = $aNextText;
|
|
||||||
}
|
|
||||||
while ($bDo);
|
|
||||||
|
|
||||||
$sText = \join("\n", $aText);
|
|
||||||
unset($aText);
|
|
||||||
|
|
||||||
$sText = \preg_replace('/[\n][ ]+/', "\n", $sText);
|
|
||||||
// $sText = \preg_replace('/[\s]+([\s])/', '\\1', $sText);
|
|
||||||
|
|
||||||
$sText = \preg_replace('/<blockquote>[\s]+/i', '<blockquote>', $sText);
|
|
||||||
$sText = \preg_replace('/[\s]+<\/blockquote>/i', '</blockquote>', $sText);
|
|
||||||
|
|
||||||
$sText = \preg_replace('/<\/blockquote>([\n]{0,2})<blockquote>/i', '\\1', $sText);
|
|
||||||
$sText = \preg_replace('/[\n]{3,}/', "\n\n", $sText);
|
|
||||||
|
|
||||||
$sText = \strtr($sText, array(
|
|
||||||
"\t" => "\xC2\xA0\xC2\xA0\xC2\xA0\xC2\xA0",
|
|
||||||
' ' => "\xC2\xA0\xC2\xA0"
|
|
||||||
));
|
|
||||||
|
|
||||||
return \nl2br($sText);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function ConvertHtmlToPlain(string $sText) : string
|
public static function ConvertHtmlToPlain(string $sText) : string
|
||||||
{
|
{
|
||||||
$sText = \MailSo\Base\Utils::StripSpaces($sText);
|
$sText = \MailSo\Base\Utils::StripSpaces($sText);
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,7 @@ class Http
|
||||||
public static function SingletonInstance() : self
|
public static function SingletonInstance() : self
|
||||||
{
|
{
|
||||||
static $oInstance = null;
|
static $oInstance = null;
|
||||||
if (null === $oInstance)
|
if (null === $oInstance) {
|
||||||
{
|
|
||||||
$oInstance = new self;
|
$oInstance = new self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,8 +64,7 @@ class Http
|
||||||
|
|
||||||
public function IsLocalhost(string $sValueToCheck = '') : bool
|
public function IsLocalhost(string $sValueToCheck = '') : bool
|
||||||
{
|
{
|
||||||
if (empty($sValueToCheck))
|
if (empty($sValueToCheck)) {
|
||||||
{
|
|
||||||
$sValueToCheck = static::GetServer('REMOTE_ADDR', '');
|
$sValueToCheck = static::GetServer('REMOTE_ADDR', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,8 +74,7 @@ class Http
|
||||||
public function GetRawBody() : string
|
public function GetRawBody() : string
|
||||||
{
|
{
|
||||||
static $sRawBody = null;
|
static $sRawBody = null;
|
||||||
if (null === $sRawBody)
|
if (null === $sRawBody) {
|
||||||
{
|
|
||||||
$sBody = \file_get_contents('php://input');
|
$sBody = \file_get_contents('php://input');
|
||||||
$sRawBody = (false !== $sBody) ? $sBody : '';
|
$sRawBody = (false !== $sBody) ? $sBody : '';
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +85,7 @@ class Http
|
||||||
{
|
{
|
||||||
$sServerKey = 'HTTP_'.\strtoupper(\str_replace('-', '_', $sHeader));
|
$sServerKey = 'HTTP_'.\strtoupper(\str_replace('-', '_', $sHeader));
|
||||||
$sResultHeader = static::GetServer($sServerKey, '');
|
$sResultHeader = static::GetServer($sServerKey, '');
|
||||||
if (0 === \strlen($sResultHeader) && \MailSo\Base\Utils::FunctionCallable('apache_request_headers')) {
|
if (!\strlen($sResultHeader) && \MailSo\Base\Utils::FunctionCallable('apache_request_headers')) {
|
||||||
$sHeaders = \apache_request_headers();
|
$sHeaders = \apache_request_headers();
|
||||||
if (isset($sHeaders[$sHeader])) {
|
if (isset($sHeaders[$sHeader])) {
|
||||||
$sResultHeader = $sHeaders[$sHeader];
|
$sResultHeader = $sHeaders[$sHeader];
|
||||||
|
|
@ -105,69 +102,44 @@ class Http
|
||||||
public function IsSecure(bool $bCheckProxy = true) : bool
|
public function IsSecure(bool $bCheckProxy = true) : bool
|
||||||
{
|
{
|
||||||
$sHttps = \strtolower(static::GetServer('HTTPS', ''));
|
$sHttps = \strtolower(static::GetServer('HTTPS', ''));
|
||||||
if ('on' === $sHttps || ('' === $sHttps && '443' === (string) static::GetServer('SERVER_PORT', '')))
|
return ('on' === $sHttps || ('' === $sHttps && '443' === (string) static::GetServer('SERVER_PORT', '')))
|
||||||
{
|
|| ($bCheckProxy && (
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($bCheckProxy && (
|
|
||||||
('https' === \strtolower(static::GetServer('HTTP_X_FORWARDED_PROTO', ''))) ||
|
('https' === \strtolower(static::GetServer('HTTP_X_FORWARDED_PROTO', ''))) ||
|
||||||
('on' === \strtolower(static::GetServer('HTTP_X_FORWARDED_SSL', '')))
|
('on' === \strtolower(static::GetServer('HTTP_X_FORWARDED_SSL', '')))
|
||||||
))
|
));
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetHost(bool $bWithRemoteUserData = false, bool $bWithoutWWW = true, bool $bWithoutPort = false) : string
|
public function GetHost(bool $bWithRemoteUserData = false, bool $bWithoutWWW = true, bool $bWithoutPort = false) : string
|
||||||
{
|
{
|
||||||
$sHost = static::GetServer('HTTP_HOST', '');
|
$sHost = static::GetServer('HTTP_HOST', '');
|
||||||
if (!\strlen($sHost))
|
if (!\strlen($sHost)) {
|
||||||
{
|
|
||||||
$sName = static::GetServer('SERVER_NAME');
|
$sName = static::GetServer('SERVER_NAME');
|
||||||
$iPort = (int) static::GetServer('SERVER_PORT', 80);
|
$iPort = (int) static::GetServer('SERVER_PORT', 80);
|
||||||
|
|
||||||
$sHost = (\in_array($iPort, array(80, 433))) ? $sName : $sName.':'.$iPort;
|
$sHost = (\in_array($iPort, array(80, 433))) ? $sName : $sName.':'.$iPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bWithoutWWW)
|
if ($bWithoutWWW) {
|
||||||
{
|
|
||||||
$sHost = 'www.' === \substr(\strtolower($sHost), 0, 4) ? \substr($sHost, 4) : $sHost;
|
$sHost = 'www.' === \substr(\strtolower($sHost), 0, 4) ? \substr($sHost, 4) : $sHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bWithRemoteUserData)
|
if ($bWithRemoteUserData) {
|
||||||
{
|
|
||||||
$sUser = \trim(static::GetServer('REMOTE_USER', ''));
|
$sUser = \trim(static::GetServer('REMOTE_USER', ''));
|
||||||
$sHost = (\strlen($sUser) ? $sUser.'@' : '').$sHost;
|
$sHost = (\strlen($sUser) ? $sUser.'@' : '').$sHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bWithoutPort)
|
return $bWithoutPort ? \preg_replace('/:\d+$/', '', $sHost) : $sHost;
|
||||||
{
|
|
||||||
$sHost = \preg_replace('/:\d+$/', '', $sHost);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sHost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetClientIp(bool $bCheckProxy = false) : string
|
public function GetClientIp(bool $bCheckProxy = false) : string
|
||||||
{
|
{
|
||||||
$sIp = '';
|
if ($bCheckProxy && null !== static::GetServer('HTTP_CLIENT_IP', null)) {
|
||||||
if ($bCheckProxy && null !== static::GetServer('HTTP_CLIENT_IP', null))
|
return static::GetServer('HTTP_CLIENT_IP', '');
|
||||||
{
|
|
||||||
$sIp = static::GetServer('HTTP_CLIENT_IP', '');
|
|
||||||
}
|
}
|
||||||
else if ($bCheckProxy && null !== static::GetServer('HTTP_X_FORWARDED_FOR', null))
|
if ($bCheckProxy && null !== static::GetServer('HTTP_X_FORWARDED_FOR', null)) {
|
||||||
{
|
return static::GetServer('HTTP_X_FORWARDED_FOR', '');
|
||||||
$sIp = static::GetServer('HTTP_X_FORWARDED_FOR', '');
|
|
||||||
}
|
}
|
||||||
else
|
return static::GetServer('REMOTE_ADDR', '');
|
||||||
{
|
|
||||||
$sIp = static::GetServer('REMOTE_ADDR', '');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sIp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function checkETag(string $ETag) : void
|
public static function checkETag(string $ETag) : void
|
||||||
|
|
@ -236,8 +208,7 @@ class Http
|
||||||
|
|
||||||
public static function StatusHeader(int $iStatus, string $sCustomStatusText = '') : void
|
public static function StatusHeader(int $iStatus, string $sCustomStatusText = '') : void
|
||||||
{
|
{
|
||||||
if (99 < $iStatus)
|
if (99 < $iStatus) {
|
||||||
{
|
|
||||||
$aStatus = array(
|
$aStatus = array(
|
||||||
200 => 'OK',
|
200 => 'OK',
|
||||||
206 => 'Partial Content',
|
206 => 'Partial Content',
|
||||||
|
|
@ -253,7 +224,7 @@ class Http
|
||||||
500 => 'Internal Server Error'
|
500 => 'Internal Server Error'
|
||||||
);
|
);
|
||||||
|
|
||||||
$sHeaderText = (0 === \strlen($sCustomStatusText) && isset($aStatus[$iStatus]) ? $aStatus[$iStatus] : $sCustomStatusText);
|
$sHeaderText = (!\strlen($sCustomStatusText) && isset($aStatus[$iStatus]) ? $aStatus[$iStatus] : $sCustomStatusText);
|
||||||
|
|
||||||
\http_response_code($iStatus);
|
\http_response_code($iStatus);
|
||||||
if (isset($_SERVER['SERVER_PROTOCOL'])) {
|
if (isset($_SERVER['SERVER_PROTOCOL'])) {
|
||||||
|
|
|
||||||
|
|
@ -1,259 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of MailSo.
|
|
||||||
*
|
|
||||||
* (c) 2014 Usenko Timur
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace MailSo\Base;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @category MailSo
|
|
||||||
* @package Base
|
|
||||||
*/
|
|
||||||
class LinkFinder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @const
|
|
||||||
*/
|
|
||||||
const OPEN_LINK = '@#@link{';
|
|
||||||
const CLOSE_LINK = '}link@#@';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $aPrepearPlainStringUrls;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sText;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var mixed
|
|
||||||
*/
|
|
||||||
private $fLinkWrapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iHtmlSpecialCharsFlags;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var mixed
|
|
||||||
*/
|
|
||||||
private $fMailWrapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iOptimizationLimit;
|
|
||||||
|
|
||||||
function __construct()
|
|
||||||
{
|
|
||||||
$this->iHtmlSpecialCharsFlags = (\defined('ENT_QUOTES') && \defined('ENT_SUBSTITUTE') && \defined('ENT_HTML401'))
|
|
||||||
? ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 : ENT_QUOTES;
|
|
||||||
|
|
||||||
if (\defined('ENT_IGNORE'))
|
|
||||||
{
|
|
||||||
$this->iHtmlSpecialCharsFlags |= ENT_IGNORE;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->iOptimizationLimit = 300000;
|
|
||||||
|
|
||||||
$this->Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Clear() : self
|
|
||||||
{
|
|
||||||
$this->aPrepearPlainStringUrls = array();
|
|
||||||
$this->fLinkWrapper = null;
|
|
||||||
$this->fMailWrapper = null;
|
|
||||||
$this->sText = '';
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Text(string $sText) : self
|
|
||||||
{
|
|
||||||
$this->sText = $sText;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $fLinkWrapper
|
|
||||||
*/
|
|
||||||
public function LinkWrapper($fLinkWrapper) : self
|
|
||||||
{
|
|
||||||
$this->fLinkWrapper = $fLinkWrapper;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $fMailWrapper
|
|
||||||
*/
|
|
||||||
public function MailWrapper($fMailWrapper) : self
|
|
||||||
{
|
|
||||||
$this->fMailWrapper = $fMailWrapper;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function UseDefaultWrappers(bool $bAddTargetBlank = false) : self
|
|
||||||
{
|
|
||||||
$this->fLinkWrapper = function ($sLink) use ($bAddTargetBlank) {
|
|
||||||
|
|
||||||
$sNameLink = $sLink;
|
|
||||||
if (!\preg_match('/^[a-z]{3,5}\:\/\//i', \ltrim($sLink)))
|
|
||||||
{
|
|
||||||
$sLink = 'https://'.\ltrim($sLink);
|
|
||||||
}
|
|
||||||
|
|
||||||
return '<a '.($bAddTargetBlank ? 'target="_blank" ': '').'href="'.$sLink.'">'.$sNameLink.'</a>';
|
|
||||||
};
|
|
||||||
|
|
||||||
$this->fMailWrapper = function ($sEmail) use ($bAddTargetBlank) {
|
|
||||||
return '<a '.($bAddTargetBlank ? 'target="_blank" ': '').'href="mailto:'.$sEmail.'">'.$sEmail.'</a>';
|
|
||||||
};
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function CompileText(bool $bUseHtmlSpecialChars = true) : string
|
|
||||||
{
|
|
||||||
$sText = \substr($this->sText, 0, $this->iOptimizationLimit);
|
|
||||||
$sSubText = \substr($this->sText, $this->iOptimizationLimit);
|
|
||||||
|
|
||||||
$this->aPrepearPlainStringUrls = array();
|
|
||||||
if (null !== $this->fLinkWrapper && \is_callable($this->fLinkWrapper))
|
|
||||||
{
|
|
||||||
$sText = $this->findLinks($sText, $this->fLinkWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null !== $this->fMailWrapper && \is_callable($this->fMailWrapper))
|
|
||||||
{
|
|
||||||
$sText = $this->findMails($sText, $this->fMailWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
$sResult = '';
|
|
||||||
if ($bUseHtmlSpecialChars)
|
|
||||||
{
|
|
||||||
$sResult = \htmlentities($sText.$sSubText, $this->iHtmlSpecialCharsFlags, 'UTF-8');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$sResult = $sText.$sSubText;
|
|
||||||
}
|
|
||||||
|
|
||||||
unset($sText, $sSubText);
|
|
||||||
|
|
||||||
if (\count($this->aPrepearPlainStringUrls))
|
|
||||||
{
|
|
||||||
$aPrepearPlainStringUrls = $this->aPrepearPlainStringUrls;
|
|
||||||
$sResult = \preg_replace_callback('/'.\preg_quote(static::OPEN_LINK, '/').
|
|
||||||
'([\d]+)'.\preg_quote(static::CLOSE_LINK, '/').'/',
|
|
||||||
function ($aMatches) use ($aPrepearPlainStringUrls) {
|
|
||||||
$iIndex = (int) $aMatches[1];
|
|
||||||
return isset($aPrepearPlainStringUrls[$iIndex]) ? $aPrepearPlainStringUrls[$iIndex] : '';
|
|
||||||
}, $sResult);
|
|
||||||
|
|
||||||
$this->aPrepearPlainStringUrls = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $fWrapper
|
|
||||||
*/
|
|
||||||
private function findLinks(string $sText, $fWrapper) : string
|
|
||||||
{
|
|
||||||
$sPattern = '/([\W]|^)((?:https?:\/\/)|(?:svn:\/\/)|(?:git:\/\/)|(?:s?ftps?:\/\/)|(?:www\.))'.
|
|
||||||
'((\S+?)(\\/)?)((?:>)?|[^\w\=\\/;\(\)\[\]]*?)(?=<|\s|$)/imu';
|
|
||||||
|
|
||||||
$aPrepearPlainStringUrls = $this->aPrepearPlainStringUrls;
|
|
||||||
$sText = \preg_replace_callback($sPattern, function ($aMatch) use ($fWrapper, &$aPrepearPlainStringUrls) {
|
|
||||||
|
|
||||||
if (\is_array($aMatch) && 6 < \count($aMatch))
|
|
||||||
{
|
|
||||||
while (\in_array($sChar = \substr($aMatch[3], -1), array(']', ')')))
|
|
||||||
{
|
|
||||||
if (\substr_count($aMatch[3], ']' === $sChar ? '[': '(') - \substr_count($aMatch[3], $sChar) < 0)
|
|
||||||
{
|
|
||||||
$aMatch[3] = \substr($aMatch[3], 0, -1);
|
|
||||||
$aMatch[6] = (']' === $sChar ? ']': ')').$aMatch[6];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$sLinkWithWrap = $fWrapper($aMatch[2].$aMatch[3]);
|
|
||||||
if (\is_string($sLinkWithWrap) && \strlen($sLinkWithWrap))
|
|
||||||
{
|
|
||||||
$aPrepearPlainStringUrls[] = \stripslashes($sLinkWithWrap);
|
|
||||||
return $aMatch[1].
|
|
||||||
static::OPEN_LINK.
|
|
||||||
(\count($aPrepearPlainStringUrls) - 1).
|
|
||||||
static::CLOSE_LINK.
|
|
||||||
$aMatch[6];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $aMatch[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return '';
|
|
||||||
|
|
||||||
}, $sText);
|
|
||||||
|
|
||||||
if (\count($aPrepearPlainStringUrls))
|
|
||||||
{
|
|
||||||
$this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sText;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $fWrapper
|
|
||||||
*/
|
|
||||||
private function findMails(string $sText, $fWrapper) : string
|
|
||||||
{
|
|
||||||
$sPattern = '/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/';
|
|
||||||
|
|
||||||
$aPrepearPlainStringUrls = $this->aPrepearPlainStringUrls;
|
|
||||||
$sText = \preg_replace_callback($sPattern, function ($aMatch) use ($fWrapper, &$aPrepearPlainStringUrls) {
|
|
||||||
|
|
||||||
if (\is_array($aMatch) && isset($aMatch[1]))
|
|
||||||
{
|
|
||||||
$sMailWithWrap = $fWrapper($aMatch[1]);
|
|
||||||
if (\is_string($sMailWithWrap) && \strlen($sMailWithWrap))
|
|
||||||
{
|
|
||||||
$aPrepearPlainStringUrls[] = \stripslashes($sMailWithWrap);
|
|
||||||
return static::OPEN_LINK.
|
|
||||||
(\count($aPrepearPlainStringUrls) - 1).
|
|
||||||
static::CLOSE_LINK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $aMatch[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return '';
|
|
||||||
|
|
||||||
}, $sText);
|
|
||||||
|
|
||||||
if (\count($aPrepearPlainStringUrls))
|
|
||||||
{
|
|
||||||
$this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -17,10 +17,7 @@ namespace MailSo\Base;
|
||||||
*/
|
*/
|
||||||
abstract class ResourceRegistry
|
abstract class ResourceRegistry
|
||||||
{
|
{
|
||||||
/**
|
public static array $Resources = array();
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
public static $Resources = array();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @staticvar bool $bInited
|
* @staticvar bool $bInited
|
||||||
|
|
@ -28,16 +25,12 @@ abstract class ResourceRegistry
|
||||||
private static function regResourcesShutdownFunc() : void
|
private static function regResourcesShutdownFunc() : void
|
||||||
{
|
{
|
||||||
static $bInited = false;
|
static $bInited = false;
|
||||||
if (!$bInited)
|
if (!$bInited) {
|
||||||
{
|
|
||||||
$bInited = true;
|
$bInited = true;
|
||||||
\register_shutdown_function(function () {
|
\register_shutdown_function(function () {
|
||||||
if (\is_array(static::$Resources))
|
if (\is_array(static::$Resources)) {
|
||||||
{
|
foreach (\array_keys(static::$Resources) as $sKey) {
|
||||||
foreach (\array_keys(static::$Resources) as $sKey)
|
if (\is_resource(static::$Resources[$sKey])) {
|
||||||
{
|
|
||||||
if (\is_resource(static::$Resources[$sKey]))
|
|
||||||
{
|
|
||||||
\fclose(static::$Resources[$sKey]);
|
\fclose(static::$Resources[$sKey]);
|
||||||
}
|
}
|
||||||
static::$Resources[$sKey] = null;
|
static::$Resources[$sKey] = null;
|
||||||
|
|
@ -57,8 +50,7 @@ abstract class ResourceRegistry
|
||||||
self::regResourcesShutdownFunc();
|
self::regResourcesShutdownFunc();
|
||||||
|
|
||||||
$oResult = \fopen('php://temp/maxmemory:'.($iMemoryMaxInMb * 1024 * 1024), 'r+b');
|
$oResult = \fopen('php://temp/maxmemory:'.($iMemoryMaxInMb * 1024 * 1024), 'r+b');
|
||||||
if (\is_resource($oResult))
|
if (\is_resource($oResult)) {
|
||||||
{
|
|
||||||
static::$Resources[(string) $oResult] = $oResult;
|
static::$Resources[(string) $oResult] = $oResult;
|
||||||
return $oResult;
|
return $oResult;
|
||||||
}
|
}
|
||||||
|
|
@ -72,8 +64,7 @@ abstract class ResourceRegistry
|
||||||
public static function CreateMemoryResourceFromString(string $sString)
|
public static function CreateMemoryResourceFromString(string $sString)
|
||||||
{
|
{
|
||||||
$oResult = self::CreateMemoryResource();
|
$oResult = self::CreateMemoryResource();
|
||||||
if (\is_resource($oResult))
|
if (\is_resource($oResult)) {
|
||||||
{
|
|
||||||
\fwrite($oResult, $sString);
|
\fwrite($oResult, $sString);
|
||||||
\rewind($oResult);
|
\rewind($oResult);
|
||||||
}
|
}
|
||||||
|
|
@ -86,18 +77,15 @@ abstract class ResourceRegistry
|
||||||
*/
|
*/
|
||||||
public static function CloseMemoryResource(&$rResource) : void
|
public static function CloseMemoryResource(&$rResource) : void
|
||||||
{
|
{
|
||||||
if (\is_resource($rResource))
|
if (\is_resource($rResource)) {
|
||||||
{
|
|
||||||
$sKey = (string) $rResource;
|
$sKey = (string) $rResource;
|
||||||
if (isset(static::$Resources[$sKey]))
|
if (isset(static::$Resources[$sKey])) {
|
||||||
{
|
|
||||||
\fclose(static::$Resources[$sKey]);
|
\fclose(static::$Resources[$sKey]);
|
||||||
static::$Resources[$sKey] = null;
|
static::$Resources[$sKey] = null;
|
||||||
unset(static::$Resources[$sKey]);
|
unset(static::$Resources[$sKey]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\is_resource($rResource))
|
if (\is_resource($rResource)) {
|
||||||
{
|
|
||||||
\fclose($rResource);
|
\fclose($rResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,50 +27,26 @@ class Binary
|
||||||
*/
|
*/
|
||||||
const STREAM_NAME = 'mailsobinary';
|
const STREAM_NAME = 'mailsobinary';
|
||||||
|
|
||||||
/**
|
private static array $aStreams = array();
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $aStreams = array();
|
|
||||||
|
|
||||||
/**
|
private static array $aRememberStreams = array();
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $aRememberStreams = array();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var resource
|
* @var resource
|
||||||
*/
|
*/
|
||||||
private $rStream;
|
private $rStream;
|
||||||
|
|
||||||
/**
|
private string $sFromEncoding;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sFromEncoding;
|
|
||||||
|
|
||||||
/**
|
private string $sToEncoding;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sToEncoding;
|
|
||||||
|
|
||||||
/**
|
private string $sFunctionName;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sFunctionName;
|
|
||||||
|
|
||||||
/**
|
private int $iPos;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iPos;
|
|
||||||
|
|
||||||
/**
|
private string $sBuffer;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sBuffer;
|
|
||||||
|
|
||||||
/**
|
private string $sReadEndBuffer;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sReadEndBuffer;
|
|
||||||
|
|
||||||
public static function GetInlineDecodeOrEncodeFunctionName(string $sContentTransferEncoding, bool $bDecode = true) : string
|
public static function GetInlineDecodeOrEncodeFunctionName(string $sContentTransferEncoding, bool $bDecode = true) : string
|
||||||
{
|
{
|
||||||
|
|
@ -96,8 +72,7 @@ class Binary
|
||||||
$sEndBuffer = '';
|
$sEndBuffer = '';
|
||||||
$iQuotedPrintableLen = \strlen($sEncodedString);
|
$iQuotedPrintableLen = \strlen($sEncodedString);
|
||||||
$iLastSpace = \strrpos($sEncodedString, ' ');
|
$iLastSpace = \strrpos($sEncodedString, ' ');
|
||||||
if (false !== $iLastSpace && $iLastSpace + 1 < $iQuotedPrintableLen)
|
if (false !== $iLastSpace && $iLastSpace + 1 < $iQuotedPrintableLen) {
|
||||||
{
|
|
||||||
$sEndBuffer = \substr($sEncodedString, $iLastSpace + 1);
|
$sEndBuffer = \substr($sEncodedString, $iLastSpace + 1);
|
||||||
$sEncodedString = \substr($sEncodedString, 0, $iLastSpace + 1);
|
$sEncodedString = \substr($sEncodedString, 0, $iLastSpace + 1);
|
||||||
}
|
}
|
||||||
|
|
@ -109,10 +84,8 @@ class Binary
|
||||||
*/
|
*/
|
||||||
public static function IsStreamRemembed($rStream) : bool
|
public static function IsStreamRemembed($rStream) : bool
|
||||||
{
|
{
|
||||||
foreach (self::$aRememberStreams as $rRem)
|
foreach (self::$aRememberStreams as $rRem) {
|
||||||
{
|
if ($rStream === $rRem) {
|
||||||
if ($rStream === $rRem)
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,8 +98,7 @@ class Binary
|
||||||
*/
|
*/
|
||||||
public static function RememberStream($rStream)
|
public static function RememberStream($rStream)
|
||||||
{
|
{
|
||||||
if (!self::IsStreamRemembed($rStream))
|
if (!self::IsStreamRemembed($rStream)) {
|
||||||
{
|
|
||||||
self::$aRememberStreams[] = $rStream;
|
self::$aRememberStreams[] = $rStream;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -139,15 +111,13 @@ class Binary
|
||||||
public static function CreateStream($rStream,
|
public static function CreateStream($rStream,
|
||||||
string $sUtilsDecodeOrEncodeFunctionName = null, string $sFromEncoding = null, string $sToEncoding = null)
|
string $sUtilsDecodeOrEncodeFunctionName = null, string $sFromEncoding = null, string $sToEncoding = null)
|
||||||
{
|
{
|
||||||
if (null === $sUtilsDecodeOrEncodeFunctionName || !\strlen($sUtilsDecodeOrEncodeFunctionName))
|
if (null === $sUtilsDecodeOrEncodeFunctionName || !\strlen($sUtilsDecodeOrEncodeFunctionName)) {
|
||||||
{
|
|
||||||
$sUtilsDecodeOrEncodeFunctionName = 'InlineNullDecode';
|
$sUtilsDecodeOrEncodeFunctionName = 'InlineNullDecode';
|
||||||
}
|
}
|
||||||
|
|
||||||
$sHashName = \md5(\microtime(true).\rand(1000, 9999));
|
$sHashName = \md5(\microtime(true).\rand(1000, 9999));
|
||||||
|
|
||||||
if (null !== $sFromEncoding && null !== $sToEncoding && $sFromEncoding !== $sToEncoding)
|
if (null !== $sFromEncoding && null !== $sToEncoding && $sFromEncoding !== $sToEncoding) {
|
||||||
{
|
|
||||||
$rStream = self::CreateStream($rStream, $sUtilsDecodeOrEncodeFunctionName);
|
$rStream = self::CreateStream($rStream, $sUtilsDecodeOrEncodeFunctionName);
|
||||||
$sUtilsDecodeOrEncodeFunctionName = 'InlineConvertDecode';
|
$sUtilsDecodeOrEncodeFunctionName = 'InlineConvertDecode';
|
||||||
}
|
}
|
||||||
|
|
@ -216,27 +186,19 @@ class Binary
|
||||||
$sReturn = '';
|
$sReturn = '';
|
||||||
$sFunctionName = $this->sFunctionName;
|
$sFunctionName = $this->sFunctionName;
|
||||||
|
|
||||||
if ($iCount > 0)
|
if ($iCount > 0) {
|
||||||
{
|
if ($iCount < \strlen($this->sBuffer)) {
|
||||||
if ($iCount < \strlen($this->sBuffer))
|
|
||||||
{
|
|
||||||
$sReturn = \substr($this->sBuffer, 0, $iCount);
|
$sReturn = \substr($this->sBuffer, 0, $iCount);
|
||||||
$this->sBuffer = \substr($this->sBuffer, $iCount);
|
$this->sBuffer = \substr($this->sBuffer, $iCount);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sReturn = $this->sBuffer;
|
$sReturn = $this->sBuffer;
|
||||||
while ($iCount > 0)
|
while ($iCount > 0) {
|
||||||
{
|
if (\feof($this->rStream)) {
|
||||||
if (\feof($this->rStream))
|
if (!\strlen($this->sBuffer.$sReturn)) {
|
||||||
{
|
|
||||||
if (!\strlen($this->sBuffer.$sReturn))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\strlen($this->sReadEndBuffer))
|
if (\strlen($this->sReadEndBuffer)) {
|
||||||
{
|
|
||||||
$sReturn .= self::$sFunctionName($this->sReadEndBuffer,
|
$sReturn .= self::$sFunctionName($this->sReadEndBuffer,
|
||||||
$this->sReadEndBuffer, $this->sFromEncoding, $this->sToEncoding);
|
$this->sReadEndBuffer, $this->sFromEncoding, $this->sToEncoding);
|
||||||
|
|
||||||
|
|
@ -245,12 +207,9 @@ class Binary
|
||||||
|
|
||||||
$iCount = 0;
|
$iCount = 0;
|
||||||
$this->sBuffer = '';
|
$this->sBuffer = '';
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sReadResult = \fread($this->rStream, 8192);
|
$sReadResult = \fread($this->rStream, 8192);
|
||||||
if (false === $sReadResult)
|
if (false === $sReadResult) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -258,14 +217,11 @@ class Binary
|
||||||
$this->sReadEndBuffer, $this->sFromEncoding, $this->sToEncoding);
|
$this->sReadEndBuffer, $this->sFromEncoding, $this->sToEncoding);
|
||||||
|
|
||||||
$iDecodeLen = \strlen($sReadResult);
|
$iDecodeLen = \strlen($sReadResult);
|
||||||
if ($iCount < $iDecodeLen)
|
if ($iCount < $iDecodeLen) {
|
||||||
{
|
|
||||||
$this->sBuffer = \substr($sReturn, $iCount);
|
$this->sBuffer = \substr($sReturn, $iCount);
|
||||||
$sReturn = \substr($sReturn, 0, $iCount);
|
$sReturn = \substr($sReturn, 0, $iCount);
|
||||||
$iCount = 0;
|
$iCount = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$iCount -= $iDecodeLen;
|
$iCount -= $iDecodeLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,25 +26,16 @@ class Literal
|
||||||
*/
|
*/
|
||||||
const STREAM_NAME = 'mailsoliteral';
|
const STREAM_NAME = 'mailsoliteral';
|
||||||
|
|
||||||
/**
|
private static array $aStreams = array();
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $aStreams = array();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var resource
|
* @var resource
|
||||||
*/
|
*/
|
||||||
private $rStream;
|
private $rStream;
|
||||||
|
|
||||||
/**
|
private int $iSize;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iSize;
|
|
||||||
|
|
||||||
/**
|
private int $iPos;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iPos;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param resource $rStream
|
* @param resource $rStream
|
||||||
|
|
@ -95,20 +86,16 @@ class Literal
|
||||||
public function stream_read(int $iCount) : string
|
public function stream_read(int $iCount) : string
|
||||||
{
|
{
|
||||||
$sResult = false;
|
$sResult = false;
|
||||||
if ($this->iSize < $this->iPos + $iCount)
|
if ($this->iSize < $this->iPos + $iCount) {
|
||||||
{
|
|
||||||
$iCount = $this->iSize - $this->iPos;
|
$iCount = $this->iSize - $this->iPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($iCount > 0)
|
if ($iCount > 0) {
|
||||||
{
|
|
||||||
$sReadResult = '';
|
$sReadResult = '';
|
||||||
$iRead = $iCount;
|
$iRead = $iCount;
|
||||||
while (0 < $iRead)
|
while (0 < $iRead) {
|
||||||
{
|
|
||||||
$sAddRead = \fread($this->rStream, $iRead);
|
$sAddRead = \fread($this->rStream, $iRead);
|
||||||
if (false === $sAddRead)
|
if (false === $sAddRead) {
|
||||||
{
|
|
||||||
$sReadResult = false;
|
$sReadResult = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -118,8 +105,7 @@ class Literal
|
||||||
$this->iPos += \strlen($sAddRead);
|
$this->iPos += \strlen($sAddRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false !== $sReadResult)
|
if (false !== $sReadResult) {
|
||||||
{
|
|
||||||
$sResult = $sReadResult;
|
$sResult = $sReadResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -163,6 +149,8 @@ class Literal
|
||||||
|
|
||||||
public function stream_seek() : bool
|
public function stream_seek() : bool
|
||||||
{
|
{
|
||||||
|
// $this->iPos = $offset;
|
||||||
|
// \fseek($this->rStream, $offset, $whence);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,35 +27,17 @@ class SubStreams
|
||||||
*/
|
*/
|
||||||
const STREAM_NAME = 'mailsosubstreams';
|
const STREAM_NAME = 'mailsosubstreams';
|
||||||
|
|
||||||
/**
|
private static array $aStreams = array();
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $aStreams = array();
|
|
||||||
|
|
||||||
/**
|
private array $aSubStreams;
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $aSubStreams;
|
|
||||||
|
|
||||||
/**
|
private int $iIndex;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iIndex;
|
|
||||||
|
|
||||||
/**
|
private string $sBuffer;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sBuffer;
|
|
||||||
|
|
||||||
/**
|
private bool $bIsEnd;
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $bIsEnd;
|
|
||||||
|
|
||||||
/**
|
private int $iPos;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iPos;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return resource|bool
|
* @return resource|bool
|
||||||
|
|
@ -72,20 +54,6 @@ class SubStreams
|
||||||
return \fopen(self::STREAM_NAME.'://'.$sHashName, 'rb');
|
return \fopen(self::STREAM_NAME.'://'.$sHashName, 'rb');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return resource|null
|
|
||||||
*/
|
|
||||||
protected function &getPart()
|
|
||||||
{
|
|
||||||
$nNull = null;
|
|
||||||
if (isset($this->aSubStreams[$this->iIndex]))
|
|
||||||
{
|
|
||||||
return $this->aSubStreams[$this->iIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $nNull;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function stream_open(string $sPath) : bool
|
public function stream_open(string $sPath) : bool
|
||||||
{
|
{
|
||||||
$this->aSubStreams = array();
|
$this->aSubStreams = array();
|
||||||
|
|
@ -119,53 +87,41 @@ class SubStreams
|
||||||
{
|
{
|
||||||
$sReturn = '';
|
$sReturn = '';
|
||||||
$mCurrentPart = null;
|
$mCurrentPart = null;
|
||||||
if ($iCount > 0)
|
if ($iCount > 0) {
|
||||||
{
|
if ($iCount < \strlen($this->sBuffer)) {
|
||||||
if ($iCount < \strlen($this->sBuffer))
|
|
||||||
{
|
|
||||||
$sReturn = \substr($this->sBuffer, 0, $iCount);
|
$sReturn = \substr($this->sBuffer, 0, $iCount);
|
||||||
$this->sBuffer = \substr($this->sBuffer, $iCount);
|
$this->sBuffer = \substr($this->sBuffer, $iCount);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sReturn = $this->sBuffer;
|
$sReturn = $this->sBuffer;
|
||||||
while ($iCount > 0)
|
while ($iCount > 0) {
|
||||||
{
|
$mCurrentPart = isset($this->aSubStreams[$this->iIndex])
|
||||||
$mCurrentPart =& $this->getPart();
|
? $this->aSubStreams[$this->iIndex]
|
||||||
if (null === $mCurrentPart)
|
: null;
|
||||||
{
|
if (null === $mCurrentPart) {
|
||||||
$this->bIsEnd = true;
|
$this->bIsEnd = true;
|
||||||
$this->sBuffer = '';
|
$this->sBuffer = '';
|
||||||
$iCount = 0;
|
$iCount = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\is_resource($mCurrentPart))
|
if (\is_resource($mCurrentPart)) {
|
||||||
{
|
if (!\feof($mCurrentPart)) {
|
||||||
if (!\feof($mCurrentPart))
|
|
||||||
{
|
|
||||||
$sReadResult = \fread($mCurrentPart, 8192);
|
$sReadResult = \fread($mCurrentPart, 8192);
|
||||||
if (false === $sReadResult)
|
if (false === $sReadResult) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$sReturn .= $sReadResult;
|
$sReturn .= $sReadResult;
|
||||||
}
|
} else {
|
||||||
else
|
++$this->iIndex;
|
||||||
{
|
|
||||||
$this->iIndex++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$iLen = \strlen($sReturn);
|
$iLen = \strlen($sReturn);
|
||||||
if ($iCount < $iLen)
|
if ($iCount < $iLen) {
|
||||||
{
|
|
||||||
$this->sBuffer = \substr($sReturn, $iCount);
|
$this->sBuffer = \substr($sReturn, $iCount);
|
||||||
$sReturn = \substr($sReturn, 0, $iCount);
|
$sReturn = \substr($sReturn, 0, $iCount);
|
||||||
$iCount = 0;
|
$iCount = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$iCount -= $iLen;
|
$iCount -= $iLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -214,6 +170,8 @@ class SubStreams
|
||||||
|
|
||||||
public function stream_seek() : bool
|
public function stream_seek() : bool
|
||||||
{
|
{
|
||||||
|
// $this->iPos = $offset;
|
||||||
|
// foreach ($this->aSubStreams as $rStream) \fseek($rStream, $offset, $whence);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,15 +59,11 @@ class TempFile
|
||||||
self::STREAM_NAME === $aPath['scheme'])
|
self::STREAM_NAME === $aPath['scheme'])
|
||||||
{
|
{
|
||||||
$sHashName = $aPath['host'];
|
$sHashName = $aPath['host'];
|
||||||
if (isset(self::$aStreams[$sHashName]) &&
|
if (isset(self::$aStreams[$sHashName]) && \is_resource(self::$aStreams[$sHashName])) {
|
||||||
\is_resource(self::$aStreams[$sHashName]))
|
|
||||||
{
|
|
||||||
$this->rStream = self::$aStreams[$sHashName];
|
$this->rStream = self::$aStreams[$sHashName];
|
||||||
\fseek($this->rStream, 0);
|
\fseek($this->rStream, 0);
|
||||||
$bResult = true;
|
$bResult = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$this->rStream = \fopen('php://temp', 'r+b');
|
$this->rStream = \fopen('php://temp', 'r+b');
|
||||||
self::$aStreams[$sHashName] = $this->rStream;
|
self::$aStreams[$sHashName] = $this->rStream;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,8 +190,7 @@ abstract class Utils
|
||||||
public static function FormatFileSize(int $iSize, int $iRound = 0) : string
|
public static function FormatFileSize(int $iSize, int $iRound = 0) : string
|
||||||
{
|
{
|
||||||
$aSizes = array('B', 'KB', 'MB');
|
$aSizes = array('B', 'KB', 'MB');
|
||||||
for ($iIndex = 0; $iSize > 1024 && isset($aSizes[$iIndex + 1]); $iIndex++)
|
for ($iIndex = 0; $iSize > 1024 && isset($aSizes[$iIndex + 1]); ++$iIndex) {
|
||||||
{
|
|
||||||
$iSize /= 1024;
|
$iSize /= 1024;
|
||||||
}
|
}
|
||||||
return \round($iSize, $iRound).$aSizes[$iIndex];
|
return \round($iSize, $iRound).$aSizes[$iIndex];
|
||||||
|
|
@ -223,12 +222,10 @@ abstract class Utils
|
||||||
public static function DecodeHeaderValue(string $sEncodedValue, string $sIncomingCharset = '', string $sForcedIncomingCharset = '') : string
|
public static function DecodeHeaderValue(string $sEncodedValue, string $sIncomingCharset = '', string $sForcedIncomingCharset = '') : string
|
||||||
{
|
{
|
||||||
$sValue = $sEncodedValue;
|
$sValue = $sEncodedValue;
|
||||||
if (\strlen($sIncomingCharset))
|
if (\strlen($sIncomingCharset)) {
|
||||||
{
|
|
||||||
$sIncomingCharset = static::NormalizeCharsetByValue($sIncomingCharset, $sValue);
|
$sIncomingCharset = static::NormalizeCharsetByValue($sIncomingCharset, $sValue);
|
||||||
|
|
||||||
$sValue = static::ConvertEncoding($sValue, $sIncomingCharset,
|
$sValue = static::ConvertEncoding($sValue, $sIncomingCharset, Enumerations\Charset::UTF_8);
|
||||||
Enumerations\Charset::UTF_8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$sValue = \preg_replace('/\?=[\n\r\t\s]{1,5}=\?/m', '?==?', $sValue);
|
$sValue = \preg_replace('/\?=[\n\r\t\s]{1,5}=\?/m', '?==?', $sValue);
|
||||||
|
|
@ -239,15 +236,11 @@ abstract class Utils
|
||||||
// \preg_match_all('/=\?[^\?]+\?[q|b|Q|B]\?[^\?]*?\?=/', $sValue, $aMatch);
|
// \preg_match_all('/=\?[^\?]+\?[q|b|Q|B]\?[^\?]*?\?=/', $sValue, $aMatch);
|
||||||
\preg_match_all('/=\?[^\?]+\?[q|b|Q|B]\?.*?\?=/', $sValue, $aMatch);
|
\preg_match_all('/=\?[^\?]+\?[q|b|Q|B]\?.*?\?=/', $sValue, $aMatch);
|
||||||
|
|
||||||
if (isset($aMatch[0]) && \is_array($aMatch[0]))
|
if (isset($aMatch[0]) && \is_array($aMatch[0])) {
|
||||||
{
|
for ($iIndex = 0, $iLen = \count($aMatch[0]); $iIndex < $iLen; ++$iIndex) {
|
||||||
for ($iIndex = 0, $iLen = \count($aMatch[0]); $iIndex < $iLen; $iIndex++)
|
if (isset($aMatch[0][$iIndex])) {
|
||||||
{
|
|
||||||
if (isset($aMatch[0][$iIndex]))
|
|
||||||
{
|
|
||||||
$iPos = \strpos($aMatch[0][$iIndex], '*');
|
$iPos = \strpos($aMatch[0][$iIndex], '*');
|
||||||
if (false !== $iPos)
|
if (false !== $iPos) {
|
||||||
{
|
|
||||||
$aMatch[0][$iIndex][0] = \substr($aMatch[0][$iIndex][0], 0, $iPos);
|
$aMatch[0][$iIndex][0] = \substr($aMatch[0][$iIndex][0], 0, $iPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -261,11 +254,9 @@ abstract class Utils
|
||||||
$sMainCharset = '';
|
$sMainCharset = '';
|
||||||
$bOneCharset = true;
|
$bOneCharset = true;
|
||||||
|
|
||||||
for ($iIndex = 0, $iLen = \count($aEncodeArray); $iIndex < $iLen; $iIndex++)
|
for ($iIndex = 0, $iLen = \count($aEncodeArray); $iIndex < $iLen; ++$iIndex) {
|
||||||
{
|
|
||||||
$aTempArr = array('', $aEncodeArray[$iIndex]);
|
$aTempArr = array('', $aEncodeArray[$iIndex]);
|
||||||
if ('=?' === \substr(\trim($aTempArr[1]), 0, 2))
|
if ('=?' === \substr(\trim($aTempArr[1]), 0, 2)) {
|
||||||
{
|
|
||||||
$iPos = \strpos($aTempArr[1], '?', 2);
|
$iPos = \strpos($aTempArr[1], '?', 2);
|
||||||
$aTempArr[0] = \substr($aTempArr[1], 2, $iPos - 2);
|
$aTempArr[0] = \substr($aTempArr[1], 2, $iPos - 2);
|
||||||
$sEncType = \strtoupper($aTempArr[1][$iPos + 1]);
|
$sEncType = \strtoupper($aTempArr[1][$iPos + 1]);
|
||||||
|
|
@ -284,17 +275,13 @@ abstract class Utils
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\strlen($aTempArr[0]))
|
if (\strlen($aTempArr[0])) {
|
||||||
{
|
|
||||||
$sCharset = \strlen($sForcedIncomingCharset) ? $sForcedIncomingCharset : $aTempArr[0];
|
$sCharset = \strlen($sForcedIncomingCharset) ? $sForcedIncomingCharset : $aTempArr[0];
|
||||||
$sCharset = static::NormalizeCharset($sCharset, true);
|
$sCharset = static::NormalizeCharset($sCharset, true);
|
||||||
|
|
||||||
if ('' === $sMainCharset)
|
if ('' === $sMainCharset) {
|
||||||
{
|
|
||||||
$sMainCharset = $sCharset;
|
$sMainCharset = $sCharset;
|
||||||
}
|
} else if ($sMainCharset !== $sCharset) {
|
||||||
else if ($sMainCharset !== $sCharset)
|
|
||||||
{
|
|
||||||
$bOneCharset = false;
|
$bOneCharset = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -308,14 +295,10 @@ abstract class Utils
|
||||||
unset($aTempArr);
|
unset($aTempArr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ($iIndex = 0, $iLen = \count($aParts); $iIndex < $iLen; $iIndex++)
|
for ($iIndex = 0, $iLen = \count($aParts); $iIndex < $iLen; ++$iIndex) {
|
||||||
{
|
if ($bOneCharset) {
|
||||||
if ($bOneCharset)
|
|
||||||
{
|
|
||||||
$sValue = \str_replace($aParts[$iIndex][0], $aParts[$iIndex][1], $sValue);
|
$sValue = \str_replace($aParts[$iIndex][0], $aParts[$iIndex][1], $sValue);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aParts[$iIndex][2] = static::NormalizeCharsetByValue($aParts[$iIndex][2], $aParts[$iIndex][1]);
|
$aParts[$iIndex][2] = static::NormalizeCharsetByValue($aParts[$iIndex][2], $aParts[$iIndex][1]);
|
||||||
|
|
||||||
$sValue = \str_replace($aParts[$iIndex][0],
|
$sValue = \str_replace($aParts[$iIndex][0],
|
||||||
|
|
@ -324,8 +307,7 @@ abstract class Utils
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bOneCharset && \strlen($sMainCharset))
|
if ($bOneCharset && \strlen($sMainCharset)) {
|
||||||
{
|
|
||||||
$sMainCharset = static::NormalizeCharsetByValue($sMainCharset, $sValue);
|
$sMainCharset = static::NormalizeCharsetByValue($sMainCharset, $sValue);
|
||||||
$sValue = static::ConvertEncoding($sValue, $sMainCharset, Enumerations\Charset::UTF_8);
|
$sValue = static::ConvertEncoding($sValue, $sMainCharset, Enumerations\Charset::UTF_8);
|
||||||
}
|
}
|
||||||
|
|
@ -337,8 +319,7 @@ abstract class Utils
|
||||||
{
|
{
|
||||||
$sResultHeaders = $sIncHeaders;
|
$sResultHeaders = $sIncHeaders;
|
||||||
|
|
||||||
if ($aHeadersToRemove)
|
if ($aHeadersToRemove) {
|
||||||
{
|
|
||||||
$aHeadersToRemove = \array_map('strtolower', $aHeadersToRemove);
|
$aHeadersToRemove = \array_map('strtolower', $aHeadersToRemove);
|
||||||
|
|
||||||
$sIncHeaders = \preg_replace('/[\r\n]+/', "\n", $sIncHeaders);
|
$sIncHeaders = \preg_replace('/[\r\n]+/', "\n", $sIncHeaders);
|
||||||
|
|
@ -347,31 +328,21 @@ abstract class Utils
|
||||||
$bSkip = false;
|
$bSkip = false;
|
||||||
$aResult = array();
|
$aResult = array();
|
||||||
|
|
||||||
foreach ($aHeaders as $sLine)
|
foreach ($aHeaders as $sLine) {
|
||||||
{
|
if (\strlen($sLine)) {
|
||||||
if (\strlen($sLine))
|
|
||||||
{
|
|
||||||
$sFirst = \substr($sLine,0,1);
|
$sFirst = \substr($sLine,0,1);
|
||||||
if (' ' === $sFirst || "\t" === $sFirst)
|
if (' ' === $sFirst || "\t" === $sFirst) {
|
||||||
{
|
if (!$bSkip) {
|
||||||
if (!$bSkip)
|
|
||||||
{
|
|
||||||
$aResult[] = $sLine;
|
$aResult[] = $sLine;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$bSkip = false;
|
$bSkip = false;
|
||||||
$aParts = \explode(':', $sLine, 2);
|
$aParts = \explode(':', $sLine, 2);
|
||||||
|
|
||||||
if (!empty($aParts) && !empty($aParts[0]))
|
if (!empty($aParts) && !empty($aParts[0])) {
|
||||||
{
|
if (\in_array(\strtolower(\trim($aParts[0])), $aHeadersToRemove)) {
|
||||||
if (\in_array(\strtolower(\trim($aParts[0])), $aHeadersToRemove))
|
|
||||||
{
|
|
||||||
$bSkip = true;
|
$bSkip = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$aResult[] = $sLine;
|
$aResult[] = $sLine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -388,20 +359,17 @@ abstract class Utils
|
||||||
public static function EncodeUnencodedValue(string $sEncodeType, string $sValue) : string
|
public static function EncodeUnencodedValue(string $sEncodeType, string $sValue) : string
|
||||||
{
|
{
|
||||||
$sValue = \trim($sValue);
|
$sValue = \trim($sValue);
|
||||||
if (\strlen($sValue) && !static::IsAscii($sValue))
|
if (\strlen($sValue) && !static::IsAscii($sValue)) {
|
||||||
{
|
|
||||||
switch (\strtoupper($sEncodeType))
|
switch (\strtoupper($sEncodeType))
|
||||||
{
|
{
|
||||||
case 'B':
|
case 'B':
|
||||||
$sValue = '=?'.\strtolower(Enumerations\Charset::UTF_8).
|
return '=?'.\strtolower(Enumerations\Charset::UTF_8).
|
||||||
'?B?'.\base64_encode($sValue).'?=';
|
'?B?'.\base64_encode($sValue).'?=';
|
||||||
break;
|
|
||||||
|
|
||||||
case 'Q':
|
case 'Q':
|
||||||
$sValue = '=?'.\strtolower(Enumerations\Charset::UTF_8).
|
return '=?'.\strtolower(Enumerations\Charset::UTF_8).
|
||||||
'?Q?'.\str_replace(array('?', ' ', '_'), array('=3F', '_', '=5F'),
|
'?Q?'.\str_replace(array('?', ' ', '_'), array('=3F', '_', '=5F'),
|
||||||
\quoted_printable_encode($sValue)).'?=';
|
\quoted_printable_encode($sValue)).'?=';
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -418,41 +386,32 @@ abstract class Utils
|
||||||
$iNlen = \strlen($sAttrName);
|
$iNlen = \strlen($sAttrName);
|
||||||
$iVlen = \strlen($sValue);
|
$iVlen = \strlen($sValue);
|
||||||
|
|
||||||
if (\strlen($sAttrName) + $iVlen > $iLen - 3)
|
if (\strlen($sAttrName) + $iVlen > $iLen - 3) {
|
||||||
{
|
|
||||||
$sections = array();
|
$sections = array();
|
||||||
$section = 0;
|
$section = 0;
|
||||||
|
|
||||||
for ($i = 0, $j = 0; $i < $iVlen; $i += $j)
|
for ($i = 0, $j = 0; $i < $iVlen; $i += $j) {
|
||||||
{
|
|
||||||
$j = $iLen - $iNlen - \strlen($section) - 4;
|
$j = $iLen - $iNlen - \strlen($section) - 4;
|
||||||
$sections[$section++] = \substr($sValue, $i, $j);
|
$sections[$section++] = \substr($sValue, $i, $j);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ($i = 0, $n = $section; $i < $n; $i++)
|
for ($i = 0, $n = $section; $i < $n; ++$i) {
|
||||||
{
|
|
||||||
$sections[$i] = ' '.$sAttrName.'*'.$i.'*='.$sections[$i];
|
$sections[$i] = ' '.$sAttrName.'*'.$i.'*='.$sections[$i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return \implode(";\r\n", $sections);
|
return \implode(";\r\n", $sections);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return $sAttrName.'*='.$sValue;
|
return $sAttrName.'*='.$sValue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static function EncodeHeaderUtf8AttributeValue(string $sAttrName, string $sValue) : string
|
public static function EncodeHeaderUtf8AttributeValue(string $sAttrName, string $sValue) : string
|
||||||
{
|
{
|
||||||
$sAttrName = \trim($sAttrName);
|
$sAttrName = \trim($sAttrName);
|
||||||
$sValue = \trim($sValue);
|
$sValue = \trim($sValue);
|
||||||
|
|
||||||
if (\strlen($sValue) && !static::IsAscii($sValue))
|
if (\strlen($sValue) && !static::IsAscii($sValue)) {
|
||||||
{
|
|
||||||
$sValue = static::AttributeRfc2231Encode($sAttrName, $sValue);
|
$sValue = static::AttributeRfc2231Encode($sAttrName, $sValue);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sValue = $sAttrName.'="'.\str_replace('"', '\\"', $sValue).'"';
|
$sValue = $sAttrName.'="'.\str_replace('"', '\\"', $sValue).'"';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -462,8 +421,7 @@ abstract class Utils
|
||||||
public static function GetAccountNameFromEmail(string $sEmail) : string
|
public static function GetAccountNameFromEmail(string $sEmail) : string
|
||||||
{
|
{
|
||||||
$sResult = '';
|
$sResult = '';
|
||||||
if (\strlen($sEmail))
|
if (\strlen($sEmail)) {
|
||||||
{
|
|
||||||
$iPos = \strrpos($sEmail, '@');
|
$iPos = \strrpos($sEmail, '@');
|
||||||
$sResult = (false === $iPos) ? $sEmail : \substr($sEmail, 0, $iPos);
|
$sResult = (false === $iPos) ? $sEmail : \substr($sEmail, 0, $iPos);
|
||||||
}
|
}
|
||||||
|
|
@ -474,11 +432,9 @@ abstract class Utils
|
||||||
public static function GetDomainFromEmail(string $sEmail) : string
|
public static function GetDomainFromEmail(string $sEmail) : string
|
||||||
{
|
{
|
||||||
$sResult = '';
|
$sResult = '';
|
||||||
if (\strlen($sEmail))
|
if (\strlen($sEmail)) {
|
||||||
{
|
|
||||||
$iPos = \strrpos($sEmail, '@');
|
$iPos = \strrpos($sEmail, '@');
|
||||||
if (false !== $iPos && 0 < $iPos)
|
if (false !== $iPos && 0 < $iPos) {
|
||||||
{
|
|
||||||
$sResult = \substr($sEmail, $iPos + 1);
|
$sResult = \substr($sEmail, $iPos + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -563,8 +519,7 @@ abstract class Utils
|
||||||
public static function ResetTimeLimit(int $iTimeToReset = 15, int $iTimeToAdd = 120) : bool
|
public static function ResetTimeLimit(int $iTimeToReset = 15, int $iTimeToAdd = 120) : bool
|
||||||
{
|
{
|
||||||
$iTime = \time();
|
$iTime = \time();
|
||||||
if ($iTime < $_SERVER['REQUEST_TIME_FLOAT'] + 5)
|
if ($iTime < $_SERVER['REQUEST_TIME_FLOAT'] + 5) {
|
||||||
{
|
|
||||||
// do nothing first 5s
|
// do nothing first 5s
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -572,18 +527,15 @@ abstract class Utils
|
||||||
static $bValidateAction = null;
|
static $bValidateAction = null;
|
||||||
static $iResetTimer = null;
|
static $iResetTimer = null;
|
||||||
|
|
||||||
if (null === $bValidateAction)
|
if (null === $bValidateAction) {
|
||||||
{
|
|
||||||
$iResetTimer = 0;
|
$iResetTimer = 0;
|
||||||
|
|
||||||
$bValidateAction = static::FunctionCallable('set_time_limit');
|
$bValidateAction = static::FunctionCallable('set_time_limit');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bValidateAction && $iTimeToReset < $iTime - $iResetTimer)
|
if ($bValidateAction && $iTimeToReset < $iTime - $iResetTimer) {
|
||||||
{
|
|
||||||
$iResetTimer = $iTime;
|
$iResetTimer = $iTime;
|
||||||
if (!\set_time_limit($iTimeToAdd))
|
if (!\set_time_limit($iTimeToAdd)) {
|
||||||
{
|
|
||||||
$bValidateAction = false;
|
$bValidateAction = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -675,24 +627,19 @@ abstract class Utils
|
||||||
public static function Base64Decode(string $sString) : string
|
public static function Base64Decode(string $sString) : string
|
||||||
{
|
{
|
||||||
$sResultString = \base64_decode($sString, true);
|
$sResultString = \base64_decode($sString, true);
|
||||||
if (false === $sResultString)
|
if (false === $sResultString) {
|
||||||
{
|
|
||||||
$sString = \str_replace(array(' ', "\r", "\n", "\t"), '', $sString);
|
$sString = \str_replace(array(' ', "\r", "\n", "\t"), '', $sString);
|
||||||
$sString = \preg_replace('/[^a-zA-Z0-9=+\/](.*)$/', '', $sString);
|
$sString = \preg_replace('/[^a-zA-Z0-9=+\/](.*)$/', '', $sString);
|
||||||
|
|
||||||
if (false !== \strpos(\trim(\trim($sString), '='), '='))
|
if (false !== \strpos(\trim(\trim($sString), '='), '=')) {
|
||||||
{
|
|
||||||
$sString = \preg_replace('/=([^=])/', '= $1', $sString);
|
$sString = \preg_replace('/=([^=])/', '= $1', $sString);
|
||||||
$aStrings = \explode(' ', $sString);
|
$aStrings = \explode(' ', $sString);
|
||||||
foreach ($aStrings as $iIndex => $sParts)
|
foreach ($aStrings as $iIndex => $sParts) {
|
||||||
{
|
|
||||||
$aStrings[$iIndex] = \base64_decode($sParts);
|
$aStrings[$iIndex] = \base64_decode($sParts);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sResultString = \implode('', $aStrings);
|
$sResultString = \implode('', $aStrings);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sResultString = \base64_decode($sString);
|
$sResultString = \base64_decode($sString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -715,23 +662,16 @@ abstract class Utils
|
||||||
*/
|
*/
|
||||||
public static function FpassthruWithTimeLimitReset($fResource, int $iBufferLen = 8192) : bool
|
public static function FpassthruWithTimeLimitReset($fResource, int $iBufferLen = 8192) : bool
|
||||||
{
|
{
|
||||||
$bResult = false;
|
$bResult = \is_resource($fResource);
|
||||||
if (\is_resource($fResource))
|
if ($bResult) {
|
||||||
{
|
while (!\feof($fResource)) {
|
||||||
while (!\feof($fResource))
|
|
||||||
{
|
|
||||||
$sBuffer = \fread($fResource, $iBufferLen);
|
$sBuffer = \fread($fResource, $iBufferLen);
|
||||||
if (false !== $sBuffer)
|
if (false === $sBuffer) {
|
||||||
{
|
|
||||||
echo $sBuffer;
|
|
||||||
static::ResetTimeLimit();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
echo $sBuffer;
|
||||||
$bResult = true;
|
static::ResetTimeLimit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $bResult;
|
return $bResult;
|
||||||
|
|
@ -743,53 +683,42 @@ abstract class Utils
|
||||||
public static function MultipleStreamWriter($rRead, array $aWrite, int $iBufferLen = 8192, bool $bResetTimeLimit = true, bool $bFixCrLf = false, bool $bRewindOnComplete = false) : int
|
public static function MultipleStreamWriter($rRead, array $aWrite, int $iBufferLen = 8192, bool $bResetTimeLimit = true, bool $bFixCrLf = false, bool $bRewindOnComplete = false) : int
|
||||||
{
|
{
|
||||||
$mResult = false;
|
$mResult = false;
|
||||||
if (\is_resource($rRead) && \count($aWrite))
|
if (\is_resource($rRead) && \count($aWrite)) {
|
||||||
{
|
|
||||||
$mResult = 0;
|
$mResult = 0;
|
||||||
while (!\feof($rRead))
|
while (!\feof($rRead)) {
|
||||||
{
|
|
||||||
$sBuffer = \fread($rRead, $iBufferLen);
|
$sBuffer = \fread($rRead, $iBufferLen);
|
||||||
if (false === $sBuffer)
|
if (false === $sBuffer) {
|
||||||
{
|
|
||||||
$mResult = false;
|
$mResult = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('' === $sBuffer)
|
if ('' === $sBuffer) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bFixCrLf)
|
if ($bFixCrLf) {
|
||||||
{
|
|
||||||
$sBuffer = \str_replace("\n", "\r\n", \str_replace("\r", '', $sBuffer));
|
$sBuffer = \str_replace("\n", "\r\n", \str_replace("\r", '', $sBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
$mResult += \strlen($sBuffer);
|
$mResult += \strlen($sBuffer);
|
||||||
|
|
||||||
foreach ($aWrite as $rWriteStream)
|
foreach ($aWrite as $rWriteStream) {
|
||||||
{
|
|
||||||
$mWriteResult = \fwrite($rWriteStream, $sBuffer);
|
$mWriteResult = \fwrite($rWriteStream, $sBuffer);
|
||||||
if (false === $mWriteResult)
|
if (false === $mWriteResult) {
|
||||||
{
|
|
||||||
$mResult = false;
|
$mResult = false;
|
||||||
break 2;
|
break 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bResetTimeLimit)
|
if ($bResetTimeLimit) {
|
||||||
{
|
|
||||||
static::ResetTimeLimit();
|
static::ResetTimeLimit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($mResult && $bRewindOnComplete)
|
if ($mResult && $bRewindOnComplete) {
|
||||||
{
|
foreach ($aWrite as $rWriteStream) {
|
||||||
foreach ($aWrite as $rWriteStream)
|
if (\is_resource($rWriteStream)) {
|
||||||
{
|
|
||||||
if (\is_resource($rWriteStream))
|
|
||||||
{
|
|
||||||
\rewind($rWriteStream);
|
\rewind($rWriteStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -843,8 +772,7 @@ abstract class Utils
|
||||||
public static function ValidateDomain(string $sDomain, bool $bSimple = false) : bool
|
public static function ValidateDomain(string $sDomain, bool $bSimple = false) : bool
|
||||||
{
|
{
|
||||||
$aMatch = array();
|
$aMatch = array();
|
||||||
if ($bSimple)
|
if ($bSimple) {
|
||||||
{
|
|
||||||
return \preg_match('/.+(\.[a-zA-Z]+)$/', $sDomain, $aMatch) && !empty($aMatch[1]);
|
return \preg_match('/.+(\.[a-zA-Z]+)$/', $sDomain, $aMatch) && !empty($aMatch[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -861,8 +789,7 @@ abstract class Utils
|
||||||
|
|
||||||
public static function IdnToUtf8(string $sStr, bool $bLowerIfAscii = false) : string
|
public static function IdnToUtf8(string $sStr, bool $bLowerIfAscii = false) : string
|
||||||
{
|
{
|
||||||
if (\strlen($sStr) && \preg_match('/(^|\.|@)xn--/i', $sStr))
|
if (\strlen($sStr) && \preg_match('/(^|\.|@)xn--/i', $sStr)) {
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$sStr = \SnappyMail\IDN::anyToUtf8($sStr);
|
$sStr = \SnappyMail\IDN::anyToUtf8($sStr);
|
||||||
|
|
@ -879,14 +806,12 @@ abstract class Utils
|
||||||
|
|
||||||
$sUser = '';
|
$sUser = '';
|
||||||
$sDomain = $sStr;
|
$sDomain = $sStr;
|
||||||
if (false !== \strpos($sStr, '@'))
|
if (false !== \strpos($sStr, '@')) {
|
||||||
{
|
|
||||||
$sUser = static::GetAccountNameFromEmail($sStr);
|
$sUser = static::GetAccountNameFromEmail($sStr);
|
||||||
$sDomain = static::GetDomainFromEmail($sStr);
|
$sDomain = static::GetDomainFromEmail($sStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\strlen($sDomain) && \preg_match('/[^\x20-\x7E]/', $sDomain))
|
if (\strlen($sDomain) && \preg_match('/[^\x20-\x7E]/', $sDomain)) {
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$sDomain = \SnappyMail\IDN::anyToAscii($sDomain);
|
$sDomain = \SnappyMail\IDN::anyToAscii($sDomain);
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,8 @@ class Xxtea
|
||||||
{
|
{
|
||||||
$aV = self::str2long($sString, true);
|
$aV = self::str2long($sString, true);
|
||||||
$aK = self::str2long($sKey, false);
|
$aK = self::str2long($sKey, false);
|
||||||
if (\count($aK) < 4)
|
if (\count($aK) < 4) {
|
||||||
{
|
for ($iIndex = \count($aK); $iIndex < 4; $iIndex++) {
|
||||||
for ($iIndex = \count($aK); $iIndex < 4; $iIndex++)
|
|
||||||
{
|
|
||||||
$aK[$iIndex] = 0;
|
$aK[$iIndex] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -36,12 +34,10 @@ class Xxtea
|
||||||
$iDelta = 0x9E3779B9;
|
$iDelta = 0x9E3779B9;
|
||||||
$iQ = \floor(6 + 52 / ($iN + 1));
|
$iQ = \floor(6 + 52 / ($iN + 1));
|
||||||
$iSum = 0;
|
$iSum = 0;
|
||||||
while (0 < $iQ--)
|
while (0 < $iQ--) {
|
||||||
{
|
|
||||||
$iSum = self::int32($iSum + $iDelta);
|
$iSum = self::int32($iSum + $iDelta);
|
||||||
$iE = $iSum >> 2 & 3;
|
$iE = $iSum >> 2 & 3;
|
||||||
for ($iPIndex = 0; $iPIndex < $iN; $iPIndex++)
|
for ($iPIndex = 0; $iPIndex < $iN; ++$iPIndex) {
|
||||||
{
|
|
||||||
$iY = $aV[$iPIndex + 1];
|
$iY = $aV[$iPIndex + 1];
|
||||||
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
|
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
|
||||||
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
|
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
|
||||||
|
|
@ -61,10 +57,8 @@ class Xxtea
|
||||||
$aV = self::str2long($sEncryptedString, false);
|
$aV = self::str2long($sEncryptedString, false);
|
||||||
$aK = self::str2long($sKey, false);
|
$aK = self::str2long($sKey, false);
|
||||||
|
|
||||||
if (\count($aK) < 4)
|
if (\count($aK) < 4) {
|
||||||
{
|
for ($iIndex = \count($aK); $iIndex < 4; ++$iIndex) {
|
||||||
for ($iIndex = \count($aK); $iIndex < 4; $iIndex++)
|
|
||||||
{
|
|
||||||
$aK[$iIndex] = 0;
|
$aK[$iIndex] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -76,11 +70,9 @@ class Xxtea
|
||||||
$iDelta = 0x9E3779B9;
|
$iDelta = 0x9E3779B9;
|
||||||
$iQ = \floor(6 + 52 / ($iN + 1));
|
$iQ = \floor(6 + 52 / ($iN + 1));
|
||||||
$iSum = self::int32($iQ * $iDelta);
|
$iSum = self::int32($iQ * $iDelta);
|
||||||
while ($iSum != 0)
|
while ($iSum != 0) {
|
||||||
{
|
|
||||||
$iE = $iSum >> 2 & 3;
|
$iE = $iSum >> 2 & 3;
|
||||||
for ($iPIndex = $iN; $iPIndex > 0; $iPIndex--)
|
for ($iPIndex = $iN; $iPIndex > 0; --$iPIndex) {
|
||||||
{
|
|
||||||
$iZ = $aV[$iPIndex - 1];
|
$iZ = $aV[$iPIndex - 1];
|
||||||
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
|
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
|
||||||
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
|
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
|
||||||
|
|
@ -100,33 +92,25 @@ class Xxtea
|
||||||
{
|
{
|
||||||
$iLen = \count($aV);
|
$iLen = \count($aV);
|
||||||
$iN = ($iLen - 1) << 2;
|
$iN = ($iLen - 1) << 2;
|
||||||
if ($aW)
|
if ($aW) {
|
||||||
{
|
|
||||||
$iM = $aV[$iLen - 1];
|
$iM = $aV[$iLen - 1];
|
||||||
if (($iM < $iN - 3) || ($iM > $iN))
|
if (($iM < $iN - 3) || ($iM > $iN)) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$iN = $iM;
|
$iN = $iM;
|
||||||
}
|
}
|
||||||
$aS = array();
|
$aS = array();
|
||||||
for ($iIndex = 0; $iIndex < $iLen; $iIndex++)
|
for ($iIndex = 0; $iIndex < $iLen; ++$iIndex) {
|
||||||
{
|
|
||||||
$aS[$iIndex] = \pack('V', $aV[$iIndex]);
|
$aS[$iIndex] = \pack('V', $aV[$iIndex]);
|
||||||
}
|
}
|
||||||
if ($aW)
|
return $aW ? \substr(\join('', $aS), 0, $iN) : \join('', $aS);
|
||||||
{
|
|
||||||
return \substr(\join('', $aS), 0, $iN);
|
|
||||||
}
|
|
||||||
return \join('', $aS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function str2long(string $sS, string $sW) : array
|
private static function str2long(string $sS, string $sW) : array
|
||||||
{
|
{
|
||||||
$aV = \unpack('V*', $sS . \str_repeat("\0", (4 - \strlen($sS) % 4) & 3));
|
$aV = \unpack('V*', $sS . \str_repeat("\0", (4 - \strlen($sS) % 4) & 3));
|
||||||
$aV = \array_values($aV);
|
$aV = \array_values($aV);
|
||||||
if ($sW)
|
if ($sW) {
|
||||||
{
|
|
||||||
$aV[\count($aV)] = \strlen($sS);
|
$aV[\count($aV)] = \strlen($sS);
|
||||||
}
|
}
|
||||||
return $aV;
|
return $aV;
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,7 @@ class CacheClient
|
||||||
*/
|
*/
|
||||||
private $oDriver;
|
private $oDriver;
|
||||||
|
|
||||||
/**
|
private string $sCacheIndex = '';
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sCacheIndex = '';
|
|
||||||
|
|
||||||
public function Set(string $sKey, string $sValue) : bool
|
public function Set(string $sKey, string $sValue) : bool
|
||||||
{
|
{
|
||||||
|
|
@ -56,13 +53,11 @@ class CacheClient
|
||||||
{
|
{
|
||||||
$sValue = '';
|
$sValue = '';
|
||||||
|
|
||||||
if ($this->oDriver)
|
if ($this->oDriver) {
|
||||||
{
|
|
||||||
$sValue = $this->oDriver->Get($sKey.$this->sCacheIndex);
|
$sValue = $this->oDriver->Get($sKey.$this->sCacheIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bClearAfterGet)
|
if ($bClearAfterGet) {
|
||||||
{
|
|
||||||
$this->Delete($sKey);
|
$this->Delete($sKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,8 +68,7 @@ class CacheClient
|
||||||
{
|
{
|
||||||
$iTimer = 0;
|
$iTimer = 0;
|
||||||
$sValue = $this->Get($sKey.'/TIMER');
|
$sValue = $this->Get($sKey.'/TIMER');
|
||||||
if (\strlen($sValue) && is_numeric($sValue))
|
if (\strlen($sValue) && \is_numeric($sValue)) {
|
||||||
{
|
|
||||||
$iTimer = (int) $sValue;
|
$iTimer = (int) $sValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,8 +77,7 @@ class CacheClient
|
||||||
|
|
||||||
public function Delete(string $sKey) : self
|
public function Delete(string $sKey) : self
|
||||||
{
|
{
|
||||||
if ($this->oDriver)
|
if ($this->oDriver) {
|
||||||
{
|
|
||||||
$this->oDriver->Delete($sKey.$this->sCacheIndex);
|
$this->oDriver->Delete($sKey.$this->sCacheIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,11 +110,9 @@ class CacheClient
|
||||||
|
|
||||||
public function Verify(bool $bCache = false) : bool
|
public function Verify(bool $bCache = false) : bool
|
||||||
{
|
{
|
||||||
if ($this->oDriver)
|
if ($this->oDriver) {
|
||||||
{
|
|
||||||
$sCacheData = \gmdate('Y-m-d-H');
|
$sCacheData = \gmdate('Y-m-d-H');
|
||||||
if ($bCache && $sCacheData === $this->Get('__verify_key__'))
|
if ($bCache && $sCacheData === $this->Get('__verify_key__')) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,19 +18,13 @@ namespace MailSo\Cache\Drivers;
|
||||||
*/
|
*/
|
||||||
class APCU implements \MailSo\Cache\DriverInterface
|
class APCU implements \MailSo\Cache\DriverInterface
|
||||||
{
|
{
|
||||||
/**
|
private string $sKeyPrefix;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sKeyPrefix;
|
|
||||||
|
|
||||||
function __construct(string $sKeyPrefix = '')
|
function __construct(string $sKeyPrefix = '')
|
||||||
{
|
{
|
||||||
$this->sKeyPrefix = $sKeyPrefix;
|
$this->sKeyPrefix = empty($sKeyPrefix)
|
||||||
if (!empty($this->sKeyPrefix))
|
? $sKeyPrefix
|
||||||
{
|
: \preg_replace('/[^a-zA-Z0-9_]/', '_', \rtrim(\trim($sKeyPrefix), '\\/')).'/';
|
||||||
$this->sKeyPrefix =
|
|
||||||
\preg_replace('/[^a-zA-Z0-9_]/', '_', rtrim(trim($this->sKeyPrefix), '\\/')).'/';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Set(string $sKey, string $sValue) : bool
|
public function Set(string $sKey, string $sValue) : bool
|
||||||
|
|
@ -51,12 +45,7 @@ class APCU implements \MailSo\Cache\DriverInterface
|
||||||
|
|
||||||
public function GC(int $iTimeToClearInHours = 24) : bool
|
public function GC(int $iTimeToClearInHours = 24) : bool
|
||||||
{
|
{
|
||||||
if (0 === $iTimeToClearInHours)
|
return (0 === $iTimeToClearInHours) ? \apcu_clear_cache('user') : false;
|
||||||
{
|
|
||||||
return \apcu_clear_cache('user');
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generateCachedKey(string $sKey) : string
|
private function generateCachedKey(string $sKey) : string
|
||||||
|
|
|
||||||
|
|
@ -18,37 +18,27 @@ namespace MailSo\Cache\Drivers;
|
||||||
*/
|
*/
|
||||||
class Memcache implements \MailSo\Cache\DriverInterface
|
class Memcache implements \MailSo\Cache\DriverInterface
|
||||||
{
|
{
|
||||||
/**
|
private int $iExpire;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iExpire;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Memcache|null
|
* @var \Memcache|\Memcached|null
|
||||||
*/
|
*/
|
||||||
private $oMem;
|
private $oMem;
|
||||||
|
|
||||||
/**
|
private string $sKeyPrefix;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sKeyPrefix;
|
|
||||||
|
|
||||||
function __construct(string $sHost = '127.0.0.1', int $iPort = 11211, int $iExpire = 43200, string $sKeyPrefix = '')
|
function __construct(string $sHost = '127.0.0.1', int $iPort = 11211, int $iExpire = 43200, string $sKeyPrefix = '')
|
||||||
{
|
{
|
||||||
$this->iExpire = 0 < $iExpire ? $iExpire : 43200;
|
$this->iExpire = 0 < $iExpire ? $iExpire : 43200;
|
||||||
|
|
||||||
$this->oMem = \class_exists('Memcache',false) ? new \Memcache : new \Memcached;
|
$this->oMem = \class_exists('Memcache',false) ? new \Memcache : new \Memcached;
|
||||||
if (!$this->oMem->addServer($sHost, \strpos($sHost, ':/') ? 0 : $this->iPort))
|
if (!$this->oMem->addServer($sHost, \strpos($sHost, ':/') ? 0 : $iPort)) {
|
||||||
{
|
|
||||||
$this->oMem = null;
|
$this->oMem = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->sKeyPrefix = $sKeyPrefix;
|
$this->sKeyPrefix = empty($sKeyPrefix)
|
||||||
if (!empty($this->sKeyPrefix))
|
? $sKeyPrefix
|
||||||
{
|
: \preg_replace('/[^a-zA-Z0-9_]/', '_', \rtrim(\trim($this->sKeyPrefix), '\\/')) . '/';
|
||||||
$this->sKeyPrefix =
|
|
||||||
\preg_replace('/[^a-zA-Z0-9_]/', '_', rtrim(trim($this->sKeyPrefix), '\\/')).'/';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Set(string $sKey, string $sValue) : bool
|
public function Set(string $sKey, string $sValue) : bool
|
||||||
|
|
@ -64,19 +54,14 @@ class Memcache implements \MailSo\Cache\DriverInterface
|
||||||
|
|
||||||
public function Delete(string $sKey) : void
|
public function Delete(string $sKey) : void
|
||||||
{
|
{
|
||||||
if ($this->oMem)
|
$this->oMem && $this->oMem->delete($this->generateCachedKey($sKey));
|
||||||
{
|
|
||||||
$this->oMem->delete($this->generateCachedKey($sKey));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GC(int $iTimeToClearInHours = 24) : bool
|
public function GC(int $iTimeToClearInHours = 24) : bool
|
||||||
{
|
{
|
||||||
if (0 === $iTimeToClearInHours && $this->oMem)
|
if (0 === $iTimeToClearInHours && $this->oMem) {
|
||||||
{
|
|
||||||
return $this->oMem->flush();
|
return $this->oMem->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,21 +18,14 @@ namespace MailSo\Cache\Drivers;
|
||||||
*/
|
*/
|
||||||
class Redis implements \MailSo\Cache\DriverInterface
|
class Redis implements \MailSo\Cache\DriverInterface
|
||||||
{
|
{
|
||||||
/**
|
private int $iExpire;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iExpire;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Memcache|null
|
* @var \Predis\Client|null
|
||||||
*/
|
*/
|
||||||
private $oRedis;
|
private $oRedis;
|
||||||
|
|
||||||
/**
|
private string $sKeyPrefix;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sKeyPrefix;
|
|
||||||
|
|
||||||
|
|
||||||
function __construct(string $sHost = '127.0.0.1', int $iPort = 6379, int $iExpire = 43200, string $sKeyPrefix = '')
|
function __construct(string $sHost = '127.0.0.1', int $iPort = 6379, int $iExpire = 43200, string $sKeyPrefix = '')
|
||||||
{
|
{
|
||||||
|
|
@ -49,8 +42,7 @@ class Redis implements \MailSo\Cache\DriverInterface
|
||||||
|
|
||||||
$this->oRedis->connect();
|
$this->oRedis->connect();
|
||||||
|
|
||||||
if (!$this->oRedis->isConnected())
|
if (!$this->oRedis->isConnected()) {
|
||||||
{
|
|
||||||
$this->oRedis = null;
|
$this->oRedis = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -60,18 +52,14 @@ class Redis implements \MailSo\Cache\DriverInterface
|
||||||
unset($oExc);
|
unset($oExc);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->sKeyPrefix = $sKeyPrefix;
|
$this->sKeyPrefix = empty($sKeyPrefix)
|
||||||
if (!empty($this->sKeyPrefix))
|
? $sKeyPrefix
|
||||||
{
|
: \preg_replace('/[^a-zA-Z0-9_]/', '_', rtrim(trim($this->sKeyPrefix), '\\/')) . '/';
|
||||||
$this->sKeyPrefix =
|
|
||||||
\preg_replace('/[^a-zA-Z0-9_]/', '_', rtrim(trim($this->sKeyPrefix), '\\/')).'/';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Set(string $sKey, string $sValue) : bool
|
public function Set(string $sKey, string $sValue) : bool
|
||||||
{
|
{
|
||||||
if (!$this->oRedis)
|
if (!$this->oRedis) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,16 +76,14 @@ class Redis implements \MailSo\Cache\DriverInterface
|
||||||
|
|
||||||
public function Delete(string $sKey) : void
|
public function Delete(string $sKey) : void
|
||||||
{
|
{
|
||||||
if ($this->oRedis)
|
if ($this->oRedis) {
|
||||||
{
|
|
||||||
$this->oRedis->del($this->generateCachedKey($sKey));
|
$this->oRedis->del($this->generateCachedKey($sKey));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GC(int $iTimeToClearInHours = 24) : bool
|
public function GC(int $iTimeToClearInHours = 24) : bool
|
||||||
{
|
{
|
||||||
if (0 === $iTimeToClearInHours && $this->oRedis)
|
if (0 === $iTimeToClearInHours && $this->oRedis) {
|
||||||
{
|
|
||||||
return $this->oRedis->flushdb();
|
return $this->oRedis->flushdb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of MailSo.
|
|
||||||
*
|
|
||||||
* (c) 2014 Usenko Timur
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace MailSo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @category MailSo
|
|
||||||
*/
|
|
||||||
class Hooks
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
static $aCallbacks = array();
|
|
||||||
|
|
||||||
static public function Run(string $sName, array $aArg = array()) : void
|
|
||||||
{
|
|
||||||
if (isset(static::$aCallbacks[$sName]))
|
|
||||||
{
|
|
||||||
foreach (static::$aCallbacks[$sName] as $mCallback)
|
|
||||||
{
|
|
||||||
$mCallback(...$aArg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $mCallback
|
|
||||||
*/
|
|
||||||
static public function Add(string $sName, $mCallback) : void
|
|
||||||
{
|
|
||||||
if (\is_callable($mCallback))
|
|
||||||
{
|
|
||||||
if (!isset(static::$aCallbacks[$sName]))
|
|
||||||
{
|
|
||||||
static::$aCallbacks[$sName] = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
static::$aCallbacks[$sName][] = $mCallback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -17,70 +17,31 @@ namespace MailSo\Imap;
|
||||||
*/
|
*/
|
||||||
class BodyStructure
|
class BodyStructure
|
||||||
{
|
{
|
||||||
/**
|
private string $sContentType;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sContentType;
|
|
||||||
|
|
||||||
/**
|
private string $sCharset;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sCharset;
|
|
||||||
|
|
||||||
/**
|
private array $aBodyParams;
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $aBodyParams;
|
|
||||||
|
|
||||||
/**
|
private string $sContentID;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sContentID;
|
|
||||||
|
|
||||||
/**
|
private string $sDescription;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sDescription;
|
|
||||||
|
|
||||||
/**
|
private string $sMailEncodingName;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sMailEncodingName;
|
|
||||||
|
|
||||||
/**
|
private string $sDisposition;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sDisposition;
|
|
||||||
|
|
||||||
/**
|
private string $sFileName;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sFileName;
|
|
||||||
|
|
||||||
/**
|
private string $sLanguage = '';
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sLanguage = '';
|
|
||||||
|
|
||||||
/**
|
private string $sLocation = '';
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sLocation = '';
|
|
||||||
|
|
||||||
/**
|
private int $iSize;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iSize;
|
|
||||||
|
|
||||||
/**
|
private string $sPartID;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sPartID;
|
|
||||||
|
|
||||||
/**
|
private array $aSubParts;
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $aSubParts;
|
|
||||||
|
|
||||||
public function MailEncodingName() : string
|
public function MailEncodingName() : string
|
||||||
{
|
{
|
||||||
|
|
@ -385,8 +346,7 @@ class BodyStructure
|
||||||
|
|
||||||
public static function NewInstance(array $aBodyStructure, string $sPartID = '') : ?self
|
public static function NewInstance(array $aBodyStructure, string $sPartID = '') : ?self
|
||||||
{
|
{
|
||||||
if (2 > \count($aBodyStructure))
|
if (2 > \count($aBodyStructure)) {
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -587,20 +547,15 @@ class BodyStructure
|
||||||
$oStructure->sPartID = $sPartID;
|
$oStructure->sPartID = $sPartID;
|
||||||
$oStructure->aSubParts = $aSubParts;
|
$oStructure->aSubParts = $aSubParts;
|
||||||
|
|
||||||
if ($iExtraItemPos < \count($aBodyStructure))
|
if ($iExtraItemPos < \count($aBodyStructure)) {
|
||||||
{
|
if (\is_array($aBodyStructure[$iExtraItemPos])) {
|
||||||
if (\is_array($aBodyStructure[$iExtraItemPos]))
|
|
||||||
{
|
|
||||||
$oStructure->sLanguage = \implode(',', $aBodyStructure[$iExtraItemPos]);
|
$oStructure->sLanguage = \implode(',', $aBodyStructure[$iExtraItemPos]);
|
||||||
}
|
} else if (\is_string($aBodyStructure[$iExtraItemPos])) {
|
||||||
else if (\is_string($aBodyStructure[$iExtraItemPos]))
|
|
||||||
{
|
|
||||||
$oStructure->sLanguage = $aBodyStructure[$iExtraItemPos];
|
$oStructure->sLanguage = $aBodyStructure[$iExtraItemPos];
|
||||||
}
|
}
|
||||||
++$iExtraItemPos;
|
++$iExtraItemPos;
|
||||||
|
|
||||||
if ($iExtraItemPos < \count($aBodyStructure) && \is_string($aBodyStructure[$iExtraItemPos]))
|
if ($iExtraItemPos < \count($aBodyStructure) && \is_string($aBodyStructure[$iExtraItemPos])) {
|
||||||
{
|
|
||||||
$oStructure->sLocation = $aBodyStructure[$iExtraItemPos];
|
$oStructure->sLocation = $aBodyStructure[$iExtraItemPos];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,6 @@ namespace MailSo\Imap\Exceptions;
|
||||||
*/
|
*/
|
||||||
class ResponseException extends \MailSo\RuntimeException
|
class ResponseException extends \MailSo\RuntimeException
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $oResponses;
|
private $oResponses;
|
||||||
|
|
||||||
public function __construct(?\MailSo\Imap\ResponseCollection $oResponses = null, string $sMessage = '', int $iCode = 0, ?\Throwable $oPrevious = null)
|
public function __construct(?\MailSo\Imap\ResponseCollection $oResponses = null, string $sMessage = '', int $iCode = 0, ?\Throwable $oPrevious = null)
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ class FetchResponse
|
||||||
|
|
||||||
if (\is_string($mItem) && (
|
if (\is_string($mItem) && (
|
||||||
$mItem === 'BODY[HEADER]' ||
|
$mItem === 'BODY[HEADER]' ||
|
||||||
0 === \strpos($mItem, 'BODY[HEADER.FIELDS') ||
|
\str_starts_with($mItem, 'BODY[HEADER.FIELDS') ||
|
||||||
$mItem === 'BODY[MIME]'))
|
$mItem === 'BODY[MIME]'))
|
||||||
{
|
{
|
||||||
$bNextIsValue = true;
|
$bNextIsValue = true;
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (0 === \strpos($type, 'SCRAM-'))
|
if (\str_starts_with($type, 'SCRAM-'))
|
||||||
{
|
{
|
||||||
$sAuthzid = $this->getResponseValue($this->SendRequestGetResponse('AUTHENTICATE', array($type)), Enumerations\ResponseType::CONTINUATION);
|
$sAuthzid = $this->getResponseValue($this->SendRequestGetResponse('AUTHENTICATE', array($type)), Enumerations\ResponseType::CONTINUATION);
|
||||||
$this->sendRaw($SASL->authenticate($sLogin, $sPassword/*, $sAuthzid*/), true);
|
$this->sendRaw($SASL->authenticate($sLogin, $sPassword/*, $sAuthzid*/), true);
|
||||||
|
|
@ -377,9 +377,7 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
if (Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType
|
if (Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType
|
||||||
&& 'NAMESPACE' === $oResponse->StatusOrIndex)
|
&& 'NAMESPACE' === $oResponse->StatusOrIndex)
|
||||||
{
|
{
|
||||||
$oReturn = new NamespaceResult;
|
return new NamespaceResult($oResponse);
|
||||||
$oReturn->InitByImapResponse($oResponse);
|
|
||||||
return $oReturn;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Exceptions\ResponseException;
|
throw new Exceptions\ResponseException;
|
||||||
|
|
|
||||||
|
|
@ -17,75 +17,38 @@ namespace MailSo\Imap;
|
||||||
*/
|
*/
|
||||||
class NamespaceResult
|
class NamespaceResult
|
||||||
{
|
{
|
||||||
/**
|
private string $sPersonal = '';
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sPersonal = '';
|
|
||||||
|
|
||||||
/**
|
private string $sPersonalDelimiter = '';
|
||||||
* @var string
|
/*
|
||||||
*/
|
private string $sOtherUser = '';
|
||||||
private $sPersonalDelimiter = '';
|
|
||||||
|
|
||||||
/**
|
private string $sOtherUserDelimiter = '';
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sOtherUser = '';
|
|
||||||
|
|
||||||
/**
|
private string $sShared = '';
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sOtherUserDelimiter = '';
|
|
||||||
|
|
||||||
/**
|
private string $sSharedDelimiter = '';
|
||||||
* @var string
|
*/
|
||||||
*/
|
function __construct(Response $oImapResponse)
|
||||||
private $sShared = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sSharedDelimiter = '';
|
|
||||||
|
|
||||||
public function InitByImapResponse(\MailSo\Imap\Response $oImapResponse) : self
|
|
||||||
{
|
{
|
||||||
if ($oImapResponse)
|
$space = static::getNamespace($oImapResponse, 2);
|
||||||
{
|
if ($space) {
|
||||||
if (isset($oImapResponse->ResponseList[2][0]) &&
|
$this->sPersonal = $space[0];
|
||||||
\is_array($oImapResponse->ResponseList[2][0]) &&
|
$this->sPersonalDelimiter = $space[1];
|
||||||
2 <= \count($oImapResponse->ResponseList[2][0]))
|
}
|
||||||
{
|
/*
|
||||||
$this->sPersonal = $oImapResponse->ResponseList[2][0][0];
|
$space = static::getNamespace($oImapResponse, 3);
|
||||||
$this->sPersonalDelimiter = $oImapResponse->ResponseList[2][0][1];
|
if ($space) {
|
||||||
|
$this->sOtherUser = $space[0];
|
||||||
$this->sPersonal = 'INBOX'.$this->sPersonalDelimiter === \substr(\strtoupper($this->sPersonal), 0, 6) ?
|
$this->sOtherUserDelimiter = $space[1];
|
||||||
'INBOX'.$this->sPersonalDelimiter.\substr($this->sPersonal, 6) : $this->sPersonal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($oImapResponse->ResponseList[3][0]) &&
|
$space = static::getNamespace($oImapResponse, 4);
|
||||||
\is_array($oImapResponse->ResponseList[3][0]) &&
|
if ($space) {
|
||||||
2 <= \count($oImapResponse->ResponseList[3][0]))
|
$this->sShared = $space[0];
|
||||||
{
|
$this->sSharedDelimiter = $space[1];
|
||||||
$this->sOtherUser = $oImapResponse->ResponseList[3][0][0];
|
|
||||||
$this->sOtherUserDelimiter = $oImapResponse->ResponseList[3][0][1];
|
|
||||||
|
|
||||||
$this->sOtherUser = 'INBOX'.$this->sOtherUserDelimiter === \substr(\strtoupper($this->sOtherUser), 0, 6) ?
|
|
||||||
'INBOX'.$this->sOtherUserDelimiter.\substr($this->sOtherUser, 6) : $this->sOtherUser;
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if (isset($oImapResponse->ResponseList[4][0]) &&
|
|
||||||
\is_array($oImapResponse->ResponseList[4][0]) &&
|
|
||||||
2 <= \count($oImapResponse->ResponseList[4][0]))
|
|
||||||
{
|
|
||||||
$this->sShared = $oImapResponse->ResponseList[4][0][0];
|
|
||||||
$this->sSharedDelimiter = $oImapResponse->ResponseList[4][0][1];
|
|
||||||
|
|
||||||
$this->sShared = 'INBOX'.$this->sSharedDelimiter === \substr(\strtoupper($this->sShared), 0, 6) ?
|
|
||||||
'INBOX'.$this->sSharedDelimiter.\substr($this->sShared, 6) : $this->sShared;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetPersonalNamespace() : string
|
public function GetPersonalNamespace() : string
|
||||||
|
|
@ -93,4 +56,20 @@ class NamespaceResult
|
||||||
return $this->sPersonal;
|
return $this->sPersonal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function getNamespace(Response $oImapResponse, int $section) : ?array
|
||||||
|
{
|
||||||
|
if (isset($oImapResponse->ResponseList[$section][0])
|
||||||
|
&& \is_array($oImapResponse->ResponseList[$section][0])
|
||||||
|
&& 2 <= \count($oImapResponse->ResponseList[$section][0]))
|
||||||
|
{
|
||||||
|
$sName = $oImapResponse->ResponseList[$section][0][0];
|
||||||
|
$sDelimiter = $oImapResponse->ResponseList[$section][0][1];
|
||||||
|
$sName = 'INBOX'.$sDelimiter === \substr(\strtoupper($sName), 0, 6)
|
||||||
|
? 'INBOX'.$sDelimiter.\substr($sName, 6)
|
||||||
|
: $sName;
|
||||||
|
return [$sName, $sDelimiter];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@ namespace MailSo\Imap\Requests;
|
||||||
*/
|
*/
|
||||||
class ESEARCH extends Request
|
class ESEARCH extends Request
|
||||||
{
|
{
|
||||||
public
|
public string $sCriterias = 'ALL';
|
||||||
$sCriterias = 'ALL',
|
|
||||||
$aReturn = [
|
public array $aReturn = [
|
||||||
/**
|
/**
|
||||||
ALL
|
ALL
|
||||||
Return all message numbers/UIDs which match the search criteria,
|
Return all message numbers/UIDs which match the search criteria,
|
||||||
|
|
@ -41,14 +41,18 @@ class ESEARCH extends Request
|
||||||
Return all message numbers/UIDs which match the search criteria,
|
Return all message numbers/UIDs which match the search criteria,
|
||||||
in the requested sort order, using a sequence-set.
|
in the requested sort order, using a sequence-set.
|
||||||
*/
|
*/
|
||||||
],
|
];
|
||||||
$bUid = true,
|
|
||||||
$sLimit = '',
|
public bool $bUid = true;
|
||||||
$sCharset = '',
|
|
||||||
|
public string $sLimit = '';
|
||||||
|
|
||||||
|
public string $sCharset = '';
|
||||||
|
|
||||||
// https://datatracker.ietf.org/doc/html/rfc7377
|
// https://datatracker.ietf.org/doc/html/rfc7377
|
||||||
$aMailboxes = [],
|
public array $aMailboxes = [];
|
||||||
$aSubtrees = [],
|
public array $aSubtrees = [];
|
||||||
$aSubtreesOne = [];
|
public array $aSubtreesOne = [];
|
||||||
|
|
||||||
function __construct(\MailSo\Imap\ImapClient $oImapClient)
|
function __construct(\MailSo\Imap\ImapClient $oImapClient)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,7 @@ namespace MailSo\Imap\Requests;
|
||||||
|
|
||||||
abstract class Request
|
abstract class Request
|
||||||
{
|
{
|
||||||
protected
|
protected \MailSo\Imap\ImapClient $oImapClient;
|
||||||
$oImapClient;
|
|
||||||
|
|
||||||
function __construct(\MailSo\Imap\ImapClient $oImapClient)
|
function __construct(\MailSo\Imap\ImapClient $oImapClient)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,18 @@ namespace MailSo\Imap\Requests;
|
||||||
*/
|
*/
|
||||||
class SORT extends Request
|
class SORT extends Request
|
||||||
{
|
{
|
||||||
public
|
public string $sCriterias = 'ALL';
|
||||||
$sCriterias = 'ALL',
|
|
||||||
$sCharset = '',
|
public string $sCharset = '';
|
||||||
$bUid = true,
|
|
||||||
$aSortTypes = [],
|
public bool $bUid = true;
|
||||||
$sLimit = '',
|
|
||||||
|
public array $aSortTypes = [];
|
||||||
|
|
||||||
|
public string $sLimit = '';
|
||||||
|
|
||||||
// RFC 5267
|
// RFC 5267
|
||||||
$aReturn = [
|
public array $aReturn = [
|
||||||
/**
|
/**
|
||||||
ALL
|
ALL
|
||||||
Return all message numbers/UIDs which match the search criteria,
|
Return all message numbers/UIDs which match the search criteria,
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,12 @@ namespace MailSo\Imap\Requests;
|
||||||
*/
|
*/
|
||||||
class THREAD extends Request
|
class THREAD extends Request
|
||||||
{
|
{
|
||||||
public
|
// ORDEREDSUBJECT or REFERENCES or REFS
|
||||||
$sAlgorithm = '', // ORDEREDSUBJECT or REFERENCES or REFS
|
public string $sAlgorithm = '';
|
||||||
$sCriterias = 'ALL',
|
|
||||||
$bUid = true;
|
public string $sCriterias = 'ALL';
|
||||||
|
|
||||||
|
public bool $bUid = true;
|
||||||
|
|
||||||
function __construct(\MailSo\Imap\ImapClient $oImapClient)
|
function __construct(\MailSo\Imap\ImapClient $oImapClient)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -19,46 +19,24 @@ use MailSo\Imap\Enumerations\ResponseType;
|
||||||
*/
|
*/
|
||||||
class Response
|
class Response
|
||||||
{
|
{
|
||||||
/**
|
public array $ResponseList = array();
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
public $ResponseList = array();
|
|
||||||
|
|
||||||
/**
|
public ?array $OptionalResponse = null;
|
||||||
* @var array | null
|
|
||||||
*/
|
|
||||||
public $OptionalResponse = null;
|
|
||||||
|
|
||||||
/**
|
public ?string $StatusOrIndex = null;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $StatusOrIndex;
|
|
||||||
|
|
||||||
/**
|
public string $HumanReadable = '';
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $HumanReadable = '';
|
|
||||||
|
|
||||||
/**
|
public bool $IsStatusResponse = false;
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
public $IsStatusResponse = false;
|
|
||||||
|
|
||||||
/**
|
public int $ResponseType = 0;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $ResponseType = 0;
|
|
||||||
|
|
||||||
/**
|
public ?string $Tag = null;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $Tag;
|
|
||||||
|
|
||||||
private function recToLine(array $aList) : string
|
private function recToLine(array $aList) : string
|
||||||
{
|
{
|
||||||
$aResult = array();
|
$aResult = array();
|
||||||
foreach ($aList as $mItem)
|
foreach ($aList as $mItem) {
|
||||||
{
|
|
||||||
$aResult[] = \is_array($mItem) ? '('.$this->recToLine($mItem).')' : (string) $mItem;
|
$aResult[] = \is_array($mItem) ? '('.$this->recToLine($mItem).')' : (string) $mItem;
|
||||||
}
|
}
|
||||||
return \implode(' ', $aResult);
|
return \implode(' ', $aResult);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace MailSo\Imap\Responses;
|
||||||
*/
|
*/
|
||||||
class ACL implements \JsonSerializable
|
class ACL implements \JsonSerializable
|
||||||
{
|
{
|
||||||
private $rights;
|
private array $rights;
|
||||||
|
|
||||||
function __construct(array $rights)
|
function __construct(array $rights)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ class SequenceSet /*extends \SplFixedArray*/ implements \Countable
|
||||||
/**
|
/**
|
||||||
* By default the numbers are unique identifiers as this is more reliable.
|
* By default the numbers are unique identifiers as this is more reliable.
|
||||||
*/
|
*/
|
||||||
public $UID = true;
|
public bool $UID = true;
|
||||||
|
|
||||||
private $data = [];
|
private array $data = [];
|
||||||
|
|
||||||
public function __construct($mItems, bool $uid = true)
|
public function __construct($mItems, bool $uid = true)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -21,15 +21,9 @@ use MailSo\Imap\Exceptions\ResponseNotFoundException;
|
||||||
*/
|
*/
|
||||||
trait ResponseParser
|
trait ResponseParser
|
||||||
{
|
{
|
||||||
/**
|
private int $iResponseBufParsedPos;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iResponseBufParsedPos;
|
|
||||||
|
|
||||||
/**
|
private bool $bNeedNext = true;
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $bNeedNext = true;
|
|
||||||
|
|
||||||
protected function partialParseResponse() : Response
|
protected function partialParseResponse() : Response
|
||||||
{
|
{
|
||||||
|
|
@ -365,9 +359,9 @@ trait ResponseParser
|
||||||
}
|
}
|
||||||
|
|
||||||
$sLiteralAtomUpperCasePeek = '';
|
$sLiteralAtomUpperCasePeek = '';
|
||||||
if (0 === \strpos($sLiteralAtomUpperCase, 'BODY')) {
|
if (\str_starts_with($sLiteralAtomUpperCase, 'BODY')) {
|
||||||
$sLiteralAtomUpperCasePeek = \str_replace('BODY', 'BODY.PEEK', $sLiteralAtomUpperCase);
|
$sLiteralAtomUpperCasePeek = \str_replace('BODY', 'BODY.PEEK', $sLiteralAtomUpperCase);
|
||||||
} else if (0 === \strpos($sLiteralAtomUpperCase, 'BINARY')) {
|
} else if (\str_starts_with($sLiteralAtomUpperCase, 'BINARY')) {
|
||||||
$sLiteralAtomUpperCasePeek = \str_replace('BINARY', 'BINARY.PEEK', $sLiteralAtomUpperCase);
|
$sLiteralAtomUpperCasePeek = \str_replace('BINARY', 'BINARY.PEEK', $sLiteralAtomUpperCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,9 @@ namespace MailSo\Log;
|
||||||
*/
|
*/
|
||||||
abstract class Driver
|
abstract class Driver
|
||||||
{
|
{
|
||||||
/**
|
protected string
|
||||||
* @var string
|
$sDatePattern = 'H:i:s',
|
||||||
*/
|
$sName = '';
|
||||||
protected $sDatePattern = 'H:i:s';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $sName = '';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
|
|
@ -41,25 +35,13 @@ abstract class Driver
|
||||||
\LOG_DEBUG => '[DEBUG]'
|
\LOG_DEBUG => '[DEBUG]'
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
protected bool $bGuidPrefix = true;
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
protected $bGuidPrefix = true;
|
|
||||||
|
|
||||||
/**
|
protected \DateTimeZone $oTimeZone;
|
||||||
* @var DateTimeZone
|
|
||||||
*/
|
|
||||||
protected $oTimeZone;
|
|
||||||
|
|
||||||
/**
|
protected bool $bTimePrefix = true;
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
protected $bTimePrefix = true;
|
|
||||||
|
|
||||||
/**
|
protected bool $bTypedPrefix = true;
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
protected $bTypedPrefix = true;
|
|
||||||
|
|
||||||
function __construct()
|
function __construct()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,7 @@ namespace MailSo\Log\Drivers;
|
||||||
*/
|
*/
|
||||||
class File extends \MailSo\Log\Driver
|
class File extends \MailSo\Log\Driver
|
||||||
{
|
{
|
||||||
/**
|
private string $sLoggerFileName;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sLoggerFileName;
|
|
||||||
|
|
||||||
function __construct(string $sLoggerFileName)
|
function __construct(string $sLoggerFileName)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace MailSo\Log\Drivers;
|
||||||
*/
|
*/
|
||||||
class Syslog extends \MailSo\Log\Driver
|
class Syslog extends \MailSo\Log\Driver
|
||||||
{
|
{
|
||||||
private $iLogLevel;
|
private int $iLogLevel = 0;
|
||||||
|
|
||||||
function __construct()
|
function __construct()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -17,20 +17,19 @@ namespace MailSo\Log;
|
||||||
*/
|
*/
|
||||||
class Logger extends \SplFixedArray
|
class Logger extends \SplFixedArray
|
||||||
{
|
{
|
||||||
private $bUsed = false;
|
private bool $bUsed = false;
|
||||||
|
|
||||||
private $iLevel = \LOG_WARNING;
|
private int $iLevel = \LOG_WARNING;
|
||||||
|
|
||||||
private $aSecretWords = [];
|
private array $aSecretWords = [];
|
||||||
|
|
||||||
private $bShowSecrets = false;
|
private bool $bShowSecrets = false;
|
||||||
|
|
||||||
function __construct(bool $bMainLogger = false)
|
function __construct(bool $bMainLogger = false)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
if ($bMainLogger)
|
if ($bMainLogger) {
|
||||||
{
|
|
||||||
\set_error_handler(array($this, '__phpErrorHandler'));
|
\set_error_handler(array($this, '__phpErrorHandler'));
|
||||||
\set_exception_handler(array($this, '__phpExceptionHandler'));
|
\set_exception_handler(array($this, '__phpExceptionHandler'));
|
||||||
\register_shutdown_function(array($this, '__loggerShutDown'));
|
\register_shutdown_function(array($this, '__loggerShutDown'));
|
||||||
|
|
@ -43,8 +42,7 @@ class Logger extends \SplFixedArray
|
||||||
public static function Guid() : string
|
public static function Guid() : string
|
||||||
{
|
{
|
||||||
static $sCache = null;
|
static $sCache = null;
|
||||||
if (null === $sCache)
|
if (null === $sCache) {
|
||||||
{
|
|
||||||
$sCache = \substr(\MailSo\Base\Utils::Sha1Rand(), -8);
|
$sCache = \substr(\MailSo\Base\Utils::Sha1Rand(), -8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,15 +25,9 @@ use MailSo\Mime\Enumerations\Parameter as MimeParameter;
|
||||||
*/
|
*/
|
||||||
class MailClient
|
class MailClient
|
||||||
{
|
{
|
||||||
/**
|
private ?\MailSo\Log\Logger $oLogger = null;
|
||||||
* @var \MailSo\Log\Logger
|
|
||||||
*/
|
|
||||||
private $oLogger = null;
|
|
||||||
|
|
||||||
/**
|
private \MailSo\Imap\ImapClient $oImapClient;
|
||||||
* @var \MailSo\Imap\ImapClient
|
|
||||||
*/
|
|
||||||
private $oImapClient;
|
|
||||||
|
|
||||||
function __construct()
|
function __construct()
|
||||||
{
|
{
|
||||||
|
|
@ -759,7 +753,7 @@ class MailClient
|
||||||
|
|
||||||
if ($aAllThreads && !$oParams->iThreadUid) {
|
if ($aAllThreads && !$oParams->iThreadUid) {
|
||||||
foreach ($oMessageCollection as $oMessage) {
|
foreach ($oMessageCollection as $oMessage) {
|
||||||
$iUid = $oMessage->Uid();
|
$iUid = $oMessage->Uid;
|
||||||
// Find thread and set it.
|
// Find thread and set it.
|
||||||
// Used by GUI to delete/move the whole thread or other features
|
// Used by GUI to delete/move the whole thread or other features
|
||||||
foreach ($aAllThreads as $aMap) {
|
foreach ($aAllThreads as $aMap) {
|
||||||
|
|
|
||||||
|
|
@ -20,80 +20,74 @@ use \MailSo\Imap\Enumerations\FetchType;
|
||||||
*/
|
*/
|
||||||
class Message implements \JsonSerializable
|
class Message implements \JsonSerializable
|
||||||
{
|
{
|
||||||
private
|
private string
|
||||||
$sFolder = '',
|
$sFolder = '',
|
||||||
$iUid = 0,
|
|
||||||
$sSubject = '',
|
$sSubject = '',
|
||||||
$sMessageId = '',
|
$sMessageId = '',
|
||||||
$sContentType = '',
|
$sContentType = '',
|
||||||
$iSize = 0,
|
|
||||||
$iSpamScore = 0,
|
|
||||||
$sSpamResult = '',
|
$sSpamResult = '',
|
||||||
$bIsSpam = false,
|
|
||||||
$bHasVirus = null,
|
|
||||||
$sVirusScanned = '',
|
$sVirusScanned = '',
|
||||||
$iInternalTimeStampInUTC = 0,
|
$InReplyTo = '',
|
||||||
$iHeaderTimeStampInUTC = 0,
|
$sPlain = '',
|
||||||
$sHeaderDate = '',
|
$sHtml = '',
|
||||||
// $aFlags = [],
|
$References = '',
|
||||||
$aFlagsLowerCase = [],
|
$sDeliveryReceipt = '',
|
||||||
|
$ReadReceipt = '';
|
||||||
|
|
||||||
|
private ?string
|
||||||
/**
|
/**
|
||||||
* https://www.rfc-editor.org/rfc/rfc8474#section-5
|
* https://www.rfc-editor.org/rfc/rfc8474#section-5
|
||||||
*/
|
*/
|
||||||
$sEmailId = '',
|
$sEmailId = null,
|
||||||
$sThreadId = '',
|
$sThreadId = null,
|
||||||
|
// https://autocrypt.org/level1.html#the-autocrypt-header
|
||||||
|
$sAutocrypt = '';
|
||||||
|
|
||||||
|
private int
|
||||||
|
$Uid = 0,
|
||||||
|
$iSize = 0,
|
||||||
|
$SpamScore = 0,
|
||||||
|
$iInternalTimeStampInUTC = 0,
|
||||||
|
$HeaderTimeStampInUTC = 0,
|
||||||
|
$iPriority = \MailSo\Mime\Enumerations\MessagePriority::NORMAL;
|
||||||
|
|
||||||
|
private bool
|
||||||
|
$bIsSpam = false;
|
||||||
|
|
||||||
|
private ?bool
|
||||||
/**
|
/**
|
||||||
* @var \MailSo\Mime\EmailCollection
|
* null = not scanned
|
||||||
|
* true = scanned and infected
|
||||||
|
* false = scanned and no infection found
|
||||||
*/
|
*/
|
||||||
|
$bHasVirus = null;
|
||||||
|
|
||||||
|
private array
|
||||||
|
// $aFlags = [],
|
||||||
|
$aFlagsLowerCase = [],
|
||||||
|
$UnsubsribeLinks = [],
|
||||||
|
$aThreads = [];
|
||||||
|
|
||||||
|
private ?array
|
||||||
|
$DraftInfo = null,
|
||||||
|
$pgpSigned = null,
|
||||||
|
$pgpEncrypted = null;
|
||||||
|
|
||||||
|
private ?\MailSo\Mime\EmailCollection
|
||||||
$oFrom = null,
|
$oFrom = null,
|
||||||
$oSender = null,
|
$oSender = null,
|
||||||
$oReplyTo = null,
|
$oReplyTo = null,
|
||||||
$oDeliveredTo = null,
|
$oDeliveredTo = null,
|
||||||
$oTo = null,
|
$oTo = null,
|
||||||
$oCc = null,
|
$oCc = null,
|
||||||
$oBcc = null,
|
$oBcc = null;
|
||||||
|
|
||||||
$sInReplyTo = '',
|
private ?AttachmentCollection
|
||||||
|
$Attachments = null;
|
||||||
|
|
||||||
$sPlain = '',
|
function __get($k)
|
||||||
$sHtml = '',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var AttachmentCollection
|
|
||||||
*/
|
|
||||||
$oAttachments = null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
$aDraftInfo = null,
|
|
||||||
|
|
||||||
$sReferences = '',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
$iPriority,
|
|
||||||
|
|
||||||
$sDeliveryReceipt = '',
|
|
||||||
|
|
||||||
$sReadReceipt = '',
|
|
||||||
|
|
||||||
// https://autocrypt.org/level1.html#the-autocrypt-header
|
|
||||||
$sAutocrypt = '',
|
|
||||||
|
|
||||||
$aUnsubsribeLinks = array(),
|
|
||||||
|
|
||||||
$aThreads = array(),
|
|
||||||
|
|
||||||
$aPgpSigned = null,
|
|
||||||
$aPgpEncrypted = null;
|
|
||||||
|
|
||||||
function __construct()
|
|
||||||
{
|
{
|
||||||
$this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::NORMAL;
|
return \property_exists($this, $k) ? $this->$k : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Plain() : string
|
public function Plain() : string
|
||||||
|
|
@ -106,174 +100,9 @@ class Message implements \JsonSerializable
|
||||||
return $this->sHtml;
|
return $this->sHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function PgpSigned() : ?array
|
|
||||||
{
|
|
||||||
return $this->aPgpSigned;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function PgpEncrypted() : ?array
|
|
||||||
{
|
|
||||||
return $this->aPgpEncrypted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Folder() : string
|
|
||||||
{
|
|
||||||
return $this->sFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Uid() : int
|
|
||||||
{
|
|
||||||
return $this->iUid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function MessageId() : string
|
|
||||||
{
|
|
||||||
return $this->sMessageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Subject() : string
|
|
||||||
{
|
|
||||||
return $this->sSubject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function ContentType() : string
|
|
||||||
{
|
|
||||||
return $this->sContentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Size() : int
|
|
||||||
{
|
|
||||||
return $this->iSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function SpamScore() : int
|
|
||||||
{
|
|
||||||
return $this->iSpamScore;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function setSpamScore($value) : void
|
private function setSpamScore($value) : void
|
||||||
{
|
{
|
||||||
$this->iSpamScore = \intval(\max(0, \min(100, $value)));
|
$this->SpamScore = \intval(\max(0, \min(100, $value)));
|
||||||
}
|
|
||||||
|
|
||||||
public function SpamResult() : string
|
|
||||||
{
|
|
||||||
return $this->sSpamResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function IsSpam() : bool
|
|
||||||
{
|
|
||||||
return $this->bIsSpam;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* null = not scanned
|
|
||||||
* true = scanned and infected
|
|
||||||
* false = scanned and no infection found
|
|
||||||
*/
|
|
||||||
public function HasVirus() : ?bool
|
|
||||||
{
|
|
||||||
return $this->bHasVirus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function InternalTimeStampInUTC() : int
|
|
||||||
{
|
|
||||||
return $this->iInternalTimeStampInUTC;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function HeaderTimeStampInUTC() : int
|
|
||||||
{
|
|
||||||
return $this->iHeaderTimeStampInUTC;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function HeaderDate() : string
|
|
||||||
{
|
|
||||||
return $this->sHeaderDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function From() : ?\MailSo\Mime\EmailCollection
|
|
||||||
{
|
|
||||||
return $this->oFrom;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Priority() : int
|
|
||||||
{
|
|
||||||
return $this->iPriority;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Sender() : ?\MailSo\Mime\EmailCollection
|
|
||||||
{
|
|
||||||
return $this->oSender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function ReplyTo() : ?\MailSo\Mime\EmailCollection
|
|
||||||
{
|
|
||||||
return $this->oReplyTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function DeliveredTo() : ?\MailSo\Mime\EmailCollection
|
|
||||||
{
|
|
||||||
return $this->oDeliveredTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function To() : ?\MailSo\Mime\EmailCollection
|
|
||||||
{
|
|
||||||
return $this->oTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Cc() : ?\MailSo\Mime\EmailCollection
|
|
||||||
{
|
|
||||||
return $this->oCc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Bcc() : ?\MailSo\Mime\EmailCollection
|
|
||||||
{
|
|
||||||
return $this->oBcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Attachments() : ?AttachmentCollection
|
|
||||||
{
|
|
||||||
return $this->oAttachments;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function InReplyTo() : string
|
|
||||||
{
|
|
||||||
return $this->sInReplyTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function References() : string
|
|
||||||
{
|
|
||||||
return $this->sReferences;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function DeliveryReceipt() : string
|
|
||||||
{
|
|
||||||
return $this->sDeliveryReceipt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function ReadReceipt() : string
|
|
||||||
{
|
|
||||||
return $this->sReadReceipt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function UnsubsribeLinks() : array
|
|
||||||
{
|
|
||||||
return $this->aUnsubsribeLinks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function ReadingConfirmation() : string
|
|
||||||
{
|
|
||||||
return $this->ReadReceipt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function DraftInfo() : ?array
|
|
||||||
{
|
|
||||||
return $this->aDraftInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Threads() : array
|
|
||||||
{
|
|
||||||
return $this->aThreads;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetThreads(array $aThreads)
|
public function SetThreads(array $aThreads)
|
||||||
|
|
@ -285,15 +114,14 @@ class Message implements \JsonSerializable
|
||||||
{
|
{
|
||||||
$oMessage = new self;
|
$oMessage = new self;
|
||||||
|
|
||||||
if (!$oBodyStructure)
|
if (!$oBodyStructure) {
|
||||||
{
|
|
||||||
$oBodyStructure = $oFetchResponse->GetFetchBodyStructure();
|
$oBodyStructure = $oFetchResponse->GetFetchBodyStructure();
|
||||||
}
|
}
|
||||||
|
|
||||||
$aFlags = $oFetchResponse->GetFetchValue(FetchType::FLAGS) ?: [];
|
$aFlags = $oFetchResponse->GetFetchValue(FetchType::FLAGS) ?: [];
|
||||||
|
|
||||||
$oMessage->sFolder = $sFolder;
|
$oMessage->sFolder = $sFolder;
|
||||||
$oMessage->iUid = (int) $oFetchResponse->GetFetchValue(FetchType::UID);
|
$oMessage->Uid = (int) $oFetchResponse->GetFetchValue(FetchType::UID);
|
||||||
$oMessage->iSize = (int) $oFetchResponse->GetFetchValue(FetchType::RFC822_SIZE);
|
$oMessage->iSize = (int) $oFetchResponse->GetFetchValue(FetchType::RFC822_SIZE);
|
||||||
// $oMessage->aFlags = $aFlags;
|
// $oMessage->aFlags = $aFlags;
|
||||||
$oMessage->aFlagsLowerCase = \array_map('mb_strtolower', \array_map('\\MailSo\\Base\\Utils::Utf7ModifiedToUtf8', $aFlags));
|
$oMessage->aFlagsLowerCase = \array_map('mb_strtolower', \array_map('\\MailSo\\Base\\Utils::Utf7ModifiedToUtf8', $aFlags));
|
||||||
|
|
@ -310,8 +138,7 @@ class Message implements \JsonSerializable
|
||||||
$sCharset = $oBodyStructure ? Utils::NormalizeCharset($oBodyStructure->SearchCharset()) : '';
|
$sCharset = $oBodyStructure ? Utils::NormalizeCharset($oBodyStructure->SearchCharset()) : '';
|
||||||
|
|
||||||
$sHeaders = $oFetchResponse->GetHeaderFieldsValue();
|
$sHeaders = $oFetchResponse->GetHeaderFieldsValue();
|
||||||
if (\strlen($sHeaders))
|
if (\strlen($sHeaders)) {
|
||||||
{
|
|
||||||
$oHeaders = new \MailSo\Mime\HeaderCollection($sHeaders, false, $sCharset);
|
$oHeaders = new \MailSo\Mime\HeaderCollection($sHeaders, false, $sCharset);
|
||||||
|
|
||||||
$sContentTypeCharset = $oHeaders->ParameterValue(
|
$sContentTypeCharset = $oHeaders->ParameterValue(
|
||||||
|
|
@ -319,13 +146,11 @@ class Message implements \JsonSerializable
|
||||||
\MailSo\Mime\Enumerations\Parameter::CHARSET
|
\MailSo\Mime\Enumerations\Parameter::CHARSET
|
||||||
);
|
);
|
||||||
|
|
||||||
if (\strlen($sContentTypeCharset))
|
if (\strlen($sContentTypeCharset)) {
|
||||||
{
|
|
||||||
$sCharset = Utils::NormalizeCharset($sContentTypeCharset);
|
$sCharset = Utils::NormalizeCharset($sContentTypeCharset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\strlen($sCharset))
|
if (\strlen($sCharset)) {
|
||||||
{
|
|
||||||
$oHeaders->SetParentCharset($sCharset);
|
$oHeaders->SetParentCharset($sCharset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -348,40 +173,28 @@ class Message implements \JsonSerializable
|
||||||
$oMessage->oReplyTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::REPLY_TO, $bCharsetAutoDetect);
|
$oMessage->oReplyTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::REPLY_TO, $bCharsetAutoDetect);
|
||||||
$oMessage->oDeliveredTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::DELIVERED_TO, $bCharsetAutoDetect);
|
$oMessage->oDeliveredTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::DELIVERED_TO, $bCharsetAutoDetect);
|
||||||
|
|
||||||
$oMessage->sInReplyTo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IN_REPLY_TO);
|
$oMessage->InReplyTo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IN_REPLY_TO);
|
||||||
$oMessage->sReferences = Utils::StripSpaces(
|
$oMessage->References = Utils::StripSpaces(
|
||||||
$oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::REFERENCES));
|
$oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::REFERENCES));
|
||||||
|
|
||||||
$sHeaderDate = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DATE);
|
$oMessage->HeaderTimeStampInUTC = \MailSo\Base\DateTimeHelper::ParseRFC2822DateString(
|
||||||
$oMessage->sHeaderDate = $sHeaderDate;
|
$oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DATE)
|
||||||
$oMessage->iHeaderTimeStampInUTC = \MailSo\Base\DateTimeHelper::ParseRFC2822DateString($sHeaderDate);
|
);
|
||||||
|
|
||||||
// Priority
|
// Priority
|
||||||
$oMessage->iPriority = \MailSo\Mime\Enumerations\MessagePriority::NORMAL;
|
$sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_MSMAIL_PRIORITY)
|
||||||
$sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_MSMAIL_PRIORITY);
|
?: $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IMPORTANCE)
|
||||||
if (!\strlen($sPriority))
|
?: $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_PRIORITY);
|
||||||
|
if (\strlen($sPriority)) {
|
||||||
|
switch (\substr(\trim($sPriority), 0, 1))
|
||||||
{
|
{
|
||||||
$sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IMPORTANCE);
|
case 'h':
|
||||||
}
|
|
||||||
if (!\strlen($sPriority))
|
|
||||||
{
|
|
||||||
$sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_PRIORITY);
|
|
||||||
}
|
|
||||||
if (\strlen($sPriority))
|
|
||||||
{
|
|
||||||
switch (\str_replace(' ', '', \strtolower($sPriority)))
|
|
||||||
{
|
|
||||||
case 'high':
|
|
||||||
case '1(highest)':
|
|
||||||
case '2(high)':
|
|
||||||
case '1':
|
case '1':
|
||||||
case '2':
|
case '2':
|
||||||
$oMessage->iPriority = \MailSo\Mime\Enumerations\MessagePriority::HIGH;
|
$oMessage->iPriority = \MailSo\Mime\Enumerations\MessagePriority::HIGH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'low':
|
case 'l':
|
||||||
case '4(low)':
|
|
||||||
case '5(lowest)':
|
|
||||||
case '4':
|
case '4':
|
||||||
case '5':
|
case '5':
|
||||||
$oMessage->iPriority = \MailSo\Mime\Enumerations\MessagePriority::LOW;
|
$oMessage->iPriority = \MailSo\Mime\Enumerations\MessagePriority::LOW;
|
||||||
|
|
@ -393,26 +206,19 @@ class Message implements \JsonSerializable
|
||||||
$oMessage->sDeliveryReceipt = \trim($oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::RETURN_RECEIPT_TO));
|
$oMessage->sDeliveryReceipt = \trim($oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::RETURN_RECEIPT_TO));
|
||||||
|
|
||||||
// Read Receipt
|
// Read Receipt
|
||||||
$oMessage->sReadReceipt = \trim($oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DISPOSITION_NOTIFICATION_TO));
|
$oMessage->ReadReceipt = \trim($oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DISPOSITION_NOTIFICATION_TO));
|
||||||
if (empty($oMessage->sReadReceipt))
|
if (empty($oMessage->ReadReceipt)) {
|
||||||
{
|
$oMessage->ReadReceipt = \trim($oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_CONFIRM_READING_TO));
|
||||||
$oMessage->sReadReceipt = \trim($oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_CONFIRM_READING_TO));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsubscribe links
|
// Unsubscribe links
|
||||||
$oMessage->aUnsubsribeLinks = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::LIST_UNSUBSCRIBE);
|
$UnsubsribeLinks = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::LIST_UNSUBSCRIBE);
|
||||||
if (empty($oMessage->aUnsubsribeLinks))
|
if ($UnsubsribeLinks) {
|
||||||
{
|
$UnsubsribeLinks = \array_map(
|
||||||
$oMessage->aUnsubsribeLinks = array();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$oMessage->aUnsubsribeLinks = explode(',', $oMessage->aUnsubsribeLinks);
|
|
||||||
$oMessage->aUnsubsribeLinks = array_map(
|
|
||||||
function ($link) {
|
function ($link) {
|
||||||
return trim($link, ' <>');
|
return trim($link, ' <>');
|
||||||
},
|
},
|
||||||
$oMessage->aUnsubsribeLinks
|
\explode(',', $UnsubsribeLinks)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -481,7 +287,7 @@ class Message implements \JsonSerializable
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\strlen($sType) && \strlen($sFolder) && $iUid) {
|
if (\strlen($sType) && \strlen($sFolder) && $iUid) {
|
||||||
$oMessage->aDraftInfo = array($sType, $iUid, $sFolder);
|
$oMessage->DraftInfo = array($sType, $iUid, $sFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -501,15 +307,14 @@ class Message implements \JsonSerializable
|
||||||
$oMessage->oTo = $oFetchResponse->GetFetchEnvelopeEmailCollection(5, $sCharset);
|
$oMessage->oTo = $oFetchResponse->GetFetchEnvelopeEmailCollection(5, $sCharset);
|
||||||
$oMessage->oCc = $oFetchResponse->GetFetchEnvelopeEmailCollection(6, $sCharset);
|
$oMessage->oCc = $oFetchResponse->GetFetchEnvelopeEmailCollection(6, $sCharset);
|
||||||
$oMessage->oBcc = $oFetchResponse->GetFetchEnvelopeEmailCollection(7, $sCharset);
|
$oMessage->oBcc = $oFetchResponse->GetFetchEnvelopeEmailCollection(7, $sCharset);
|
||||||
$oMessage->sInReplyTo = $oFetchResponse->GetFetchEnvelopeValue(8, '');
|
$oMessage->InReplyTo = $oFetchResponse->GetFetchEnvelopeValue(8, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($oBodyStructure)
|
if ($oBodyStructure) {
|
||||||
{
|
|
||||||
$gEncryptedParts = $oBodyStructure->SearchByContentType('multipart/encrypted');
|
$gEncryptedParts = $oBodyStructure->SearchByContentType('multipart/encrypted');
|
||||||
foreach ($gEncryptedParts as $oPart) {
|
foreach ($gEncryptedParts as $oPart) {
|
||||||
if ($oPart->IsPgpEncrypted()) {
|
if ($oPart->IsPgpEncrypted()) {
|
||||||
$oMessage->aPgpEncrypted = [
|
$oMessage->pgpEncrypted = [
|
||||||
'PartId' => $oPart->SubParts()[1]->PartID()
|
'PartId' => $oPart->SubParts()[1]->PartID()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
@ -521,7 +326,7 @@ class Message implements \JsonSerializable
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$oPgpSignaturePart = $oPart->SubParts()[1];
|
$oPgpSignaturePart = $oPart->SubParts()[1];
|
||||||
$oMessage->aPgpSigned = [
|
$oMessage->pgpSigned = [
|
||||||
// /?/Raw/&q[]=/0/Download/&q[]=/...
|
// /?/Raw/&q[]=/0/Download/&q[]=/...
|
||||||
// /?/Raw/&q[]=/0/View/&q[]=/...
|
// /?/Raw/&q[]=/0/View/&q[]=/...
|
||||||
'BodyPartId' => $oPart->SubParts()[0]->PartID(),
|
'BodyPartId' => $oPart->SubParts()[0]->PartID(),
|
||||||
|
|
@ -532,40 +337,36 @@ class Message implements \JsonSerializable
|
||||||
// An empty section specification refers to the entire message, including the header.
|
// An empty section specification refers to the entire message, including the header.
|
||||||
// But Dovecot does not return it with BODY.PEEK[1], so we also use BODY.PEEK[1.MIME].
|
// But Dovecot does not return it with BODY.PEEK[1], so we also use BODY.PEEK[1.MIME].
|
||||||
$sPgpText = \trim(
|
$sPgpText = \trim(
|
||||||
\trim($oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oMessage->aPgpSigned['BodyPartId'].'.MIME]'))
|
\trim($oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oMessage->pgpSigned['BodyPartId'].'.MIME]'))
|
||||||
. "\r\n\r\n"
|
. "\r\n\r\n"
|
||||||
. \trim($oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oMessage->aPgpSigned['BodyPartId'].']'))
|
. \trim($oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oMessage->pgpSigned['BodyPartId'].']'))
|
||||||
);
|
);
|
||||||
if ($sPgpText) {
|
if ($sPgpText) {
|
||||||
$oMessage->aPgpSigned['Body'] = $sPgpText;
|
$oMessage->pgpSigned['Body'] = $sPgpText;
|
||||||
}
|
}
|
||||||
$sPgpSignatureText = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oMessage->aPgpSigned['SigPartId'].']');
|
$sPgpSignatureText = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oMessage->pgpSigned['SigPartId'].']');
|
||||||
if ($sPgpSignatureText && 0 < \strpos($sPgpSignatureText, 'BEGIN PGP SIGNATURE')) {
|
if ($sPgpSignatureText && 0 < \strpos($sPgpSignatureText, 'BEGIN PGP SIGNATURE')) {
|
||||||
$oMessage->aPgpSigned['Signature'] = $oPart->SubParts()[0]->PartID();
|
$oMessage->pgpSigned['Signature'] = $oPart->SubParts()[0]->PartID();
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$aTextParts = $oBodyStructure->GetHtmlAndPlainParts();
|
$aTextParts = $oBodyStructure->GetHtmlAndPlainParts();
|
||||||
if ($aTextParts)
|
if ($aTextParts) {
|
||||||
{
|
|
||||||
$sCharset = $sCharset ?: \MailSo\Base\Enumerations\Charset::UTF_8;
|
$sCharset = $sCharset ?: \MailSo\Base\Enumerations\Charset::UTF_8;
|
||||||
|
|
||||||
$aHtmlParts = array();
|
$aHtmlParts = array();
|
||||||
$aPlainParts = array();
|
$aPlainParts = array();
|
||||||
|
|
||||||
foreach ($aTextParts as $oPart)
|
foreach ($aTextParts as $oPart) {
|
||||||
{
|
|
||||||
$sText = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oPart->PartID().']');
|
$sText = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oPart->PartID().']');
|
||||||
if (null === $sText)
|
if (null === $sText) {
|
||||||
{
|
|
||||||
// TextPartIsTrimmed ?
|
// TextPartIsTrimmed ?
|
||||||
$sText = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oPart->PartID().']<0>');
|
$sText = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oPart->PartID().']<0>');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\is_string($sText) && \strlen($sText))
|
if (\is_string($sText) && \strlen($sText)) {
|
||||||
{
|
|
||||||
$sText = Utils::DecodeEncodingValue($sText, $oPart->MailEncodingName());
|
$sText = Utils::DecodeEncodingValue($sText, $oPart->MailEncodingName());
|
||||||
$sText = Utils::ConvertEncoding($sText,
|
$sText = Utils::ConvertEncoding($sText,
|
||||||
Utils::NormalizeCharset($oPart->Charset() ?: $sCharset, true),
|
Utils::NormalizeCharset($oPart->Charset() ?: $sCharset, true),
|
||||||
|
|
@ -575,34 +376,28 @@ class Message implements \JsonSerializable
|
||||||
|
|
||||||
// https://datatracker.ietf.org/doc/html/rfc4880#section-7
|
// https://datatracker.ietf.org/doc/html/rfc4880#section-7
|
||||||
// Cleartext Signature
|
// Cleartext Signature
|
||||||
if (!$oMessage->aPgpSigned && \str_contains($sText, '-----BEGIN PGP SIGNED MESSAGE-----'))
|
if (!$oMessage->pgpSigned && \str_contains($sText, '-----BEGIN PGP SIGNED MESSAGE-----')) {
|
||||||
{
|
$oMessage->pgpSigned = [
|
||||||
$oMessage->aPgpSigned = [
|
|
||||||
'BodyPartId' => $oPart->PartID()
|
'BodyPartId' => $oPart->PartID()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\str_contains($sText, '-----BEGIN PGP MESSAGE-----'))
|
if (\str_contains($sText, '-----BEGIN PGP MESSAGE-----')) {
|
||||||
{
|
|
||||||
$keyIds = [];
|
$keyIds = [];
|
||||||
if (\SnappyMail\PGP\GPG::isSupported()) {
|
if (\SnappyMail\PGP\GPG::isSupported()) {
|
||||||
$GPG = new \SnappyMail\PGP\GPG('');
|
$GPG = new \SnappyMail\PGP\GPG('');
|
||||||
$keyIds = $GPG->getEncryptedMessageKeys($sText);
|
$keyIds = $GPG->getEncryptedMessageKeys($sText);
|
||||||
}
|
}
|
||||||
$oMessage->aPgpEncrypted = [
|
$oMessage->pgpEncrypted = [
|
||||||
'PartId' => $oPart->PartID(),
|
'PartId' => $oPart->PartID(),
|
||||||
'KeyIds' => $keyIds
|
'KeyIds' => $keyIds
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('text/html' === $oPart->ContentType())
|
if ('text/html' === $oPart->ContentType()) {
|
||||||
{
|
|
||||||
$aHtmlParts[] = $sText;
|
$aHtmlParts[] = $sText;
|
||||||
}
|
} else {
|
||||||
else
|
if ($oPart->IsFlowedFormat()) {
|
||||||
{
|
|
||||||
if ($oPart->IsFlowedFormat())
|
|
||||||
{
|
|
||||||
$sText = Utils::DecodeFlowedFormat($sText);
|
$sText = Utils::DecodeFlowedFormat($sText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -618,14 +413,12 @@ class Message implements \JsonSerializable
|
||||||
}
|
}
|
||||||
|
|
||||||
$gAttachmentsParts = $oBodyStructure->SearchAttachmentsParts();
|
$gAttachmentsParts = $oBodyStructure->SearchAttachmentsParts();
|
||||||
if ($gAttachmentsParts->valid())
|
if ($gAttachmentsParts->valid()) {
|
||||||
{
|
$oMessage->Attachments = new AttachmentCollection;
|
||||||
$oMessage->oAttachments = new AttachmentCollection;
|
foreach ($gAttachmentsParts as /* @var $oAttachmentItem \MailSo\Imap\BodyStructure */ $oAttachmentItem) {
|
||||||
foreach ($gAttachmentsParts as /* @var $oAttachmentItem \MailSo\Imap\BodyStructure */ $oAttachmentItem)
|
|
||||||
{
|
|
||||||
// if ('application/pgp-keys' === $oAttachmentItem->ContentType()) import ???
|
// if ('application/pgp-keys' === $oAttachmentItem->ContentType()) import ???
|
||||||
$oMessage->oAttachments->append(
|
$oMessage->Attachments->append(
|
||||||
new Attachment($oMessage->sFolder, $oMessage->iUid, $oAttachmentItem)
|
new Attachment($oMessage->sFolder, $oMessage->Uid, $oAttachmentItem)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -657,11 +450,11 @@ class Message implements \JsonSerializable
|
||||||
return array(
|
return array(
|
||||||
'@Object' => 'Object/Message',
|
'@Object' => 'Object/Message',
|
||||||
'Folder' => $this->sFolder,
|
'Folder' => $this->sFolder,
|
||||||
'Uid' => $this->iUid,
|
'Uid' => $this->Uid,
|
||||||
'subject' => \trim(Utils::Utf8Clear($this->sSubject)),
|
'subject' => \trim(Utils::Utf8Clear($this->sSubject)),
|
||||||
'encrypted' => 'multipart/encrypted' == $this->sContentType || $this->PgpEncrypted(),
|
'encrypted' => 'multipart/encrypted' == $this->sContentType || $this->pgpEncrypted,
|
||||||
'MessageId' => $this->sMessageId,
|
'MessageId' => $this->sMessageId,
|
||||||
'SpamScore' => $this->bIsSpam ? 100 : $this->iSpamScore,
|
'SpamScore' => $this->bIsSpam ? 100 : $this->SpamScore,
|
||||||
'SpamResult' => $this->sSpamResult,
|
'SpamResult' => $this->sSpamResult,
|
||||||
'IsSpam' => $this->bIsSpam,
|
'IsSpam' => $this->bIsSpam,
|
||||||
'HasVirus' => $this->bHasVirus,
|
'HasVirus' => $this->bHasVirus,
|
||||||
|
|
@ -679,11 +472,11 @@ class Message implements \JsonSerializable
|
||||||
|
|
||||||
'Priority' => $this->iPriority,
|
'Priority' => $this->iPriority,
|
||||||
'Threads' => $this->aThreads,
|
'Threads' => $this->aThreads,
|
||||||
'UnsubsribeLinks' => $this->aUnsubsribeLinks,
|
'UnsubsribeLinks' => $this->UnsubsribeLinks,
|
||||||
'ReadReceipt' => '',
|
'ReadReceipt' => '',
|
||||||
'Autocrypt' => $this->sAutocrypt,
|
'Autocrypt' => $this->sAutocrypt,
|
||||||
|
|
||||||
'Attachments' => $this->oAttachments,
|
'Attachments' => $this->Attachments,
|
||||||
|
|
||||||
'Flags' => $aFlags,
|
'Flags' => $aFlags,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,18 +13,22 @@ namespace MailSo\Mail;
|
||||||
|
|
||||||
class MessageListParams
|
class MessageListParams
|
||||||
{
|
{
|
||||||
public
|
public string
|
||||||
$sFolderName, // string
|
$sFolderName,
|
||||||
$sSearch = '', // string
|
$sSearch,
|
||||||
$oCacher = null, // ?\MailSo\Cache\CacheClient
|
$sSort;
|
||||||
$bUseSortIfSupported = false, // bool
|
|
||||||
$bUseThreads = false, // bool
|
|
||||||
$bHideDeleted = true, // bool
|
|
||||||
$sSort = ''; // string
|
|
||||||
|
|
||||||
protected
|
public ?\MailSo\Cache\CacheClient
|
||||||
$iOffset = 0,
|
$oCacher = null;
|
||||||
$iLimit = 10,
|
|
||||||
|
public bool
|
||||||
|
$bUseSortIfSupported = false,
|
||||||
|
$bUseThreads,
|
||||||
|
$bHideDeleted = true;
|
||||||
|
|
||||||
|
protected int
|
||||||
|
$iOffset,
|
||||||
|
$iLimit,
|
||||||
$iPrevUidNext = 0, // used to check for new messages
|
$iPrevUidNext = 0, // used to check for new messages
|
||||||
$iThreadUid = 0;
|
$iThreadUid = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,33 +17,20 @@ namespace MailSo\Mime;
|
||||||
*/
|
*/
|
||||||
class Email implements \JsonSerializable
|
class Email implements \JsonSerializable
|
||||||
{
|
{
|
||||||
/**
|
private string $sDisplayName;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sDisplayName;
|
|
||||||
|
|
||||||
/**
|
private string $sEmail;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sEmail;
|
|
||||||
|
|
||||||
/**
|
private string $sDkimStatus = Enumerations\DkimStatus::NONE;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sDkimStatus;
|
|
||||||
|
|
||||||
/**
|
private string $sDkimValue = '';
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sDkimValue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
function __construct(string $sEmail, string $sDisplayName = '')
|
function __construct(string $sEmail, string $sDisplayName = '')
|
||||||
{
|
{
|
||||||
if (!\strlen(\trim($sEmail)))
|
if (!\strlen(\trim($sEmail))) {
|
||||||
{
|
|
||||||
throw new \InvalidArgumentException;
|
throw new \InvalidArgumentException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,9 +38,6 @@ class Email implements \JsonSerializable
|
||||||
\MailSo\Base\Utils::Trim($sEmail), true);
|
\MailSo\Base\Utils::Trim($sEmail), true);
|
||||||
|
|
||||||
$this->sDisplayName = \MailSo\Base\Utils::Trim($sDisplayName);
|
$this->sDisplayName = \MailSo\Base\Utils::Trim($sDisplayName);
|
||||||
|
|
||||||
$this->sDkimStatus = Enumerations\DkimStatus::NONE;
|
|
||||||
$this->sDkimValue = '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -62,8 +46,7 @@ class Email implements \JsonSerializable
|
||||||
public static function Parse(string $sEmailAddress) : self
|
public static function Parse(string $sEmailAddress) : self
|
||||||
{
|
{
|
||||||
$sEmailAddress = \MailSo\Base\Utils::Trim($sEmailAddress);
|
$sEmailAddress = \MailSo\Base\Utils::Trim($sEmailAddress);
|
||||||
if (!\strlen(\trim($sEmailAddress)))
|
if (!\strlen(\trim($sEmailAddress))) {
|
||||||
{
|
|
||||||
throw new \InvalidArgumentException;
|
throw new \InvalidArgumentException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,20 +62,16 @@ class Email implements \JsonSerializable
|
||||||
$iEndIndex = 0;
|
$iEndIndex = 0;
|
||||||
$iCurrentIndex = 0;
|
$iCurrentIndex = 0;
|
||||||
|
|
||||||
while ($iCurrentIndex < \strlen($sEmailAddress))
|
while ($iCurrentIndex < \strlen($sEmailAddress)) {
|
||||||
{
|
|
||||||
switch ($sEmailAddress[$iCurrentIndex])
|
switch ($sEmailAddress[$iCurrentIndex])
|
||||||
{
|
{
|
||||||
// case '\'':
|
// case '\'':
|
||||||
case '"':
|
case '"':
|
||||||
// $sQuoteChar = $sEmailAddress[$iCurrentIndex];
|
// $sQuoteChar = $sEmailAddress[$iCurrentIndex];
|
||||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
if (!$bInName && !$bInAddress && !$bInComment) {
|
||||||
{
|
|
||||||
$bInName = true;
|
$bInName = true;
|
||||||
$iStartIndex = $iCurrentIndex;
|
$iStartIndex = $iCurrentIndex;
|
||||||
}
|
} else if (!$bInAddress && !$bInComment) {
|
||||||
else if ((!$bInAddress) && (!$bInComment))
|
|
||||||
{
|
|
||||||
$iEndIndex = $iCurrentIndex;
|
$iEndIndex = $iCurrentIndex;
|
||||||
$sName = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
$sName = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||||
|
|
@ -103,10 +82,8 @@ class Email implements \JsonSerializable
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '<':
|
case '<':
|
||||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
if (!$bInName && !$bInAddress && !$bInComment) {
|
||||||
{
|
if ($iCurrentIndex > 0 && !\strlen($sName)) {
|
||||||
if ($iCurrentIndex > 0 && \strlen($sName) === 0)
|
|
||||||
{
|
|
||||||
$sName = \substr($sEmailAddress, 0, $iCurrentIndex);
|
$sName = \substr($sEmailAddress, 0, $iCurrentIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,8 +92,7 @@ class Email implements \JsonSerializable
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
if ($bInAddress)
|
if ($bInAddress) {
|
||||||
{
|
|
||||||
$iEndIndex = $iCurrentIndex;
|
$iEndIndex = $iCurrentIndex;
|
||||||
$sEmail = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
$sEmail = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||||
|
|
@ -127,15 +103,13 @@ class Email implements \JsonSerializable
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '(':
|
case '(':
|
||||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
if (!$bInName && !$bInAddress && !$bInComment) {
|
||||||
{
|
|
||||||
$bInComment = true;
|
$bInComment = true;
|
||||||
$iStartIndex = $iCurrentIndex;
|
$iStartIndex = $iCurrentIndex;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ')':
|
case ')':
|
||||||
if ($bInComment)
|
if ($bInComment) {
|
||||||
{
|
|
||||||
$iEndIndex = $iCurrentIndex;
|
$iEndIndex = $iCurrentIndex;
|
||||||
$sComment = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
$sComment = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||||
|
|
@ -146,28 +120,23 @@ class Email implements \JsonSerializable
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '\\':
|
case '\\':
|
||||||
$iCurrentIndex++;
|
++$iCurrentIndex;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$iCurrentIndex++;
|
++$iCurrentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\strlen($sEmail) === 0)
|
if (!\strlen($sEmail)) {
|
||||||
{
|
|
||||||
$aRegs = array('');
|
$aRegs = array('');
|
||||||
if (\preg_match('/[^@\s]+@\S+/i', $sEmailAddress, $aRegs) && isset($aRegs[0]))
|
if (\preg_match('/[^@\s]+@\S+/i', $sEmailAddress, $aRegs) && isset($aRegs[0])) {
|
||||||
{
|
|
||||||
$sEmail = $aRegs[0];
|
$sEmail = $aRegs[0];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sName = $sEmailAddress;
|
$sName = $sEmailAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((\strlen($sEmail) > 0) && (\strlen($sName) == 0) && (\strlen($sComment) == 0))
|
if (\strlen($sEmail) && !\strlen($sName) && !\strlen($sComment)) {
|
||||||
{
|
|
||||||
$sName = \str_replace($sEmail, '', $sEmailAddress);
|
$sName = \str_replace($sEmail, '', $sEmailAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -234,19 +203,16 @@ class Email implements \JsonSerializable
|
||||||
$sReturn = '';
|
$sReturn = '';
|
||||||
|
|
||||||
$sDisplayName = \str_replace('"', '\"', $this->sDisplayName);
|
$sDisplayName = \str_replace('"', '\"', $this->sDisplayName);
|
||||||
if ($bConvertSpecialsName)
|
if ($bConvertSpecialsName) {
|
||||||
{
|
$sDisplayName = \strlen($sDisplayName)
|
||||||
$sDisplayName = 0 === \strlen($sDisplayName) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue(
|
? \MailSo\Base\Utils::EncodeUnencodedValue(\MailSo\Base\Enumerations\Encoding::BASE64_SHORT, $sDisplayName)
|
||||||
\MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
|
: '';
|
||||||
$sDisplayName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$sDisplayName = 0 === \strlen($sDisplayName) ? '' : '"'.$sDisplayName.'"';
|
$sDisplayName = \strlen($sDisplayName) ? '"'.$sDisplayName.'"' : '';
|
||||||
if (\strlen($this->sEmail))
|
if (\strlen($this->sEmail)) {
|
||||||
{
|
|
||||||
$sReturn = $this->GetEmail($bIdn);
|
$sReturn = $this->GetEmail($bIdn);
|
||||||
if (\strlen($sDisplayName))
|
if (\strlen($sDisplayName)) {
|
||||||
{
|
|
||||||
$sReturn = $sDisplayName.' <'.$sReturn.'>';
|
$sReturn = $sDisplayName.' <'.$sReturn.'>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,7 @@ class EmailCollection extends \MailSo\Base\Collection
|
||||||
public function ToArray() : array
|
public function ToArray() : array
|
||||||
{
|
{
|
||||||
$aReturn = array();
|
$aReturn = array();
|
||||||
foreach ($this as $oEmail)
|
foreach ($this as $oEmail) {
|
||||||
{
|
|
||||||
$aReturn[] = $oEmail->ToArray();
|
$aReturn[] = $oEmail->ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,8 +45,7 @@ class EmailCollection extends \MailSo\Base\Collection
|
||||||
|
|
||||||
public function MergeWithOtherCollection(EmailCollection $oEmails) : self
|
public function MergeWithOtherCollection(EmailCollection $oEmails) : self
|
||||||
{
|
{
|
||||||
foreach ($oEmails as $oEmail)
|
foreach ($oEmails as $oEmail) {
|
||||||
{
|
|
||||||
$this->append($oEmail);
|
$this->append($oEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,11 +56,9 @@ class EmailCollection extends \MailSo\Base\Collection
|
||||||
{
|
{
|
||||||
$aReturn = array();
|
$aReturn = array();
|
||||||
|
|
||||||
foreach ($this as $oEmail)
|
foreach ($this as $oEmail) {
|
||||||
{
|
|
||||||
$sEmail = $oEmail->GetEmail();
|
$sEmail = $oEmail->GetEmail();
|
||||||
if (!isset($aReturn[$sEmail]))
|
if (!isset($aReturn[$sEmail])) {
|
||||||
{
|
|
||||||
$aReturn[$sEmail] = $oEmail;
|
$aReturn[$sEmail] = $oEmail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -73,8 +69,7 @@ class EmailCollection extends \MailSo\Base\Collection
|
||||||
public function ToString(bool $bConvertSpecialsName = false, bool $bIdn = false) : string
|
public function ToString(bool $bConvertSpecialsName = false, bool $bIdn = false) : string
|
||||||
{
|
{
|
||||||
$aReturn = array();
|
$aReturn = array();
|
||||||
foreach ($this as $oEmail)
|
foreach ($this as $oEmail) {
|
||||||
{
|
|
||||||
$aReturn[] = $oEmail->ToString($bConvertSpecialsName, $bIdn);
|
$aReturn[] = $oEmail->ToString($bConvertSpecialsName, $bIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,8 +82,7 @@ class EmailCollection extends \MailSo\Base\Collection
|
||||||
$sRawEmails = \trim($sRawEmails);
|
$sRawEmails = \trim($sRawEmails);
|
||||||
|
|
||||||
$sWorkingRecipientsLen = \strlen($sRawEmails);
|
$sWorkingRecipientsLen = \strlen($sRawEmails);
|
||||||
if (!$sWorkingRecipientsLen)
|
if (!$sWorkingRecipientsLen) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,59 +96,49 @@ class EmailCollection extends \MailSo\Base\Collection
|
||||||
|
|
||||||
$iCurrentPos = 0;
|
$iCurrentPos = 0;
|
||||||
|
|
||||||
while ($iCurrentPos < $sWorkingRecipientsLen)
|
while ($iCurrentPos < $sWorkingRecipientsLen) {
|
||||||
{
|
|
||||||
switch ($sRawEmails[$iCurrentPos])
|
switch ($sRawEmails[$iCurrentPos])
|
||||||
{
|
{
|
||||||
case '\'':
|
case '\'':
|
||||||
case '"':
|
case '"':
|
||||||
if (!$bIsInQuotes)
|
if (!$bIsInQuotes) {
|
||||||
{
|
|
||||||
$sChQuote = $sRawEmails[$iCurrentPos];
|
$sChQuote = $sRawEmails[$iCurrentPos];
|
||||||
$bIsInQuotes = true;
|
$bIsInQuotes = true;
|
||||||
}
|
} else if ($sChQuote == $sRawEmails[$iCurrentPos]) {
|
||||||
else if ($sChQuote == $sRawEmails[$iCurrentPos])
|
|
||||||
{
|
|
||||||
$bIsInQuotes = false;
|
$bIsInQuotes = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '<':
|
case '<':
|
||||||
if (!$bIsInAngleBrackets)
|
if (!$bIsInAngleBrackets) {
|
||||||
{
|
|
||||||
$bIsInAngleBrackets = true;
|
$bIsInAngleBrackets = true;
|
||||||
if ($bIsInQuotes)
|
if ($bIsInQuotes) {
|
||||||
{
|
|
||||||
$bIsInQuotes = false;
|
$bIsInQuotes = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '>':
|
case '>':
|
||||||
if ($bIsInAngleBrackets)
|
if ($bIsInAngleBrackets) {
|
||||||
{
|
|
||||||
$bIsInAngleBrackets = false;
|
$bIsInAngleBrackets = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '(':
|
case '(':
|
||||||
if (!$bIsInBrackets)
|
if (!$bIsInBrackets) {
|
||||||
{
|
|
||||||
$bIsInBrackets = true;
|
$bIsInBrackets = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ')':
|
case ')':
|
||||||
if ($bIsInBrackets)
|
if ($bIsInBrackets) {
|
||||||
{
|
|
||||||
$bIsInBrackets = false;
|
$bIsInBrackets = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ',':
|
case ',':
|
||||||
case ';':
|
case ';':
|
||||||
if (!$bIsInAngleBrackets && !$bIsInBrackets && !$bIsInQuotes)
|
if (!$bIsInAngleBrackets && !$bIsInBrackets && !$bIsInQuotes) {
|
||||||
{
|
|
||||||
$iEmailEndPos = $iCurrentPos;
|
$iEmailEndPos = $iCurrentPos;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -175,8 +159,7 @@ class EmailCollection extends \MailSo\Base\Collection
|
||||||
++$iCurrentPos;
|
++$iCurrentPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($iEmailStartPos < $iCurrentPos)
|
if ($iEmailStartPos < $iCurrentPos) {
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$this->append(
|
$this->append(
|
||||||
|
|
|
||||||
|
|
@ -17,35 +17,17 @@ namespace MailSo\Mime;
|
||||||
*/
|
*/
|
||||||
class Header
|
class Header
|
||||||
{
|
{
|
||||||
/**
|
private string $sName;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sName;
|
|
||||||
|
|
||||||
/**
|
private string $sValue;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sValue;
|
|
||||||
|
|
||||||
/**
|
private string $sFullValue;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sFullValue;
|
|
||||||
|
|
||||||
/**
|
private string $sEncodedValueForReparse;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sEncodedValueForReparse;
|
|
||||||
|
|
||||||
/**
|
private ?ParameterCollection $oParameters = null;
|
||||||
* @var ParameterCollection
|
|
||||||
*/
|
|
||||||
private $oParameters;
|
|
||||||
|
|
||||||
/**
|
private string $sParentCharset;
|
||||||
* @var strign
|
|
||||||
*/
|
|
||||||
private $sParentCharset;
|
|
||||||
|
|
||||||
function __construct(string $sName, string $sValue = '', string $sEncodedValueForReparse = '', string $sParentCharset = '')
|
function __construct(string $sName, string $sValue = '', string $sEncodedValueForReparse = '', string $sParentCharset = '')
|
||||||
{
|
{
|
||||||
|
|
@ -59,26 +41,19 @@ class Header
|
||||||
$this->sFullValue = \trim($sValue);
|
$this->sFullValue = \trim($sValue);
|
||||||
$this->sEncodedValueForReparse = '';
|
$this->sEncodedValueForReparse = '';
|
||||||
|
|
||||||
if (\strlen($sEncodedValueForReparse) && $this->IsReparsed())
|
if (\strlen($sEncodedValueForReparse) && $this->IsReparsed()) {
|
||||||
{
|
|
||||||
$this->sEncodedValueForReparse = \trim($sEncodedValueForReparse);
|
$this->sEncodedValueForReparse = \trim($sEncodedValueForReparse);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\strlen($this->sFullValue) && $this->IsParameterized())
|
if (\strlen($this->sFullValue) && $this->IsParameterized()) {
|
||||||
{
|
|
||||||
$aRawExplode = \explode(';', $this->sFullValue, 2);
|
$aRawExplode = \explode(';', $this->sFullValue, 2);
|
||||||
if (2 === \count($aRawExplode))
|
if (2 === \count($aRawExplode)) {
|
||||||
{
|
|
||||||
$this->sValue = $aRawExplode[0];
|
$this->sValue = $aRawExplode[0];
|
||||||
$this->oParameters = new ParameterCollection($aRawExplode[1]);
|
$this->oParameters = new ParameterCollection($aRawExplode[1]);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$this->sValue = $this->sFullValue;
|
$this->sValue = $this->sFullValue;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$this->sValue = $this->sFullValue;
|
$this->sValue = $this->sFullValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,14 +64,12 @@ class Header
|
||||||
|
|
||||||
public static function NewInstanceFromEncodedString(string $sEncodedLines, string $sIncomingCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1) : Header
|
public static function NewInstanceFromEncodedString(string $sEncodedLines, string $sIncomingCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1) : Header
|
||||||
{
|
{
|
||||||
if (empty($sIncomingCharset))
|
if (empty($sIncomingCharset)) {
|
||||||
{
|
|
||||||
$sIncomingCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1;
|
$sIncomingCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$aParts = \explode(':', \str_replace("\r", '', $sEncodedLines), 2);
|
$aParts = \explode(':', \str_replace("\r", '', $sEncodedLines), 2);
|
||||||
if (isset($aParts[0]) && isset($aParts[1]) && \strlen($aParts[0]) && \strlen($aParts[1]))
|
if (isset($aParts[0]) && isset($aParts[1]) && \strlen($aParts[0]) && \strlen($aParts[1])) {
|
||||||
{
|
|
||||||
return new self(
|
return new self(
|
||||||
\trim($aParts[0]),
|
\trim($aParts[0]),
|
||||||
\trim(\MailSo\Base\Utils::DecodeHeaderValue(\trim($aParts[1]), $sIncomingCharset)),
|
\trim(\MailSo\Base\Utils::DecodeHeaderValue(\trim($aParts[1]), $sIncomingCharset)),
|
||||||
|
|
@ -130,8 +103,7 @@ class Header
|
||||||
|
|
||||||
public function SetParentCharset(string $sParentCharset) : Header
|
public function SetParentCharset(string $sParentCharset) : Header
|
||||||
{
|
{
|
||||||
if ($this->sParentCharset !== $sParentCharset && $this->IsReparsed() && \strlen($this->sEncodedValueForReparse))
|
if ($this->sParentCharset !== $sParentCharset && $this->IsReparsed() && \strlen($this->sEncodedValueForReparse)) {
|
||||||
{
|
|
||||||
$this->initInputData(
|
$this->initInputData(
|
||||||
$this->sName,
|
$this->sName,
|
||||||
\trim(\MailSo\Base\Utils::DecodeHeaderValue($this->sEncodedValueForReparse, $sParentCharset)),
|
\trim(\MailSo\Base\Utils::DecodeHeaderValue($this->sEncodedValueForReparse, $sParentCharset)),
|
||||||
|
|
@ -165,11 +137,8 @@ class Header
|
||||||
{
|
{
|
||||||
$sResult = $this->sFullValue;
|
$sResult = $this->sFullValue;
|
||||||
|
|
||||||
if ($this->IsSubject())
|
if ($this->IsSubject()) {
|
||||||
{
|
if (!\MailSo\Base\Utils::IsAscii($sResult) && \function_exists('iconv_mime_encode')) {
|
||||||
if (!\MailSo\Base\Utils::IsAscii($sResult) &&
|
|
||||||
\function_exists('iconv_mime_encode'))
|
|
||||||
{
|
|
||||||
$aPreferences = array(
|
$aPreferences = array(
|
||||||
// 'scheme' => \MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE_SHORT,
|
// 'scheme' => \MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE_SHORT,
|
||||||
'scheme' => \MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
|
'scheme' => \MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,9 @@ namespace MailSo\Mime;
|
||||||
class HeaderCollection extends \MailSo\Base\Collection
|
class HeaderCollection extends \MailSo\Base\Collection
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $sRawHeaders = '';
|
protected string $sRawHeaders = '';
|
||||||
|
|
||||||
/**
|
protected string $sParentCharset = '';
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $sParentCharset = '';
|
|
||||||
|
|
||||||
function __construct(string $sRawHeaders = '', bool $bStoreRawHeaders = true, string $sParentCharset = '')
|
function __construct(string $sRawHeaders = '', bool $bStoreRawHeaders = true, string $sParentCharset = '')
|
||||||
{
|
{
|
||||||
|
|
@ -149,40 +146,29 @@ class HeaderCollection extends \MailSo\Base\Collection
|
||||||
}
|
}
|
||||||
|
|
||||||
$sFirstChar = \substr($sHeadersValue, 0, 1);
|
$sFirstChar = \substr($sHeadersValue, 0, 1);
|
||||||
if ($sFirstChar !== ' ' && $sFirstChar !== "\t" && false === \strpos($sHeadersValue, ':'))
|
if ($sFirstChar !== ' ' && $sFirstChar !== "\t" && false === \strpos($sHeadersValue, ':')) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (null !== $sName && ($sFirstChar === ' ' || $sFirstChar === "\t"))
|
if (null !== $sName && ($sFirstChar === ' ' || $sFirstChar === "\t")) {
|
||||||
{
|
|
||||||
$sValue = \is_null($sValue) ? '' : $sValue;
|
$sValue = \is_null($sValue) ? '' : $sValue;
|
||||||
|
|
||||||
if ('?=' === \substr(\rtrim($sHeadersValue), -2))
|
if ('?=' === \substr(\rtrim($sHeadersValue), -2)) {
|
||||||
{
|
|
||||||
$sHeadersValue = \rtrim($sHeadersValue);
|
$sHeadersValue = \rtrim($sHeadersValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('=?' === \substr(\ltrim($sHeadersValue), 0, 2))
|
if ('=?' === \substr(\ltrim($sHeadersValue), 0, 2)) {
|
||||||
{
|
|
||||||
$sHeadersValue = \ltrim($sHeadersValue);
|
$sHeadersValue = \ltrim($sHeadersValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('=?' === \substr($sHeadersValue, 0, 2))
|
if ('=?' === \substr($sHeadersValue, 0, 2)) {
|
||||||
{
|
|
||||||
$sValue .= $sHeadersValue;
|
$sValue .= $sHeadersValue;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$sValue .= "\n".$sHeadersValue;
|
$sValue .= "\n".$sHeadersValue;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if (null !== $sName) {
|
||||||
{
|
|
||||||
if (null !== $sName)
|
|
||||||
{
|
|
||||||
$oHeader = Header::NewInstanceFromEncodedString($sName.': '.$sValue, $this->sParentCharset);
|
$oHeader = Header::NewInstanceFromEncodedString($sName.': '.$sValue, $this->sParentCharset);
|
||||||
if ($oHeader)
|
if ($oHeader) {
|
||||||
{
|
|
||||||
$this->append($oHeader);
|
$this->append($oHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,18 +180,15 @@ class HeaderCollection extends \MailSo\Base\Collection
|
||||||
$sName = $aHeaderParts[0];
|
$sName = $aHeaderParts[0];
|
||||||
$sValue = isset($aHeaderParts[1]) ? $aHeaderParts[1] : '';
|
$sValue = isset($aHeaderParts[1]) ? $aHeaderParts[1] : '';
|
||||||
|
|
||||||
if ('?=' === \substr(\rtrim($sValue), -2))
|
if ('?=' === \substr(\rtrim($sValue), -2)) {
|
||||||
{
|
|
||||||
$sValue = \rtrim($sValue);
|
$sValue = \rtrim($sValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null !== $sName)
|
if (null !== $sName) {
|
||||||
{
|
|
||||||
$oHeader = Header::NewInstanceFromEncodedString($sName.': '.$sValue, $this->sParentCharset);
|
$oHeader = Header::NewInstanceFromEncodedString($sName.': '.$sValue, $this->sParentCharset);
|
||||||
if ($oHeader)
|
if ($oHeader) {
|
||||||
{
|
|
||||||
$this->append($oHeader);
|
$this->append($oHeader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -218,10 +201,8 @@ class HeaderCollection extends \MailSo\Base\Collection
|
||||||
$aResult = array();
|
$aResult = array();
|
||||||
|
|
||||||
$aHeaders = $this->ValuesByName(Enumerations\Header::AUTHENTICATION_RESULTS);
|
$aHeaders = $this->ValuesByName(Enumerations\Header::AUTHENTICATION_RESULTS);
|
||||||
if (\count($aHeaders))
|
if (\count($aHeaders)) {
|
||||||
{
|
foreach ($aHeaders as $sHeaderValue) {
|
||||||
foreach ($aHeaders as $sHeaderValue)
|
|
||||||
{
|
|
||||||
$sStatus = '';
|
$sStatus = '';
|
||||||
$sHeader = '';
|
$sHeader = '';
|
||||||
$sDkimLine = '';
|
$sDkimLine = '';
|
||||||
|
|
@ -230,35 +211,28 @@ class HeaderCollection extends \MailSo\Base\Collection
|
||||||
|
|
||||||
$sHeaderValue = \preg_replace('/[\r\n\t\s]+/', ' ', $sHeaderValue);
|
$sHeaderValue = \preg_replace('/[\r\n\t\s]+/', ' ', $sHeaderValue);
|
||||||
|
|
||||||
if (\preg_match('/dkim=.+/i', $sHeaderValue, $aMatch) && !empty($aMatch[0]))
|
if (\preg_match('/dkim=.+/i', $sHeaderValue, $aMatch) && !empty($aMatch[0])) {
|
||||||
{
|
|
||||||
$sDkimLine = $aMatch[0];
|
$sDkimLine = $aMatch[0];
|
||||||
|
|
||||||
$aMatch = array();
|
$aMatch = array();
|
||||||
if (\preg_match('/dkim=([a-zA-Z0-9]+)/i', $sDkimLine, $aMatch) && !empty($aMatch[1]))
|
if (\preg_match('/dkim=([a-zA-Z0-9]+)/i', $sDkimLine, $aMatch) && !empty($aMatch[1])) {
|
||||||
{
|
|
||||||
$sStatus = $aMatch[1];
|
$sStatus = $aMatch[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
$aMatch = array();
|
$aMatch = array();
|
||||||
if (\preg_match('/header\.(d|i|from)=([^\s;]+)/i', $sDkimLine, $aMatch) && !empty($aMatch[2]))
|
if (\preg_match('/header\.(d|i|from)=([^\s;]+)/i', $sDkimLine, $aMatch) && !empty($aMatch[2])) {
|
||||||
{
|
|
||||||
$sHeader = \trim($aMatch[2]);
|
$sHeader = \trim($aMatch[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($sStatus) && !empty($sHeader))
|
if (!empty($sStatus) && !empty($sHeader)) {
|
||||||
{
|
|
||||||
$aResult[] = array($sStatus, $sHeader, $sDkimLine);
|
$aResult[] = array($sStatus, $sHeader, $sDkimLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// X-DKIM-Authentication-Results: signer="hostinger.com" status="pass"
|
// X-DKIM-Authentication-Results: signer="hostinger.com" status="pass"
|
||||||
$aHeaders = $this->ValuesByName(Enumerations\Header::X_DKIM_AUTHENTICATION_RESULTS);
|
$aHeaders = $this->ValuesByName(Enumerations\Header::X_DKIM_AUTHENTICATION_RESULTS);
|
||||||
foreach ($aHeaders as $sHeaderValue)
|
foreach ($aHeaders as $sHeaderValue) {
|
||||||
{
|
|
||||||
$sStatus = '';
|
$sStatus = '';
|
||||||
$sHeader = '';
|
$sHeader = '';
|
||||||
|
|
||||||
|
|
@ -266,18 +240,15 @@ class HeaderCollection extends \MailSo\Base\Collection
|
||||||
|
|
||||||
$sHeaderValue = \preg_replace('/[\r\n\t\s]+/', ' ', $sHeaderValue);
|
$sHeaderValue = \preg_replace('/[\r\n\t\s]+/', ' ', $sHeaderValue);
|
||||||
|
|
||||||
if (\preg_match('/status[\s]?=[\s]?"([a-zA-Z0-9]+)"/i', $sHeaderValue, $aMatch) && !empty($aMatch[1]))
|
if (\preg_match('/status[\s]?=[\s]?"([a-zA-Z0-9]+)"/i', $sHeaderValue, $aMatch) && !empty($aMatch[1])) {
|
||||||
{
|
|
||||||
$sStatus = $aMatch[1];
|
$sStatus = $aMatch[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\preg_match('/signer[\s]?=[\s]?"([^";]+)"/i', $sHeaderValue, $aMatch) && !empty($aMatch[1]))
|
if (\preg_match('/signer[\s]?=[\s]?"([^";]+)"/i', $sHeaderValue, $aMatch) && !empty($aMatch[1])) {
|
||||||
{
|
|
||||||
$sHeader = \trim($aMatch[1]);
|
$sHeader = \trim($aMatch[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($sStatus) && !empty($sHeader))
|
if (!empty($sStatus) && !empty($sHeader)) {
|
||||||
{
|
|
||||||
$aResult[] = array($sStatus, $sHeader, $sHeaderValue);
|
$aResult[] = array($sStatus, $sHeader, $sHeaderValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -292,9 +263,7 @@ class HeaderCollection extends \MailSo\Base\Collection
|
||||||
foreach ($oEmails as $oEmail) {
|
foreach ($oEmails as $oEmail) {
|
||||||
$sEmail = $oEmail->GetEmail();
|
$sEmail = $oEmail->GetEmail();
|
||||||
foreach ($aDkimStatuses as $aDkimData) {
|
foreach ($aDkimStatuses as $aDkimData) {
|
||||||
if (isset($aDkimData[0], $aDkimData[1]) &&
|
if (isset($aDkimData[0], $aDkimData[1]) && $aDkimData[1] === \strstr($sEmail, $aDkimData[1])) {
|
||||||
$aDkimData[1] === \strstr($sEmail, $aDkimData[1]))
|
|
||||||
{
|
|
||||||
$oEmail->SetDkimStatusAndValue($aDkimData[0], empty($aDkimData[2]) ? '' : $aDkimData[2]);
|
$oEmail->SetDkimStatusAndValue($aDkimData[0], empty($aDkimData[2]) ? '' : $aDkimData[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,7 @@ namespace MailSo\Mime;
|
||||||
*/
|
*/
|
||||||
class Message extends Part
|
class Message extends Part
|
||||||
{
|
{
|
||||||
/**
|
private array $aHeadersValue = array(
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $aHeadersValue = array(
|
|
||||||
/*
|
/*
|
||||||
Enumerations\Header::BCC => '',
|
Enumerations\Header::BCC => '',
|
||||||
Enumerations\Header::CC => '',
|
Enumerations\Header::CC => '',
|
||||||
|
|
@ -42,22 +39,11 @@ class Message extends Part
|
||||||
*/
|
*/
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
private AttachmentCollection $oAttachmentCollection;
|
||||||
* @var AttachmentCollection
|
|
||||||
*/
|
|
||||||
private $oAttachmentCollection;
|
|
||||||
|
|
||||||
/**
|
private bool $bAddEmptyTextPart = true;
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $bAddEmptyTextPart = true;
|
|
||||||
|
|
||||||
/**
|
private bool $bAddDefaultXMailer = true;
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $bAddDefaultXMailer = true;
|
|
||||||
|
|
||||||
public $messageIdRequired = true;
|
|
||||||
|
|
||||||
function __construct()
|
function __construct()
|
||||||
{
|
{
|
||||||
|
|
@ -177,8 +163,7 @@ class Message extends Part
|
||||||
public function SetCustomHeader(string $sHeaderName, string $sValue) : self
|
public function SetCustomHeader(string $sHeaderName, string $sValue) : self
|
||||||
{
|
{
|
||||||
$sHeaderName = \trim($sHeaderName);
|
$sHeaderName = \trim($sHeaderName);
|
||||||
if (\strlen($sHeaderName))
|
if (\strlen($sHeaderName)) {
|
||||||
{
|
|
||||||
$this->aHeadersValue[$sHeaderName] = $sValue;
|
$this->aHeadersValue[$sHeaderName] = $sValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,8 +221,7 @@ class Message extends Part
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\strlen($sResult))
|
if (\strlen($sResult)) {
|
||||||
{
|
|
||||||
$this->aHeadersValue[Enumerations\Header::X_PRIORITY] = $sResult;
|
$this->aHeadersValue[Enumerations\Header::X_PRIORITY] = $sResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,18 +297,15 @@ class Message extends Part
|
||||||
|
|
||||||
private function generateNewMessageId(string $sHostName = '') : string
|
private function generateNewMessageId(string $sHostName = '') : string
|
||||||
{
|
{
|
||||||
if (0 === \strlen($sHostName))
|
if (!\strlen($sHostName)) {
|
||||||
{
|
|
||||||
$sHostName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
|
$sHostName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($sHostName) && \MailSo\Base\Utils::FunctionCallable('php_uname'))
|
if (empty($sHostName) && \MailSo\Base\Utils::FunctionCallable('php_uname')) {
|
||||||
{
|
|
||||||
$sHostName = \php_uname('n');
|
$sHostName = \php_uname('n');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($sHostName))
|
if (empty($sHostName)) {
|
||||||
{
|
|
||||||
$sHostName = 'localhost';
|
$sHostName = 'localhost';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -432,7 +413,7 @@ class Message extends Part
|
||||||
$oRootPart->Headers->SetByName(Enumerations\Header::DATE, \gmdate('r'), true);
|
$oRootPart->Headers->SetByName(Enumerations\Header::DATE, \gmdate('r'), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->messageIdRequired && !isset($this->aHeadersValue[Enumerations\Header::MESSAGE_ID])) {
|
if (!isset($this->aHeadersValue[Enumerations\Header::MESSAGE_ID])) {
|
||||||
$oRootPart->Headers->SetByName(Enumerations\Header::MESSAGE_ID, $this->generateNewMessageId(), true);
|
$oRootPart->Headers->SetByName(Enumerations\Header::MESSAGE_ID, $this->generateNewMessageId(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,9 @@ namespace MailSo\Mime;
|
||||||
*/
|
*/
|
||||||
class Parameter
|
class Parameter
|
||||||
{
|
{
|
||||||
/**
|
private string $sName;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sName;
|
|
||||||
|
|
||||||
/**
|
private string $sValue;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sValue;
|
|
||||||
|
|
||||||
function __construct(string $sName, string $sValue)
|
function __construct(string $sName, string $sValue)
|
||||||
{
|
{
|
||||||
|
|
@ -66,12 +60,11 @@ class Parameter
|
||||||
{
|
{
|
||||||
$this->Reset();
|
$this->Reset();
|
||||||
|
|
||||||
$aParts = explode($sSeparator, $sRawParam, 2);
|
$aParts = \explode($sSeparator, $sRawParam, 2);
|
||||||
|
|
||||||
$this->sName = trim(trim($aParts[0]), '"\'');
|
$this->sName = \trim(\trim($aParts[0]), '"\'');
|
||||||
if (2 === count($aParts))
|
if (2 === \count($aParts)) {
|
||||||
{
|
$this->sValue = \trim(\trim($aParts[1]), '"\'');
|
||||||
$this->sValue = trim(trim($aParts[1]), '"\'');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
@ -79,25 +72,20 @@ class Parameter
|
||||||
|
|
||||||
public function ToString(bool $bConvertSpecialsName = false) : string
|
public function ToString(bool $bConvertSpecialsName = false) : string
|
||||||
{
|
{
|
||||||
$sResult = '';
|
if (!\strlen($this->sName)) {
|
||||||
if (\strlen($this->sName))
|
return '';
|
||||||
{
|
|
||||||
$sResult = $this->sName.'=';
|
|
||||||
if ($bConvertSpecialsName && in_array(strtolower($this->sName), array(
|
|
||||||
strtolower(Enumerations\Parameter::NAME),
|
|
||||||
strtolower(Enumerations\Parameter::FILENAME)
|
|
||||||
)))
|
|
||||||
{
|
|
||||||
$sResult .= '"'.\MailSo\Base\Utils::EncodeUnencodedValue(
|
|
||||||
\MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
|
|
||||||
$this->sValue).'"';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$sResult .= '"'.$this->sValue.'"';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $sResult;
|
if ($bConvertSpecialsName && \in_array(\strtolower($this->sName), array(
|
||||||
|
\strtolower(Enumerations\Parameter::NAME),
|
||||||
|
\strtolower(Enumerations\Parameter::FILENAME)
|
||||||
|
)))
|
||||||
|
{
|
||||||
|
return $this->sName . '="' . \MailSo\Base\Utils::EncodeUnencodedValue(
|
||||||
|
\MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
|
||||||
|
$this->sValue) . '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->sName . '="' . $this->sValue . '"';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,7 @@ class ParameterCollection extends \MailSo\Base\Collection
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
if (\strlen($sRawParams))
|
\strlen($sRawParams) && $this->Parse($sRawParams);
|
||||||
{
|
|
||||||
$this->Parse($sRawParams);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function append($oParameter, bool $bToTop = false) : void
|
public function append($oParameter, bool $bToTop = false) : void
|
||||||
|
|
@ -66,8 +63,7 @@ class ParameterCollection extends \MailSo\Base\Collection
|
||||||
|
|
||||||
$aDataToParse = \explode(';', $sRawParams);
|
$aDataToParse = \explode(';', $sRawParams);
|
||||||
|
|
||||||
foreach ($aDataToParse as $sParam)
|
foreach ($aDataToParse as $sParam) {
|
||||||
{
|
|
||||||
$this->append(Parameter::CreateFromParameterLine($sParam));
|
$this->append(Parameter::CreateFromParameterLine($sParam));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,11 +75,9 @@ class ParameterCollection extends \MailSo\Base\Collection
|
||||||
public function ToString(bool $bConvertSpecialsName = false) : string
|
public function ToString(bool $bConvertSpecialsName = false) : string
|
||||||
{
|
{
|
||||||
$aResult = array();
|
$aResult = array();
|
||||||
foreach ($this as $oParam)
|
foreach ($this as $oParam) {
|
||||||
{
|
|
||||||
$sLine = $oParam->ToString($bConvertSpecialsName);
|
$sLine = $oParam->ToString($bConvertSpecialsName);
|
||||||
if (\strlen($sLine))
|
if (\strlen($sLine)) {
|
||||||
{
|
|
||||||
$aResult[] = $sLine;
|
$aResult[] = $sLine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -99,26 +93,22 @@ class ParameterCollection extends \MailSo\Base\Collection
|
||||||
$this->Clear();
|
$this->Clear();
|
||||||
|
|
||||||
$aPreParams = array();
|
$aPreParams = array();
|
||||||
foreach ($aDataToReParse as $oParam)
|
foreach ($aDataToReParse as $oParam) {
|
||||||
{
|
|
||||||
$aMatch = array();
|
$aMatch = array();
|
||||||
$sParamName = $oParam->Name();
|
$sParamName = $oParam->Name();
|
||||||
|
|
||||||
if (\preg_match('/([^\*]+)\*([\d]{1,2})\*/', $sParamName, $aMatch) && isset($aMatch[1], $aMatch[2])
|
if (\preg_match('/([^\*]+)\*([\d]{1,2})\*/', $sParamName, $aMatch) && isset($aMatch[1], $aMatch[2])
|
||||||
&& \strlen($aMatch[1]) && \is_numeric($aMatch[2]))
|
&& \strlen($aMatch[1]) && \is_numeric($aMatch[2]))
|
||||||
{
|
{
|
||||||
if (!isset($aPreParams[$aMatch[1]]))
|
if (!isset($aPreParams[$aMatch[1]])) {
|
||||||
{
|
|
||||||
$aPreParams[$aMatch[1]] = array();
|
$aPreParams[$aMatch[1]] = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$sValue = $oParam->Value();
|
$sValue = $oParam->Value();
|
||||||
|
|
||||||
if (false !== \strpos($sValue, "''"))
|
if (false !== \strpos($sValue, "''")) {
|
||||||
{
|
|
||||||
$aValueParts = \explode("''", $sValue, 2);
|
$aValueParts = \explode("''", $sValue, 2);
|
||||||
if (\is_array($aValueParts) && 2 === \count($aValueParts) && \strlen($aValueParts[1]))
|
if (\is_array($aValueParts) && 2 === \count($aValueParts) && \strlen($aValueParts[1])) {
|
||||||
{
|
|
||||||
$sCharset = $aValueParts[0];
|
$sCharset = $aValueParts[0];
|
||||||
$sValue = $aValueParts[1];
|
$sValue = $aValueParts[1];
|
||||||
}
|
}
|
||||||
|
|
@ -128,17 +118,14 @@ class ParameterCollection extends \MailSo\Base\Collection
|
||||||
}
|
}
|
||||||
else if (\preg_match('/([^\*]+)\*/', $sParamName, $aMatch) && isset($aMatch[1]))
|
else if (\preg_match('/([^\*]+)\*/', $sParamName, $aMatch) && isset($aMatch[1]))
|
||||||
{
|
{
|
||||||
if (!isset($aPreParams[$aMatch[1]]))
|
if (!isset($aPreParams[$aMatch[1]])) {
|
||||||
{
|
|
||||||
$aPreParams[$aMatch[1]] = array();
|
$aPreParams[$aMatch[1]] = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$sValue = $oParam->Value();
|
$sValue = $oParam->Value();
|
||||||
if (false !== \strpos($sValue, "''"))
|
if (false !== \strpos($sValue, "''")) {
|
||||||
{
|
|
||||||
$aValueParts = \explode("''", $sValue, 2);
|
$aValueParts = \explode("''", $sValue, 2);
|
||||||
if (\is_array($aValueParts) && 2 === \count($aValueParts) && \strlen($aValueParts[1]))
|
if (\is_array($aValueParts) && 2 === \count($aValueParts) && \strlen($aValueParts[1])) {
|
||||||
{
|
|
||||||
$sCharset = $aValueParts[0];
|
$sCharset = $aValueParts[0];
|
||||||
$sValue = $aValueParts[1];
|
$sValue = $aValueParts[1];
|
||||||
}
|
}
|
||||||
|
|
@ -152,14 +139,12 @@ class ParameterCollection extends \MailSo\Base\Collection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($aPreParams as $sName => $aValues)
|
foreach ($aPreParams as $sName => $aValues) {
|
||||||
{
|
\ksort($aValues);
|
||||||
ksort($aValues);
|
|
||||||
$sResult = \implode(\array_values($aValues));
|
$sResult = \implode(\array_values($aValues));
|
||||||
$sResult = \urldecode($sResult);
|
$sResult = \urldecode($sResult);
|
||||||
|
|
||||||
if (\strlen($sCharset))
|
if (\strlen($sCharset)) {
|
||||||
{
|
|
||||||
$sResult = \MailSo\Base\Utils::ConvertEncoding($sResult,
|
$sResult = \MailSo\Base\Utils::ConvertEncoding($sResult,
|
||||||
$sCharset, \MailSo\Base\Enumerations\Charset::UTF_8);
|
$sCharset, \MailSo\Base\Enumerations\Charset::UTF_8);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ abstract class Parser
|
||||||
POS_SUBPARTS = 3,
|
POS_SUBPARTS = 3,
|
||||||
POS_CLOSE_BOUNDARY = 4;
|
POS_CLOSE_BOUNDARY = 4;
|
||||||
|
|
||||||
private static $LineParts = [];
|
private static array $LineParts = [];
|
||||||
|
|
||||||
protected static function writeBody(Part $oPart, string $sBuffer) : void
|
protected static function writeBody(Part $oPart, string $sBuffer) : void
|
||||||
{
|
{
|
||||||
|
|
@ -59,21 +59,18 @@ abstract class Parser
|
||||||
|
|
||||||
$oMimePart = null;
|
$oMimePart = null;
|
||||||
$sFirstNotNullCharset = null;
|
$sFirstNotNullCharset = null;
|
||||||
foreach (static::$LineParts as /* @var $oMimePart Part */ $oMimePart)
|
foreach (static::$LineParts as /* @var $oMimePart Part */ $oMimePart) {
|
||||||
{
|
|
||||||
$sCharset = $oMimePart->HeaderCharset();
|
$sCharset = $oMimePart->HeaderCharset();
|
||||||
if (\strlen($sCharset))
|
if (\strlen($sCharset)) {
|
||||||
{
|
|
||||||
$sFirstNotNullCharset = $sCharset;
|
$sFirstNotNullCharset = $sCharset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sFirstNotNullCharset = (null !== $sFirstNotNullCharset)
|
$sFirstNotNullCharset = (null !== $sFirstNotNullCharset)
|
||||||
? $sFirstNotNullCharset : Part::$DefaultCharset;
|
? $sFirstNotNullCharset : \MailSo\Base\Enumerations\Charset::ISO_8859_1;
|
||||||
|
|
||||||
foreach (static::$LineParts as /* @var $oMimePart Part */ $oMimePart)
|
foreach (static::$LineParts as /* @var $oMimePart Part */ $oMimePart) {
|
||||||
{
|
|
||||||
$sHeaderCharset = $oMimePart->HeaderCharset();
|
$sHeaderCharset = $oMimePart->HeaderCharset();
|
||||||
$oMimePart->Headers->SetParentCharset($sHeaderCharset);
|
$oMimePart->Headers->SetParentCharset($sHeaderCharset);
|
||||||
}
|
}
|
||||||
|
|
@ -93,53 +90,38 @@ abstract class Parser
|
||||||
$sCurrentBoundary = '';
|
$sCurrentBoundary = '';
|
||||||
$bIsBoundaryCheck = false;
|
$bIsBoundaryCheck = false;
|
||||||
$aHeadersLines = array();
|
$aHeadersLines = array();
|
||||||
while (true)
|
while (true) {
|
||||||
{
|
if (!$bNotFirstRead) {
|
||||||
if (!$bNotFirstRead)
|
|
||||||
{
|
|
||||||
$sPrevBuffer = $sBuffer;
|
$sPrevBuffer = $sBuffer;
|
||||||
$sBuffer = '';
|
$sBuffer = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$bIsOef && !\feof($rStreamHandle))
|
if (!$bIsOef && !\feof($rStreamHandle)) {
|
||||||
{
|
if (!$bNotFirstRead) {
|
||||||
if (!$bNotFirstRead)
|
|
||||||
{
|
|
||||||
$sBuffer = \fread($rStreamHandle, 8192);
|
$sBuffer = \fread($rStreamHandle, 8192);
|
||||||
if (false === $sBuffer)
|
if (false === $sBuffer) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$bNotFirstRead = false;
|
$bNotFirstRead = false;
|
||||||
}
|
}
|
||||||
}
|
} else if ($bIsOef && !\strlen($sBuffer)) {
|
||||||
else if ($bIsOef && !\strlen($sBuffer))
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$bIsOef = true;
|
$bIsOef = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true)
|
while (true) {
|
||||||
{
|
|
||||||
$sCurrentLine = $sPrevBuffer.$sBuffer;
|
$sCurrentLine = $sPrevBuffer.$sBuffer;
|
||||||
if (self::POS_HEADERS === $iParsePosition)
|
if (self::POS_HEADERS === $iParsePosition) {
|
||||||
{
|
|
||||||
$iEndLen = 4;
|
$iEndLen = 4;
|
||||||
$iPos = \strpos($sCurrentLine, "\r\n\r\n", $iOffset);
|
$iPos = \strpos($sCurrentLine, "\r\n\r\n", $iOffset);
|
||||||
if (false === $iPos)
|
if (false === $iPos) {
|
||||||
{
|
|
||||||
$iEndLen = 2;
|
$iEndLen = 2;
|
||||||
$iPos = \strpos($sCurrentLine, "\n\n", $iOffset);
|
$iPos = \strpos($sCurrentLine, "\n\n", $iOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false !== $iPos)
|
if (false !== $iPos) {
|
||||||
{
|
|
||||||
$aHeadersLines[] = \substr($sCurrentLine, $iOffset, $iPos + $iEndLen - $iOffset);
|
$aHeadersLines[] = \substr($sCurrentLine, $iOffset, $iPos + $iEndLen - $iOffset);
|
||||||
|
|
||||||
$oPart->Headers->Parse(\implode($aHeadersLines))->SetParentCharset($oPart->HeaderCharset());
|
$oPart->Headers->Parse(\implode($aHeadersLines))->SetParentCharset($oPart->HeaderCharset());
|
||||||
|
|
@ -156,42 +138,31 @@ abstract class Parser
|
||||||
$iOffset = $iPos + $iEndLen;
|
$iOffset = $iPos + $iEndLen;
|
||||||
$iParsePosition = self::POS_BODY;
|
$iParsePosition = self::POS_BODY;
|
||||||
continue;
|
continue;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$iBufferLen = \strlen($sPrevBuffer);
|
$iBufferLen = \strlen($sPrevBuffer);
|
||||||
if ($iBufferLen > $iOffset)
|
if ($iBufferLen > $iOffset) {
|
||||||
{
|
|
||||||
$aHeadersLines[] = \substr($sPrevBuffer, $iOffset);
|
$aHeadersLines[] = \substr($sPrevBuffer, $iOffset);
|
||||||
$iOffset = 0;
|
$iOffset = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$iOffset -= $iBufferLen;
|
$iOffset -= $iBufferLen;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else if (self::POS_BODY === $iParsePosition) {
|
||||||
else if (self::POS_BODY === $iParsePosition)
|
|
||||||
{
|
|
||||||
$iPos = false;
|
$iPos = false;
|
||||||
$sBoundaryLen = 0;
|
$sBoundaryLen = 0;
|
||||||
$bIsBoundaryEnd = false;
|
$bIsBoundaryEnd = false;
|
||||||
$bCurrentPartBody = false;
|
$bCurrentPartBody = false;
|
||||||
$bIsBoundaryCheck = \count($aBoundaryStack);
|
$bIsBoundaryCheck = \count($aBoundaryStack);
|
||||||
|
|
||||||
foreach ($aBoundaryStack as $sKey => $sBoundary)
|
foreach ($aBoundaryStack as $sKey => $sBoundary) {
|
||||||
{
|
if (false !== ($iPos = \strpos($sCurrentLine, $sBoundary, $iOffset))) {
|
||||||
if (false !== ($iPos = \strpos($sCurrentLine, $sBoundary, $iOffset)))
|
if ($sCurrentBoundary === $sBoundary) {
|
||||||
{
|
|
||||||
if ($sCurrentBoundary === $sBoundary)
|
|
||||||
{
|
|
||||||
$bCurrentPartBody = true;
|
$bCurrentPartBody = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sBoundaryLen = \strlen($sBoundary);
|
$sBoundaryLen = \strlen($sBoundary);
|
||||||
if ('--' === \substr($sCurrentLine, $iPos + $sBoundaryLen, 2))
|
if ('--' === \substr($sCurrentLine, $iPos + $sBoundaryLen, 2)) {
|
||||||
{
|
|
||||||
$sBoundaryLen += 2;
|
$sBoundaryLen += 2;
|
||||||
$bIsBoundaryEnd = true;
|
$bIsBoundaryEnd = true;
|
||||||
unset($aBoundaryStack[$sKey]);
|
unset($aBoundaryStack[$sKey]);
|
||||||
|
|
@ -203,54 +174,42 @@ abstract class Parser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false !== $iPos)
|
if (false !== $iPos) {
|
||||||
{
|
|
||||||
static::writeBody($oPart, \substr($sCurrentLine, $iOffset, $iPos - $iOffset));
|
static::writeBody($oPart, \substr($sCurrentLine, $iOffset, $iPos - $iOffset));
|
||||||
$iOffset = $iPos;
|
$iOffset = $iPos;
|
||||||
|
|
||||||
if ($bCurrentPartBody)
|
if ($bCurrentPartBody) {
|
||||||
{
|
|
||||||
$iParsePosition = self::POS_SUBPARTS;
|
$iParsePosition = self::POS_SUBPARTS;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$iBufferLen = \strlen($sPrevBuffer);
|
$iBufferLen = \strlen($sPrevBuffer);
|
||||||
if ($iBufferLen > $iOffset)
|
if ($iBufferLen > $iOffset) {
|
||||||
{
|
|
||||||
static::writeBody($oPart, \substr($sPrevBuffer, $iOffset));
|
static::writeBody($oPart, \substr($sPrevBuffer, $iOffset));
|
||||||
$iOffset = 0;
|
$iOffset = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$iOffset -= $iBufferLen;
|
$iOffset -= $iBufferLen;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else if (self::POS_SUBPARTS === $iParsePosition) {
|
||||||
else if (self::POS_SUBPARTS === $iParsePosition)
|
|
||||||
{
|
|
||||||
$iPos = false;
|
$iPos = false;
|
||||||
$iBoundaryLen = 0;
|
$iBoundaryLen = 0;
|
||||||
$bIsBoundaryEnd = false;
|
$bIsBoundaryEnd = false;
|
||||||
$bCurrentPartBody = false;
|
$bCurrentPartBody = false;
|
||||||
$bIsBoundaryCheck = \count($aBoundaryStack);
|
$bIsBoundaryCheck = \count($aBoundaryStack);
|
||||||
|
|
||||||
foreach ($aBoundaryStack as $sKey => $sBoundary)
|
foreach ($aBoundaryStack as $sKey => $sBoundary) {
|
||||||
{
|
$iPos = \strpos($sCurrentLine, $sBoundary, $iOffset);
|
||||||
if (false !== ($iPos = \strpos($sCurrentLine, $sBoundary, $iOffset)))
|
if (false !== $iPos) {
|
||||||
{
|
if ($sCurrentBoundary === $sBoundary) {
|
||||||
if ($sCurrentBoundary === $sBoundary)
|
|
||||||
{
|
|
||||||
$bCurrentPartBody = true;
|
$bCurrentPartBody = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$iBoundaryLen = \strlen($sBoundary);
|
$iBoundaryLen = \strlen($sBoundary);
|
||||||
if ('--' === \substr($sCurrentLine, $iPos + $iBoundaryLen, 2))
|
if ('--' === \substr($sCurrentLine, $iPos + $iBoundaryLen, 2)) {
|
||||||
{
|
|
||||||
$iBoundaryLen += 2;
|
$iBoundaryLen += 2;
|
||||||
$bIsBoundaryEnd = true;
|
$bIsBoundaryEnd = true;
|
||||||
unset($aBoundaryStack[$sKey]);
|
unset($aBoundaryStack[$sKey]);
|
||||||
|
|
@ -261,8 +220,7 @@ abstract class Parser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false !== $iPos && $bCurrentPartBody)
|
if (false !== $iPos && $bCurrentPartBody) {
|
||||||
{
|
|
||||||
$iOffset = $iPos + $iBoundaryLen;
|
$iOffset = $iPos + $iBoundaryLen;
|
||||||
|
|
||||||
$oSubPart = new Part;
|
$oSubPart = new Part;
|
||||||
|
|
@ -274,39 +232,27 @@ abstract class Parser
|
||||||
static::$LineParts[] = $oSubPart;
|
static::$LineParts[] = $oSubPart;
|
||||||
//$iParsePosition = self::POS_HEADERS;
|
//$iParsePosition = self::POS_HEADERS;
|
||||||
unset($oSubPart);
|
unset($oSubPart);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\strlen($sPrevBuffer))
|
if (\strlen($sPrevBuffer)) {
|
||||||
{
|
if (self::POS_HEADERS === $iParsePosition) {
|
||||||
if (self::POS_HEADERS === $iParsePosition)
|
|
||||||
{
|
|
||||||
$aHeadersLines[] = ($iOffset < \strlen($sPrevBuffer))
|
$aHeadersLines[] = ($iOffset < \strlen($sPrevBuffer))
|
||||||
? \substr($sPrevBuffer, $iOffset)
|
? \substr($sPrevBuffer, $iOffset)
|
||||||
: $sPrevBuffer;
|
: $sPrevBuffer;
|
||||||
|
|
||||||
$oPart->Headers->Parse(\implode($aHeadersLines))->SetParentCharset($oPart->HeaderCharset());
|
$oPart->Headers->Parse(\implode($aHeadersLines))->SetParentCharset($oPart->HeaderCharset());
|
||||||
$aHeadersLines = array();
|
$aHeadersLines = array();
|
||||||
}
|
} else if (!$bIsBoundaryCheck && self::POS_BODY === $iParsePosition) {
|
||||||
else if (self::POS_BODY === $iParsePosition)
|
|
||||||
{
|
|
||||||
if (!$bIsBoundaryCheck)
|
|
||||||
{
|
|
||||||
static::writeBody($oPart, ($iOffset < \strlen($sPrevBuffer))
|
static::writeBody($oPart, ($iOffset < \strlen($sPrevBuffer))
|
||||||
? \substr($sPrevBuffer, $iOffset) : $sPrevBuffer);
|
? \substr($sPrevBuffer, $iOffset) : $sPrevBuffer);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
}
|
if (self::POS_HEADERS === $iParsePosition && \count($aHeadersLines)) {
|
||||||
else
|
|
||||||
{
|
|
||||||
if (self::POS_HEADERS === $iParsePosition && \count($aHeadersLines))
|
|
||||||
{
|
|
||||||
$oPart->Headers->Parse(\implode($aHeadersLines))->SetParentCharset($oPart->HeaderCharset());
|
$oPart->Headers->Parse(\implode($aHeadersLines))->SetParentCharset($oPart->HeaderCharset());
|
||||||
$aHeadersLines = array();
|
$aHeadersLines = array();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,7 @@ namespace MailSo\Mime;
|
||||||
*/
|
*/
|
||||||
class Part
|
class Part
|
||||||
{
|
{
|
||||||
/**
|
public HeaderCollection $Headers;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public static $DefaultCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var HeaderCollection
|
|
||||||
*/
|
|
||||||
public $Headers;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var resource
|
* @var resource
|
||||||
|
|
@ -37,10 +29,7 @@ class Part
|
||||||
*/
|
*/
|
||||||
public $Raw = null;
|
public $Raw = null;
|
||||||
|
|
||||||
/**
|
public PartCollection $SubParts;
|
||||||
* @var PartCollection
|
|
||||||
*/
|
|
||||||
public $SubParts;
|
|
||||||
|
|
||||||
function __construct()
|
function __construct()
|
||||||
{
|
{
|
||||||
|
|
@ -74,39 +63,29 @@ class Part
|
||||||
}
|
}
|
||||||
|
|
||||||
public function IsFlowedFormat() : bool
|
public function IsFlowedFormat() : bool
|
||||||
{
|
|
||||||
$bResult = false;
|
|
||||||
if ($this->Headers)
|
|
||||||
{
|
{
|
||||||
$bResult = 'flowed' === \trim(\strtolower($this->Headers->ParameterValue(
|
$bResult = 'flowed' === \trim(\strtolower($this->Headers->ParameterValue(
|
||||||
Enumerations\Header::CONTENT_TYPE,
|
Enumerations\Header::CONTENT_TYPE,
|
||||||
Enumerations\Parameter::FORMAT)));
|
Enumerations\Parameter::FORMAT)));
|
||||||
|
|
||||||
if ($bResult && \in_array($this->MailEncodingName(), array('base64', 'quoted-printable')))
|
if ($bResult && \in_array($this->MailEncodingName(), array('base64', 'quoted-printable'))) {
|
||||||
{
|
|
||||||
$bResult = false;
|
$bResult = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return $bResult;
|
return $bResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function FileName() : string
|
public function FileName() : string
|
||||||
{
|
|
||||||
$sResult = '';
|
|
||||||
if ($this->Headers)
|
|
||||||
{
|
{
|
||||||
$sResult = \trim($this->Headers->ParameterValue(
|
$sResult = \trim($this->Headers->ParameterValue(
|
||||||
Enumerations\Header::CONTENT_DISPOSITION,
|
Enumerations\Header::CONTENT_DISPOSITION,
|
||||||
Enumerations\Parameter::FILENAME));
|
Enumerations\Parameter::FILENAME));
|
||||||
|
|
||||||
if (!\strlen($sResult))
|
if (!\strlen($sResult)) {
|
||||||
{
|
|
||||||
$sResult = \trim($this->Headers->ParameterValue(
|
$sResult = \trim($this->Headers->ParameterValue(
|
||||||
Enumerations\Header::CONTENT_TYPE,
|
Enumerations\Header::CONTENT_TYPE,
|
||||||
Enumerations\Parameter::NAME));
|
Enumerations\Parameter::NAME));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return $sResult;
|
return $sResult;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace MailSo\Mime;
|
||||||
*/
|
*/
|
||||||
class PartCollection extends \MailSo\Base\Collection
|
class PartCollection extends \MailSo\Base\Collection
|
||||||
{
|
{
|
||||||
protected $sBoundary;
|
protected string $sBoundary = '';
|
||||||
|
|
||||||
public function append($oPart, bool $bToTop = false) : void
|
public function append($oPart, bool $bToTop = false) : void
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,9 @@ namespace MailSo\Net\Exceptions;
|
||||||
*/
|
*/
|
||||||
class SocketCanNotConnectToHostException extends ConnectionException
|
class SocketCanNotConnectToHostException extends ConnectionException
|
||||||
{
|
{
|
||||||
/**
|
private string $sSocketMessage;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sSocketMessage;
|
|
||||||
|
|
||||||
/**
|
private int $iSocketCode;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iSocketCode;
|
|
||||||
|
|
||||||
public function __construct(string $sSocketMessage = '', int $iSocketCode = 0, string $sMessage = '', int $iCode = 0, ?\Throwable $oPrevious = null)
|
public function __construct(string $sSocketMessage = '', int $iSocketCode = 0, string $sMessage = '', int $iCode = 0, ?\Throwable $oPrevious = null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,7 @@ namespace MailSo\Sieve\Exceptions;
|
||||||
*/
|
*/
|
||||||
class ResponseException extends \MailSo\RuntimeException
|
class ResponseException extends \MailSo\RuntimeException
|
||||||
{
|
{
|
||||||
/**
|
private array $aResponses;
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $aResponses;
|
|
||||||
|
|
||||||
public function __construct(array $aResponses = array(), string $sMessage = '', int $iCode = 0, ?\Throwable $oPrevious = null)
|
public function __construct(array $aResponses = array(), string $sMessage = '', int $iCode = 0, ?\Throwable $oPrevious = null)
|
||||||
{
|
{
|
||||||
|
|
@ -37,7 +34,7 @@ class ResponseException extends \MailSo\RuntimeException
|
||||||
|
|
||||||
public function GetLastResponse() : ?\MailSo\Sieve\Response
|
public function GetLastResponse() : ?\MailSo\Sieve\Response
|
||||||
{
|
{
|
||||||
$iCnt = count($this->aResponses);
|
$iCnt = \count($this->aResponses);
|
||||||
return $iCnt ? $this->aResponses[$iCnt - 1] : null;
|
return $iCnt ? $this->aResponses[$iCnt - 1] : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ class SieveClient extends \MailSo\Net\NetClient
|
||||||
$bAuth = false;
|
$bAuth = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (0 === \strpos($type, 'SCRAM-'))
|
if (\str_starts_with($type, 'SCRAM-'))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
$sAuthzid = $this->getResponseValue($this->SendRequestGetResponse('AUTHENTICATE', array($type)), \MailSo\Imap\Enumerations\ResponseType::CONTINUATION);
|
$sAuthzid = $this->getResponseValue($this->SendRequestGetResponse('AUTHENTICATE', array($type)), \MailSo\Imap\Enumerations\ResponseType::CONTINUATION);
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,7 @@ namespace MailSo\Smtp\Exceptions;
|
||||||
*/
|
*/
|
||||||
class ResponseException extends \MailSo\RuntimeException
|
class ResponseException extends \MailSo\RuntimeException
|
||||||
{
|
{
|
||||||
/**
|
private array $aResponses;
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $aResponses;
|
|
||||||
|
|
||||||
public function __construct(array $aResponses = array(), string $sMessage = '', int $iCode = 0, ?\Throwable $oPrevious = null)
|
public function __construct(array $aResponses = array(), string $sMessage = '', int $iCode = 0, ?\Throwable $oPrevious = null)
|
||||||
{
|
{
|
||||||
|
|
@ -37,7 +34,7 @@ class ResponseException extends \MailSo\RuntimeException
|
||||||
|
|
||||||
public function GetLastResponse() : ?\MailSo\Smtp\Response
|
public function GetLastResponse() : ?\MailSo\Smtp\Response
|
||||||
{
|
{
|
||||||
$iCnt = count($this->aResponses);
|
$iCnt = \count($this->aResponses);
|
||||||
return $iCnt ? $this->aResponses[$iCnt - 1] : null;
|
return $iCnt ? $this->aResponses[$iCnt - 1] : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ class SmtpClient extends \MailSo\Net\NetClient
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (0 === \strpos($type, 'SCRAM-')) {
|
if (\str_starts_with($type, 'SCRAM-')) {
|
||||||
// RFC 5802
|
// RFC 5802
|
||||||
$sResult = $this->sendRequestWithCheck($SASL->authenticate($sLogin, $sPassword, $sResult), 234, '');
|
$sResult = $this->sendRequestWithCheck($SASL->authenticate($sLogin, $sPassword, $sResult), 234, '');
|
||||||
$sChallenge = $SASL->challenge($sResult);
|
$sChallenge = $SASL->challenge($sResult);
|
||||||
|
|
|
||||||
|
|
@ -890,7 +890,7 @@ class Actions
|
||||||
{
|
{
|
||||||
$time = \microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
|
$time = \microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
|
||||||
if ($iDelay > $time) {
|
if ($iDelay > $time) {
|
||||||
\usleep(($iDelay - $time) * 1000000);
|
\usleep(\intval(($iDelay - $time) * 1000000));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,7 @@ trait Response
|
||||||
;
|
;
|
||||||
|
|
||||||
$aAdditionalParams = array();
|
$aAdditionalParams = array();
|
||||||
if (null !== $iErrorCode)
|
if (null !== $iErrorCode) {
|
||||||
{
|
|
||||||
$aAdditionalParams['ErrorCode'] = (int) $iErrorCode;
|
$aAdditionalParams['ErrorCode'] = (int) $iErrorCode;
|
||||||
$aAdditionalParams['ErrorMessage'] = null === $sErrorMessage ? '' : (string) $sErrorMessage;
|
$aAdditionalParams['ErrorMessage'] = null === $sErrorMessage ? '' : (string) $sErrorMessage;
|
||||||
$aAdditionalParams['ErrorMessageAdditional'] = null === $sAdditionalErrorMessage ? '' : (string) $sAdditionalErrorMessage;
|
$aAdditionalParams['ErrorMessageAdditional'] = null === $sAdditionalErrorMessage ? '' : (string) $sAdditionalErrorMessage;
|
||||||
|
|
@ -56,35 +55,27 @@ trait Response
|
||||||
$sErrorMessage = null;
|
$sErrorMessage = null;
|
||||||
$sErrorMessageAdditional = null;
|
$sErrorMessageAdditional = null;
|
||||||
|
|
||||||
if ($oException instanceof \RainLoop\Exceptions\ClientException)
|
if ($oException instanceof \RainLoop\Exceptions\ClientException) {
|
||||||
{
|
|
||||||
$iErrorCode = $oException->getCode();
|
$iErrorCode = $oException->getCode();
|
||||||
$sErrorMessage = null;
|
$sErrorMessage = null;
|
||||||
|
|
||||||
if ($iErrorCode === Notifications::ClientViewError)
|
if ($iErrorCode === Notifications::ClientViewError) {
|
||||||
{
|
|
||||||
$sErrorMessage = $oException->getMessage();
|
$sErrorMessage = $oException->getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
$sErrorMessageAdditional = $oException->getAdditionalMessage();
|
$sErrorMessageAdditional = $oException->getAdditionalMessage();
|
||||||
if (empty($sErrorMessageAdditional))
|
if (empty($sErrorMessageAdditional)) {
|
||||||
{
|
|
||||||
$sErrorMessageAdditional = null;
|
$sErrorMessageAdditional = null;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$iErrorCode = Notifications::UnknownError;
|
$iErrorCode = Notifications::UnknownError;
|
||||||
$sErrorMessage = $oException->getCode().' - '.$oException->getMessage();
|
$sErrorMessage = $oException->getCode().' - '.$oException->getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
$oPrevious = $oException->getPrevious();
|
$oPrevious = $oException->getPrevious();
|
||||||
if ($oPrevious)
|
if ($oPrevious) {
|
||||||
{
|
|
||||||
$this->Logger()->WriteException($oPrevious);
|
$this->Logger()->WriteException($oPrevious);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$this->Logger()->WriteException($oException);
|
$this->Logger()->WriteException($oException);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,8 +96,7 @@ trait Response
|
||||||
'Result' => $this->responseObject($mResult, $sActionName)
|
'Result' => $this->responseObject($mResult, $sActionName)
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ($aAdditionalParams as $sKey => $mValue)
|
foreach ($aAdditionalParams as $sKey => $mValue) {
|
||||||
{
|
|
||||||
$aResult[$sKey] = $mValue;
|
$aResult[$sKey] = $mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,17 +131,13 @@ trait Response
|
||||||
private $aCheckableFolder = null;
|
private $aCheckableFolder = null;
|
||||||
private function responseObject($mResponse, string $sParent = '')
|
private function responseObject($mResponse, string $sParent = '')
|
||||||
{
|
{
|
||||||
if (!($mResponse instanceof \JsonSerializable))
|
if (!($mResponse instanceof \JsonSerializable)) {
|
||||||
{
|
if (\is_object($mResponse)) {
|
||||||
if (\is_object($mResponse))
|
|
||||||
{
|
|
||||||
return '["'.\get_class($mResponse).'"]';
|
return '["'.\get_class($mResponse).'"]';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\is_array($mResponse))
|
if (\is_array($mResponse)) {
|
||||||
{
|
foreach ($mResponse as $iKey => $oItem) {
|
||||||
foreach ($mResponse as $iKey => $oItem)
|
|
||||||
{
|
|
||||||
$mResponse[$iKey] = $this->responseObject($oItem, $sParent);
|
$mResponse[$iKey] = $this->responseObject($oItem, $sParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -159,14 +145,13 @@ trait Response
|
||||||
return $mResponse;
|
return $mResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($mResponse instanceof \MailSo\Mail\Message)
|
if ($mResponse instanceof \MailSo\Mail\Message) {
|
||||||
{
|
|
||||||
$mResult = $mResponse->jsonSerialize();
|
$mResult = $mResponse->jsonSerialize();
|
||||||
|
|
||||||
$oAccount = $this->getAccountFromToken();
|
$oAccount = $this->getAccountFromToken();
|
||||||
|
|
||||||
if (!$mResult['DateTimeStampInUTC'] || $this->Config()->Get('labs', 'date_from_headers', false)) {
|
if (!$mResult['DateTimeStampInUTC'] || $this->Config()->Get('labs', 'date_from_headers', false)) {
|
||||||
$iDateTimeStampInUTC = $mResponse->HeaderTimeStampInUTC();
|
$iDateTimeStampInUTC = $mResponse->HeaderTimeStampInUTC;
|
||||||
if ($iDateTimeStampInUTC) {
|
if ($iDateTimeStampInUTC) {
|
||||||
$mResult['DateTimeStampInUTC'] = $iDateTimeStampInUTC;
|
$mResult['DateTimeStampInUTC'] = $iDateTimeStampInUTC;
|
||||||
}
|
}
|
||||||
|
|
@ -187,34 +172,30 @@ trait Response
|
||||||
'FileName' => (\strlen($sSubject) ? \MailSo\Base\Utils::SecureFileName($sSubject) : 'message-'.$mResult['Uid']) . '.eml'
|
'FileName' => (\strlen($sSubject) ? \MailSo\Base\Utils::SecureFileName($sSubject) : 'message-'.$mResult['Uid']) . '.eml'
|
||||||
));
|
));
|
||||||
|
|
||||||
$mResult['Attachments'] = $this->responseObject($mResponse->Attachments(), $sParent);
|
$mResult['Attachments'] = $this->responseObject($mResponse->Attachments, $sParent);
|
||||||
|
|
||||||
if ('Message' === $sParent)
|
if ('Message' === $sParent) {
|
||||||
{
|
$mResult['DraftInfo'] = $mResponse->DraftInfo;
|
||||||
$mResult['DraftInfo'] = $mResponse->DraftInfo();
|
$mResult['InReplyTo'] = $mResponse->InReplyTo;
|
||||||
$mResult['InReplyTo'] = $mResponse->InReplyTo();
|
$mResult['UnsubsribeLinks'] = $mResponse->UnsubsribeLinks;
|
||||||
$mResult['UnsubsribeLinks'] = $mResponse->UnsubsribeLinks();
|
$mResult['References'] = $mResponse->References;
|
||||||
$mResult['References'] = $mResponse->References();
|
|
||||||
|
|
||||||
$mResult['Html'] = $mResponse->Html();
|
$mResult['Html'] = $mResponse->Html();
|
||||||
$mResult['Plain'] = $mResponse->Plain();
|
$mResult['Plain'] = $mResponse->Plain();
|
||||||
|
|
||||||
// $this->GetCapa(Capa::OPEN_PGP) || $this->GetCapa(Capa::GNUPG)
|
// $this->GetCapa(Capa::OPEN_PGP) || $this->GetCapa(Capa::GNUPG)
|
||||||
$mResult['PgpSigned'] = $mResponse->PgpSigned();
|
$mResult['PgpSigned'] = $mResponse->pgpSigned;
|
||||||
$mResult['PgpEncrypted'] = $mResponse->PgpEncrypted();
|
$mResult['PgpEncrypted'] = $mResponse->pgpEncrypted;
|
||||||
|
|
||||||
$mResult['ReadReceipt'] = $mResponse->ReadReceipt();
|
$mResult['ReadReceipt'] = $mResponse->ReadReceipt;
|
||||||
|
|
||||||
if (\strlen($mResult['ReadReceipt']) && !\in_array('$forwarded', $mResult['Flags']))
|
if (\strlen($mResult['ReadReceipt']) && !\in_array('$forwarded', $mResult['Flags'])) {
|
||||||
{
|
|
||||||
// \in_array('$mdnsent', $mResult['Flags'])
|
// \in_array('$mdnsent', $mResult['Flags'])
|
||||||
if (\strlen($mResult['ReadReceipt']))
|
if (\strlen($mResult['ReadReceipt'])) {
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$oReadReceipt = \MailSo\Mime\Email::Parse($mResult['ReadReceipt']);
|
$oReadReceipt = \MailSo\Mime\Email::Parse($mResult['ReadReceipt']);
|
||||||
if (!$oReadReceipt)
|
if (!$oReadReceipt) {
|
||||||
{
|
|
||||||
$mResult['ReadReceipt'] = '';
|
$mResult['ReadReceipt'] = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -231,8 +212,7 @@ trait Response
|
||||||
return $mResult;
|
return $mResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($mResponse instanceof \MailSo\Mail\Attachment)
|
if ($mResponse instanceof \MailSo\Mail\Attachment) {
|
||||||
{
|
|
||||||
$mResult = $mResponse->jsonSerialize();
|
$mResult = $mResponse->jsonSerialize();
|
||||||
$mResult['IsThumbnail'] = $this->GetCapa(Capa::ATTACHMENT_THUMBNAILS) && $this->isFileHasThumbnail($mResult['FileName']);
|
$mResult['IsThumbnail'] = $this->GetCapa(Capa::ATTACHMENT_THUMBNAILS) && $this->isFileHasThumbnail($mResult['FileName']);
|
||||||
$mResult['Download'] = Utils::EncodeKeyValuesQ(array(
|
$mResult['Download'] = Utils::EncodeKeyValuesQ(array(
|
||||||
|
|
@ -246,8 +226,7 @@ trait Response
|
||||||
return $mResult;
|
return $mResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($mResponse instanceof \MailSo\Imap\Folder)
|
if ($mResponse instanceof \MailSo\Imap\Folder) {
|
||||||
{
|
|
||||||
$aResult = $mResponse->jsonSerialize();
|
$aResult = $mResponse->jsonSerialize();
|
||||||
|
|
||||||
$sHash = $mResponse->Hash($this->MailClient()->ImapClient()->Hash());
|
$sHash = $mResponse->Hash($this->MailClient()->ImapClient()->Hash());
|
||||||
|
|
@ -268,8 +247,7 @@ trait Response
|
||||||
return $aResult;
|
return $aResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($mResponse instanceof \MailSo\Base\Collection)
|
if ($mResponse instanceof \MailSo\Base\Collection) {
|
||||||
{
|
|
||||||
$mResult = $mResponse->jsonSerialize();
|
$mResult = $mResponse->jsonSerialize();
|
||||||
$mResult['@Collection'] = $this->responseObject($mResult['@Collection'], $sParent);
|
$mResult['@Collection'] = $this->responseObject($mResult['@Collection'], $sParent);
|
||||||
if ($mResponse instanceof \MailSo\Mail\EmailCollection) {
|
if ($mResponse instanceof \MailSo\Mail\EmailCollection) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue