v1.2.12.435

This commit is contained in:
RainLoop Team 2013-10-11 01:56:33 +04:00
parent 513936e5f7
commit 93e620e3de
399 changed files with 765 additions and 687 deletions

View file

@ -0,0 +1,183 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
abstract class Collection
{
/**
* @var array
*/
protected $aItems;
/**
* @access protected
*/
protected function __construct()
{
$this->aItems = array();
}
/**
* @param mixed $mItem
* @param bool $bToTop = false
* @return self
*/
public function Add($mItem, $bToTop = false)
{
if ($bToTop)
{
\array_unshift($this->aItems, $mItem);
}
else
{
\array_push($this->aItems, $mItem);
}
return $this;
}
/**
* @param array $aItems
* @return self
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public function AddArray($aItems)
{
if (!\is_array($aItems))
{
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
}
foreach ($aItems as $mItem)
{
$this->Add($mItem);
}
return $this;
}
/**
* @return self
*/
public function Clear()
{
$this->aItems = array();
return $this;
}
/**
* @return array
*/
public function CloneAsArray()
{
return $this->aItems;
}
/**
* @return int
*/
public function Count()
{
return \count($this->aItems);
}
/**
* @return array
*/
public function &GetAsArray()
{
return $this->aItems;
}
/**
* @param mixed $mCallback
*/
public function MapList($mCallback)
{
$aResult = array();
if (\is_callable($mCallback))
{
foreach ($this->aItems as $oItem)
{
$aResult[] = \call_user_func($mCallback, $oItem);
}
}
return $aResult;
}
/**
* @param mixed $mCallback
* @return array
*/
public function FilterList($mCallback)
{
$aResult = array();
if (\is_callable($mCallback))
{
foreach ($this->aItems as $oItem)
{
if (\call_user_func($mCallback, $oItem))
{
$aResult[] = $oItem;
}
}
}
return $aResult;
}
/**
* @param mixed $mCallback
* @return void
*/
public function ForeachList($mCallback)
{
if (\is_callable($mCallback))
{
foreach ($this->aItems as $oItem)
{
\call_user_func($mCallback, $oItem);
}
}
}
/**
* @return mixed | null
* @return mixed
*/
public function &GetByIndex($iIndex)
{
$mResult = null;
if (\key_exists($iIndex, $this->aItems))
{
$mResult = $this->aItems[$iIndex];
}
return $mResult;
}
/**
* @param array $aItems
* @return self
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public function SetAsArray($aItems)
{
if (!\is_array($aItems))
{
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
}
$this->aItems = $aItems;
return $this;
}
}

View file

@ -0,0 +1,180 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class Crypt {
/**
*
* @param string $sString
* @param string $sKey
*
* @return string
*/
public static function XxteaEncrypt($sString, $sKey)
{
if (0 === \strlen($sString))
{
return '';
}
$aV = self::str2long($sString, true);
$aK = self::str2long($sKey, false);
if (\count($aK) < 4)
{
for ($iIndex = \count($aK); $iIndex < 4; $iIndex++)
{
$aK[$iIndex] = 0;
}
}
$iN = \count($aV) - 1;
$iZ = $aV[$iN];
$iY = $aV[0];
$iDelta = 0x9E3779B9;
$iQ = \floor(6 + 52 / ($iN + 1));
$iSum = 0;
while (0 < $iQ--)
{
$iSum = self::int32($iSum + $iDelta);
$iE = $iSum >> 2 & 3;
for ($iPIndex = 0; $iPIndex < $iN; $iPIndex++)
{
$iY = $aV[$iPIndex + 1];
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
$iZ = $aV[$iPIndex] = self::int32($aV[$iPIndex] + $iMx);
}
$iY = $aV[0];
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
$iZ = $aV[$iN] = self::int32($aV[$iN] + $iMx);
}
return self::long2str($aV, false);
}
/**
* @param string $sEncriptedString
* @param string $sKey
*
* @return string
*/
public static function XxteaDecrypt($sEncriptedString, $sKey)
{
if (0 === \strlen($sEncriptedString))
{
return '';
}
$aV = self::str2long($sEncriptedString, false);
$aK = self::str2long($sKey, false);
if (\count($aK) < 4)
{
for ($iIndex = \count($aK); $iIndex < 4; $iIndex++)
{
$aK[$iIndex] = 0;
}
}
$iN = \count($aV) - 1;
$iZ = $aV[$iN];
$iY = $aV[0];
$iDelta = 0x9E3779B9;
$iQ = \floor(6 + 52 / ($iN + 1));
$iSum = self::int32($iQ * $iDelta);
while ($iSum != 0)
{
$iE = $iSum >> 2 & 3;
for ($iPIndex = $iN; $iPIndex > 0; $iPIndex--)
{
$iZ = $aV[$iPIndex - 1];
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
$iY = $aV[$iPIndex] = self::int32($aV[$iPIndex] - $iMx);
}
$iZ = $aV[$iN];
$iMx = self::int32((($iZ >> 5 & 0x07ffffff) ^ $iY << 2) +
(($iY >> 3 & 0x1fffffff) ^ $iZ << 4)) ^ self::int32(($iSum ^ $iY) + ($aK[$iPIndex & 3 ^ $iE] ^ $iZ));
$iY = $aV[0] = self::int32($aV[0] - $iMx);
$iSum = self::int32($iSum - $iDelta);
}
return self::long2str($aV, true);
}
/**
* @param array $aV
* @param array $aW
*
* @return string
*/
private static function long2str($aV, $aW)
{
$iLen = \count($aV);
$iN = ($iLen - 1) << 2;
if ($aW)
{
$iM = $aV[$iLen - 1];
if (($iM < $iN - 3) || ($iM > $iN))
{
return false;
}
$iN = $iM;
}
$aS = array();
for ($iIndex = 0; $iIndex < $iLen; $iIndex++)
{
$aS[$iIndex] = \pack('V', $aV[$iIndex]);
}
if ($aW)
{
return \substr(\join('', $aS), 0, $iN);
}
else
{
return \join('', $aS);
}
}
/**
* @param string $sS
* @param string $sW
*
* @return array
*/
private static function str2long($sS, $sW)
{
$aV = \unpack('V*', $sS . \str_repeat("\0", (4 - \strlen($sS) % 4) & 3));
$aV = \array_values($aV);
if ($sW)
{
$aV[\count($aV)] = \strlen($sS);
}
return $aV;
}
/**
* @param int $iN
*
* @return int
*/
private static function int32($iN)
{
while ($iN >= 2147483648)
{
$iN -= 4294967296;
}
while ($iN <= -2147483649)
{
$iN += 4294967296;
}
return (int) $iN;
}
}

View file

@ -0,0 +1,74 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class DateTimeHelper
{
/**
* @access private
*/
private function __construct()
{
}
/**
* @staticvar \DateTimeZone $oDateTimeZone
*
* @return \DateTimeZone
*/
public static function GetUtcTimeZoneObject()
{
static $oDateTimeZone = null;
if (null === $oDateTimeZone)
{
$oDateTimeZone = new \DateTimeZone('UTC');
}
return $oDateTimeZone;
}
/**
* Parse date string formated as "Thu, 10 Jun 2010 08:58:33 -0700 (PDT)"
* RFC2822
*
* @param string $sDateTime
*
* @return int
*/
public static function ParseRFC2822DateString($sDateTime)
{
$sDateTime = \trim(\preg_replace('/ \([a-zA-Z0-9]+\)$/', '', \trim($sDateTime)));
$oDateTime = \DateTime::createFromFormat('D, d M Y H:i:s O', $sDateTime, \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject());
return $oDateTime ? $oDateTime->getTimestamp() : 0;
}
/**
* Parse date string formated as "10-Jan-2012 01:58:17 -0800"
* IMAP INTERNALDATE Format
*
* @param string $sDateTime
*
* @return int
*/
public static function ParseInternalDateString($sDateTime)
{
$oDateTime = \DateTime::createFromFormat('d-M-Y H:i:s O', \trim($sDateTime), \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject());
return $oDateTime ? $oDateTime->getTimestamp() : 0;
}
/**
* Parse date string formated as "2011-06-14 23:59:59 +0400"
*
* @param string $sDateTime
*
* @return int
*/
public static function ParseDateStringType1($sDateTime)
{
$oDateTime = \DateTime::createFromFormat('Y-m-d H:i:s O', \trim($sDateTime), \MailSo\Base\DateTimeHelper::GetUtcTimeZoneObject());
return $oDateTime ? $oDateTime->getTimestamp() : 0;
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace MailSo\Base\Enumerations;
/**
* @category MailSo
* @package Base
* @subpackage Enumerations
*/
class Charset
{
const UTF_8 = 'utf-8';
const UTF_7 = 'utf-7';
const UTF_7_IMAP = 'utf7-imap';
const WIN_1250 = 'windows-1250';
const WIN_1251 = 'windows-1251';
const WIN_1252 = 'windows-1252';
const WIN_1253 = 'windows-1253';
const WIN_1254 = 'windows-1254';
const WIN_1255 = 'windows-1255';
const WIN_1256 = 'windows-1256';
const WIN_1257 = 'windows-1257';
const WIN_1258 = 'windows-1258';
const ISO_8859_1 = 'iso-8859-1';
const ISO_8859_8 = 'iso-8859-8';
const ISO_8859_8_I = 'iso-8859-8-i';
}

View file

@ -0,0 +1,24 @@
<?php
namespace MailSo\Base\Enumerations;
/**
* @category MailSo
* @package Base
* @subpackage Enumerations
*/
class Encoding
{
const QUOTED_PRINTABLE = 'Quoted-Printable';
const QUOTED_PRINTABLE_LOWER = 'quoted-printable';
const QUOTED_PRINTABLE_SHORT = 'Q';
const BASE64 = 'Base64';
const BASE64_LOWER = 'base64';
const BASE64_SHORT = 'B';
const SEVEN_BIT = '7bit';
const _7_BIT = '7bit';
const EIGHT_BIT = '8bit';
const _8_BIT = '8bit';
}

View file

@ -0,0 +1,24 @@
<?php
namespace MailSo\Base\Exceptions;
/**
* @category MailSo
* @package Base
* @subpackage Exceptions
*/
class Exception extends \Exception
{
/**
* @param string $sMessage
* @param int $iCode
* @param \Exception|null $oPrevious
*/
public function __construct($sMessage = '', $iCode = 0, $oPrevious = null)
{
$sMessage = 0 === strlen($sMessage) ? str_replace('\\', '-', get_class($this)).' ('.
basename($this->getFile()).' ~ '.$this->getLine().')' : $sMessage;
parent::__construct($sMessage, $iCode, $oPrevious);
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Base\Exceptions;
/**
* @category MailSo
* @package Base
* @subpackage Exceptions
*/
class InvalidArgumentException extends \MailSo\Base\Exceptions\Exception {}

View file

@ -0,0 +1,684 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class HtmlUtils
{
/**
* @access private
*/
private function __construct()
{
}
/**
* @param string $sText
*
* @return \DOMDocument | bool
*/
public static function GetDomFromText($sText)
{
static $bOnce = true;
if ($bOnce)
{
$bOnce = false;
if (\MailSo\Base\Utils::FunctionExistsAndEnabled('libxml_use_internal_errors'))
{
@\libxml_use_internal_errors(true);
}
}
$oDom = new \DOMDocument('1.0', 'utf-8');
// @$oDom->loadHTML('<'.'?xml version="1.0" encoding="utf-8"?'.'>'.
// '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body>'.$sText.'</body></html>');
@$oDom->loadHTML('<'.'?xml version="1.0" encoding="utf-8"?'.'>'.$sText);
return $oDom;
}
/**
* @param string $sHtml
* @param bool $bSetupBody = false
*
* @return string
*/
public static function ClearBodyAndHtmlTag($sHtml, $bSetupBody = false)
{
$sHtml = \preg_replace('/<body([^>]*)>/im', '<div'.($bSetupBody ? ' class="mailso-body" ' : '').'\\1>', $sHtml);
$sHtml = \preg_replace('/<\/body>/im', '</div>', $sHtml);
$sHtml = \preg_replace('/<html([^>]*)>/im', '<div\\1>', $sHtml);
$sHtml = \preg_replace('/<\/html>/im', '</div>', $sHtml);
return $sHtml;
}
/**
* @param string $sHtml
*
* @return string
*/
public static function ClearTags($sHtml)
{
$aRemoveTags = array(
'head', 'link', 'base', 'meta', 'title', 'style', 'script', 'bgsound',
'object', 'embed', 'applet', 'mocha', 'iframe', 'frame', 'frameset'
);
$aToRemove = array(
'/<!doctype[^>]*>/msi',
'/<\?xml [^>]*\?>/msi'
);
foreach ($aRemoveTags as $sTag)
{
$aToRemove[] = '\'<'.$sTag.'[^>]*>.*?</[\s]*'.$sTag.'>\'msi';
$aToRemove[] = '\'<'.$sTag.'[^>]*>\'msi';
$aToRemove[] = '\'</[\s]*'.$sTag.'[^>]*>\'msi';
}
return \preg_replace($aToRemove, '', $sHtml);
}
/**
* @param string $sHtml
*
* @return string
*/
public static function ClearOn($sHtml)
{
$aToReplace = array(
'/on(Blur)/si',
'/on(Change)/si',
'/on(Click)/si',
'/on(DblClick)/si',
'/on(Error)/si',
'/on(Focus)/si',
'/on(KeyDown)/si',
'/on(KeyPress)/si',
'/on(KeyUp)/si',
'/on(Load)/si',
'/on(MouseDown)/si',
'/on(MouseEnter)/si',
'/on(MouseLeave)/si',
'/on(MouseMove)/si',
'/on(MouseOut)/si',
'/on(MouseOver)/si',
'/on(MouseUp)/si',
'/on(Move)/si',
'/on(Resize)/si',
'/on(ResizeEnd)/si',
'/on(ResizeStart)/si',
'/on(Scroll)/si',
'/on(Select)/si',
'/on(Submit)/si',
'/on(Unload)/si'
);
return \preg_replace($aToReplace, 'оn\\1', $sHtml);
}
/**
*
* @param string $sStyle
* @param \DOMElement $oElement
* @param bool $bHasExternals
* @param array $aFoundCIDs
*
* @return string
*/
public static function ClearStyle($sStyle, $oElement, &$bHasExternals, &$aFoundCIDs)
{
$sStyle = \trim($sStyle);
$aOutStyles = array();
$aStyles = \explode(';', $sStyle);
$aMatch = array();
foreach ($aStyles as $sStyleItem)
{
$aStyleValue = \explode(':', $sStyleItem, 2);
$sName = \trim(\strtolower($aStyleValue[0]));
$sValue = isset($aStyleValue[1]) ? \trim($aStyleValue[1]) : '';
if ('position' === $sName && 'fixed' === \strtolower($sValue))
{
$sValue = 'absolute';
}
if (0 === \strlen($sName) || 0 === \strlen($sValue))
{
continue;
}
$sStyleItem = $sName.': '.$sValue;
$aStyleValue = array($sName, $sValue);
/*if (\in_array($sName, array('position', 'left', 'right', 'top', 'bottom', 'behavior', 'cursor')))
{
// skip
}
else */if (\in_array($sName, array('behavior', 'cursor')) ||
('display' === $sName && 'none' === \strtolower($sValue)) ||
\preg_match('/expression/i', $sValue) ||
('text-indent' === $sName && '-' === \substr(trim($sValue), 0, 1))
)
{
// skip
}
else if (\in_array($sName, array('background-image', 'background', 'list-style-image', 'content'))
&& \preg_match('/url[\s]?\(([^)]+)\)/im', $sValue, $aMatch) && !empty($aMatch[1]))
{
$sFullUrl = \trim($aMatch[0], '"\' ');
$sUrl = \trim($aMatch[1], '"\' ');
$sStyleValue = \trim(\preg_replace('/[\s]+/', ' ', \str_replace($sFullUrl, '', $sValue)));
$sStyleItem = empty($sStyleValue) ? '' : $sName.': '.$sStyleValue;
if ('cid:' === \strtolower(\substr($sUrl, 0, 4)))
{
if ($oElement)
{
$oElement->setAttribute('data-x-style-cid-name',
'background' === $sName ? 'background-image' : $sName);
$oElement->setAttribute('data-x-style-cid', \substr($sUrl, 4));
$aFoundCIDs[] = \substr($sUrl, 4);
}
}
else
{
if ($oElement)
{
if (\preg_match('/http[s]?:\/\//i', $sUrl))
{
$bHasExternals = true;
if (\in_array($sName, array('background-image', 'list-style-image', 'content')))
{
$sStyleItem = '';
}
$sTemp = '';
if ($oElement->hasAttribute('data-x-style-url'))
{
$sTemp = \trim($oElement->getAttribute('data-x-style-url'));
}
$sTemp = empty($sTemp) ? '' : (';' === \substr($sTemp, -1) ? $sTemp.' ' : $sTemp.'; ');
$oElement->setAttribute('data-x-style-url', \trim($sTemp.
('background' === $sName ? 'background-image' : $sName).': '.$sFullUrl, ' ;'));
}
else if ('data:image/' !== \strtolower(\substr(\trim($sUrl), 0, 11)))
{
$oElement->setAttribute('data-x-broken-style-src', $sFullUrl);
}
}
}
if (!empty($sStyleItem))
{
$aOutStyles[] = $sStyleItem;
}
}
else if ('height' === $sName)
{
// $aOutStyles[] = 'min-'.ltrim($sStyleItem);
$aOutStyles[] = $sStyleItem;
}
else
{
$aOutStyles[] = $sStyleItem;
}
}
return \implode(';', $aOutStyles);
}
/**
* @param string $sHtml
* @param bool $bHasExternals
* @param array $aFoundCIDs
*
* @return string
*/
public static function ClearHtml($sHtml, &$bHasExternals = false, &$aFoundCIDs = array())
{
$sHtml = null === $sHtml ? '' : (string) $sHtml;
$sHtml = \trim($sHtml);
if (0 === \strlen($sHtml))
{
return '';
}
$bHasExternals = false;
$sHtml = \MailSo\Base\HtmlUtils::ClearTags($sHtml);
$sHtml = \MailSo\Base\HtmlUtils::ClearOn($sHtml);
// $sHtml = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sHtml);
// Dom Part
$oDom = \MailSo\Base\HtmlUtils::GetDomFromText($sHtml);
unset($sHtml);
if ($oDom)
{
$aNodes = $oDom->getElementsByTagName('*');
foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement)
{
$sTagNameLower = \strtolower($oElement->tagName);
if ('iframe' === $sTagNameLower || 'frame' === $sTagNameLower)
{
$oElement->setAttribute('src', 'javascript:false');
}
if (\in_array($sTagNameLower, array('a', 'form', 'area')))
{
$oElement->setAttribute('target', '_blank');
}
if (\in_array($sTagNameLower, array('a', 'form', 'area', 'input', 'button', 'textarea')))
{
$oElement->setAttribute('tabindex', '-1');
}
// if ('blockquote' === $sTagNameLower)
// {
// $oElement->removeAttribute('style');
// }
@$oElement->removeAttribute('id');
@$oElement->removeAttribute('class');
@$oElement->removeAttribute('contenteditable');
@$oElement->removeAttribute('designmode');
@$oElement->removeAttribute('data-bind');
if ($oElement->hasAttribute('src'))
{
$sSrc = \trim($oElement->getAttribute('src'));
$oElement->removeAttribute('src');
if ('cid:' === \strtolower(\substr($sSrc, 0, 4)))
{
$oElement->setAttribute('data-x-src-cid', \substr($sSrc, 4));
$aFoundCIDs[] = \substr($sSrc, 4);
}
else
{
if (\preg_match('/http[s]?:\/\//i', $sSrc))
{
$oElement->setAttribute('data-x-src', $sSrc);
$bHasExternals = true;
}
else if ('data:image/' === \strtolower(\substr(\trim($sSrc), 0, 11)))
{
$oElement->setAttribute('src', $sSrc);
}
else
{
$oElement->setAttribute('data-x-broken-src', $sSrc);
}
}
}
$sBackground = $oElement->hasAttribute('background')
? \trim($oElement->getAttribute('background')) : '';
$sBackgroundColor = $oElement->hasAttribute('bgcolor')
? \trim($oElement->getAttribute('bgcolor')) : '';
if (!empty($sBackground) || !empty($sBackgroundColor))
{
$aStyles = array();
$sStyles = $oElement->hasAttribute('style')
? $oElement->getAttribute('style') : '';
if (!empty($sBackground))
{
$aStyles[] = 'background-image: url(\''.$sBackground.'\')';
$oElement->removeAttribute('background');
}
if (!empty($sBackgroundColor))
{
$aStyles[] = 'background-color: '.$sBackgroundColor;
$oElement->removeAttribute('bgcolor');
}
$oElement->setAttribute('style', (empty($sStyles) ? '' : $sStyles.'; ').\implode('; ', $aStyles));
}
if ($oElement->hasAttribute('style'))
{
$oElement->setAttribute('style',
\MailSo\Base\HtmlUtils::ClearStyle($oElement->getAttribute('style'), $oElement, $bHasExternals, $aFoundCIDs));
}
}
$sResult = $oDom->saveHTML();
}
unset($oDom);
$sResult = \MailSo\Base\HtmlUtils::ClearTags($sResult);
$sResult = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sResult, true);
return \trim($sResult);
}
/**
* @param string $sHtml
* @param array $aFoundCids = array()
* @param array|null $mFoundDataURL = null
*
* @return string
*/
public static function BuildHtml($sHtml, &$aFoundCids = array(), &$mFoundDataURL = null)
{
$oDom = \MailSo\Base\HtmlUtils::GetDomFromText($sHtml);
unset($sHtml);
$aNodes = $oDom->getElementsByTagName('*');
foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement)
{
$sTagNameLower = \strtolower($oElement->tagName);
if ($oElement->hasAttribute('data-x-src-cid'))
{
$sCid = $oElement->getAttribute('data-x-src-cid');
$oElement->removeAttribute('data-x-src-cid');
if (!empty($sCid))
{
$aFoundCids[] = $sCid;
@$oElement->removeAttribute('src');
$oElement->setAttribute('src', 'cid:'.$sCid);
}
}
if ($oElement->hasAttribute('data-x-broken-src'))
{
$oElement->setAttribute('src', $oElement->getAttribute('data-x-broken-src'));
$oElement->removeAttribute('data-x-broken-src');
}
if ($oElement->hasAttribute('data-x-src'))
{
$oElement->setAttribute('src', $oElement->getAttribute('data-x-src'));
$oElement->removeAttribute('data-x-src');
}
if ($oElement->hasAttribute('data-x-href'))
{
$oElement->setAttribute('href', $oElement->getAttribute('data-x-href'));
$oElement->removeAttribute('data-x-href');
}
if ($oElement->hasAttribute('data-x-style-cid-name') && $oElement->hasAttribute('data-x-style-cid'))
{
$sCidName = $oElement->getAttribute('data-x-style-cid-name');
$sCid = $oElement->getAttribute('data-x-style-cid');
$oElement->removeAttribute('data-x-style-cid-name');
$oElement->removeAttribute('data-x-style-cid');
if (!empty($sCidName) && !empty($sCid) && \in_array($sCidName,
array('background-image', 'background', 'list-style-image', 'content')))
{
$sStyles = '';
if ($oElement->hasAttribute('style'))
{
$sStyles = \trim(\trim($oElement->getAttribute('style')), ';');
}
$sBack = $sCidName.': url(cid:'.$sCid.')';
$sStyles = \preg_replace('/'.\preg_quote($sCidName, '/').':\s?[^;]+/i', $sBack, $sStyles);
if (false === \strpos($sStyles, $sBack))
{
$sStyles .= empty($sStyles) ? '': '; ';
$sStyles .= $sBack;
}
$oElement->setAttribute('style', $sStyles);
$aFoundCids[] = $sCid;
}
}
if ($oElement->hasAttribute('data-x-style-url'))
{
$sAddStyles = $oElement->getAttribute('data-x-style-url');
$oElement->removeAttribute('data-x-style-url');
if (!empty($sAddStyles))
{
$sStyles = '';
if ($oElement->hasAttribute('style'))
{
$sStyles = \trim(\trim($oElement->getAttribute('style')), ';');
}
$oElement->setAttribute('style', (empty($sStyles) ? '' : $sStyles.'; ').$sAddStyles);
}
}
if ('img' === $sTagNameLower && \is_array($mFoundDataURL))
{
$sSrc = $oElement->getAttribute('src');
if ('data:image/' === \strtolower(\substr($sSrc, 0, 11)))
{
$sHash = \md5($sSrc);
$mFoundDataURL[$sHash] = $sSrc;
$oElement->setAttribute('src', 'cid:'.$sHash);
}
}
}
$sResult = $oDom->saveHTML();
unset($oDom);
$sResult = \MailSo\Base\HtmlUtils::ClearTags($sResult);
$sResult = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sResult);
return '<!DOCTYPE html><html'.(\MailSo\Base\Utils::IsRTL($sResult) ? ' dir="rtl"' : ' dir="ltr"').'><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><head>'.
'<body>'.\trim($sResult).'</body></html>';
}
/**
* @param string $sText
* @param bool $bLinksWithTargetBlank = true
*
* @return string
*/
public static function ConvertPlainToHtml($sText, $bLinksWithTargetBlank = true)
{
$sText = \trim($sText);
if (0 === \strlen($sText))
{
return '';
}
$sText = \MailSo\Base\LinkFinder::NewInstance()
->Text($sText)
->UseDefaultWrappers($bLinksWithTargetBlank)
// ->CompileText(true, false);
->CompileText(true, true);
$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), '&gt;');
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(
"\n" => "<br />",
"\t" => '&nbsp;&nbsp;&nbsp;',
' ' => '&nbsp;&nbsp;'
));
return $sText;
}
/**
* @param string $sText
*
* @return string
*/
public static function ConvertHtmlToPlain($sText)
{
$sText = trim(stripslashes($sText));
$sText = preg_replace('/[\s]+/', ' ', $sText);
$sText = preg_replace(array(
"/\r/",
"/[\n\t]+/",
'/<script[^>]*>.*?<\/script>/i',
'/<style[^>]*>.*?<\/style>/i',
'/<title[^>]*>.*?<\/title>/i',
'/<h[123][^>]*>(.+?)<\/h[123]>/i',
'/<h[456][^>]*>(.+?)<\/h[456]>/i',
'/<p[^>]*>/i',
'/<br[^>]*>/i',
'/<b[^>]*>(.+?)<\/b>/i',
'/<i[^>]*>(.+?)<\/i>/i',
'/(<ul[^>]*>|<\/ul>)/i',
'/(<ol[^>]*>|<\/ol>)/i',
'/<li[^>]*>/i',
'/<a[^>]*href="([^"]+)"[^>]*>(.+?)<\/a>/i',
'/<hr[^>]*>/i',
'/(<table[^>]*>|<\/table>)/i',
'/(<tr[^>]*>|<\/tr>)/i',
'/<td[^>]*>(.+?)<\/td>/i',
'/<th[^>]*>(.+?)<\/th>/i',
'/&nbsp;/i',
'/&quot;/i',
'/&gt;/i',
'/&lt;/i',
'/&amp;/i',
'/&copy;/i',
'/&trade;/i',
'/&#8220;/',
'/&#8221;/',
'/&#8211;/',
'/&#8217;/',
'/&#38;/',
'/&#169;/',
'/&#8482;/',
'/&#151;/',
'/&#147;/',
'/&#148;/',
'/&#149;/',
'/&reg;/i',
'/&bull;/i',
'/&[&;]+;/i',
'/&#39;/',
'/&#160;/'
), array(
'',
' ',
'',
'',
'',
"\n\n\\1\n\n",
"\n\n\\1\n\n",
"\n\n\t",
"\n",
'\\1',
'\\1',
"\n\n",
"\n\n",
"\n\t* ",
'\\2 (\\1)',
"\n------------------------------------\n",
"\n",
"\n",
"\t\\1\n",
"\t\\1\n",
' ',
'"',
'>',
'<',
'&',
'(c)',
'(tm)',
'"',
'"',
'-',
"'",
'&',
'(c)',
'(tm)',
'--',
'"',
'"',
'*',
'(R)',
'*',
'',
'\'',
''
), $sText);
$sText = str_ireplace('<div>',"\n<div>", $sText);
$sText = strip_tags($sText, '');
$sText = preg_replace("/\n\\s+\n/", "\n", $sText);
$sText = preg_replace("/[\n]{3,}/", "\n\n", $sText);
return trim($sText);
}
}

View file

@ -0,0 +1,583 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class Http
{
/**
* @var bool
*/
private $bIsMagicQuotesOn;
/**
* @access private
*/
private function __construct()
{
$this->bIsMagicQuotesOn = (bool) @\ini_get('magic_quotes_gpc');
}
/**
* @return \MailSo\Base\Http
*/
public static function NewInstance()
{
return new self();
}
/**
* @staticvar \MailSo\Base\Http $oInstance;
*
* @return \MailSo\Base\Http
*/
public static function SingletonInstance()
{
static $oInstance = null;
if (null === $oInstance)
{
$oInstance = self::NewInstance();
}
return $oInstance;
}
/**
* @param string $sKey
*
* @return bool
*/
public function HasQuery($sKey)
{
return isset($_GET[$sKey]);
}
/**
* @param string $sKey
* @param mixed $mDefault = null
* @param bool $bClearPercZeroZero = true
*
* @return mixed
*/
public function GetQuery($sKey, $mDefault = null, $bClearPercZeroZero = true)
{
return isset($_GET[$sKey]) ? \MailSo\Base\Utils::StripSlashesValue($_GET[$sKey], $bClearPercZeroZero) : $mDefault;
}
/**
* @return array|null
*/
public function GetQueryAsArray()
{
return isset($_GET) && \is_array($_GET) ? \MailSo\Base\Utils::StripSlashesValue($_GET, true) : null;
}
/**
* @param string $sKey
*
* @return bool
*/
public function HasPost($sKey)
{
return isset($_POST[$sKey]);
}
/**
* @param string $sKey
* @param mixed $mDefault = null
* @param bool $bClearPercZeroZero = false
*
* @return mixed
*/
public function GetPost($sKey, $mDefault = null, $bClearPercZeroZero = false)
{
return isset($_POST[$sKey]) ? \MailSo\Base\Utils::StripSlashesValue($_POST[$sKey], $bClearPercZeroZero) : $mDefault;
}
/**
* @return array|null
*/
public function GetPostAsArray()
{
return isset($_POST) && \is_array($_POST) ? \MailSo\Base\Utils::StripSlashesValue($_POST, false) : null;
}
/**
* @param string $sKey
*
* @return bool
*/
public function HasRequest($sKey)
{
return isset($_REQUEST[$sKey]);
}
/**
* @param string $sKey
* @param mixed $mDefault = null
*
* @return mixed
*/
public function GetRequest($sKey, $mDefault = null)
{
return isset($_REQUEST[$sKey]) ? \MailSo\Base\Utils::StripSlashesValue($_REQUEST[$sKey]) : $mDefault;
}
/**
* @param string $sKey
*
* @return bool
*/
public function HasServer($sKey)
{
return isset($_SERVER[$sKey]);
}
/**
* @param string $sKey
* @param mixed $mDefault = null
*
* @return mixed
*/
public function GetServer($sKey, $mDefault = null)
{
return isset($_SERVER[$sKey]) ? $_SERVER[$sKey] : $mDefault;
}
/**
* @param string $sKey
*
* @return bool
*/
public function HasEnv($sKey)
{
return isset($_ENV[$sKey]);
}
/**
* @param string $sKey
* @param mixed $mDefault = null
*
* @return mixed
*/
public function GetEnv($sKey, $mDefault = null)
{
return isset($_ENV[$sKey]) ? $_ENV[$sKey] : $mDefault;
}
/**
* @return string
*/
public function ServerProtocol()
{
return $this->GetServer('SERVER_PROTOCOL', 'HTTP/1.0');
}
/**
* @return string
*/
public function GetMethod()
{
return $this->GetServer('REQUEST_METHOD', '');
}
/**
* @return bool
*/
public function IsPost()
{
return ('POST' === $this->GetMethod());
}
/**
* @return bool
*/
public function IsGet()
{
return ('GET' === $this->GetMethod());
}
/**
* @return string
*/
public function GetQueryString()
{
return $this->GetServer('QUERY_STRING', '');
}
/**
* @return bool
*/
public function CheckLocalhost($sServer)
{
return \in_array(\strtolower(\trim($sServer)), array(
'localhost', '127.0.0.1', '::1', '::1/128', '0:0:0:0:0:0:0:1'
));
}
/**
* @return bool
*/
public function IsLocalhost()
{
return $this->CheckLocalhost($this->GetServer('REMOTE_ADDR', ''));
}
/**
* @return string
*/
public function GetRawBody()
{
static $sRawBody = null;
if (null === $sRawBody)
{
$sBody = @\file_get_contents('php://input');
$sRawBody = (false !== $sBody) ? $sBody : '';
}
return $sRawBody;
}
/**
* @param string $sHeader
*
* @return string
*/
public function GetHeader($sHeader)
{
$sResultHeader = '';
$sServerKey = 'HTTP_'.\strtoupper(\str_replace('-', '_', $sHeader));
$sResultHeader = $this->GetServer($sServerKey, '');
if (0 === \strlen($sResultHeader) &&
\MailSo\Base\Utils::FunctionExistsAndEnabled('apache_request_headers'))
{
$sHeaders = \apache_request_headers();
if (isset($sHeaders[$sHeader]))
{
$sResultHeader = $sHeaders[$sHeader];
}
}
return $sResultHeader;
}
/**
* @return string
*/
public function GetScheme()
{
return ('on' === \strtolower($this->GetServer('HTTPS'))) ? 'https' : 'http';
}
/**
* @return bool
*/
public function IsSecure()
{
return ('https' === $this->GetScheme());
}
/**
* @param bool $bWithRemoteUserData = false
* @param bool $bRemoveWWW = true
*
* @return string
*/
public function GetHost($bWithRemoteUserData = false, $bRemoveWWW = true)
{
$sHost = $this->GetServer('HTTP_HOST', '');
if (0 === \strlen($sHost))
{
$sScheme = $this->GetScheme();
$sName = $this->GetServer('SERVER_NAME');
$iPort = (int) $this->GetServer('SERVER_PORT');
$sHost = (('http' === $sScheme && 80 === $iPort) || ('https' === $sScheme && 443 === $iPort))
? $sName : $sName.':'.$iPort;
}
if ($bRemoveWWW)
{
$sHost = 'www.' === \substr(\strtolower($sHost), 0, 4) ? \substr($sHost, 0, 4) : $sHost;
}
if ($bWithRemoteUserData)
{
$sUser = \trim($this->HasServer('REMOTE_USER') ? $this->GetServer('REMOTE_USER', '') : '');
$sHost = (0 < \strlen($sUser) ? $sUser.'@' : '').$sHost;
}
return $sHost;
}
/**
* @param bool $bCheckProxy = true
*
* @return string
*/
public function GetClientIp($bCheckProxy = true)
{
$sIp = '';
if ($bCheckProxy && null !== $this->GetServer('HTTP_CLIENT_IP', null))
{
$sIp = $this->GetServer('HTTP_CLIENT_IP', '');
}
else if ($bCheckProxy && null !== $this->GetServer('HTTP_X_FORWARDED_FOR', null))
{
$sIp = $this->GetServer('HTTP_X_FORWARDED_FOR', '');
}
else
{
$sIp = $this->GetServer('REMOTE_ADDR', '');
}
return $sIp;
}
/**
* @param string $sUrl
* @param array $aPost = array()
* @param string $sCustomUserAgent = 'MaiSo Http User Agent (v1)'
* @param int $iCode = 0
* @param \MailSo\Log\Logger $oLogger = null
*
* @return string|bool
*/
public function SendPostRequest($sUrl, $aPost = array(), $sCustomUserAgent = 'MaiSo Http User Agent (v1)', &$iCode = 0, $oLogger = null)
{
$aOptions = array(
CURLOPT_URL => $sUrl,
CURLOPT_HEADER => false,
CURLOPT_FAILONERROR => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $aPost,
CURLOPT_TIMEOUT => 20
);
if (0 < \strlen($sCustomUserAgent))
{
$aOptions[CURLOPT_USERAGENT] = $sCustomUserAgent;
}
$oCurl = \curl_init();
\curl_setopt_array($oCurl, $aOptions);
if ($oLogger)
{
$oLogger->Write('cURL: Send post request: '.$sUrl);
}
$mResult = \curl_exec($oCurl);
$iCode = (int) \curl_getinfo($oCurl, CURLINFO_HTTP_CODE);
$sContentType = (string) \curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE);
if ($oLogger)
{
$oLogger->Write('cURL: Post request result: (Status: '.$iCode.', ContentType: '.$sContentType.')');
if (false === $mResult || 200 !== $iCode)
{
$oLogger->Write('cURL: Error: '.\curl_error($oCurl), \MailSo\Log\Enumerations\Type::WARNING);
}
}
if (\is_resource($oCurl))
{
\curl_close($oCurl);
}
return $mResult;
}
/**
* @param string $sUrl
* @param resource $rFile
* @param string $sCustomUserAgent = 'MaiSo Http User Agent (v1)'
* @param string $sContentType = ''
* @param int $iCode = 0
* @param \MailSo\Log\Logger $oLogger = null
*
* @return bool
*/
public function SaveUrlToFile($sUrl, $rFile, $sCustomUserAgent = 'MaiSo Http User Agent (v1)', &$sContentType = '', &$iCode = 0, $oLogger = null)
{
if (!is_resource($rFile))
{
if ($oLogger)
{
$oLogger->Write('cURL: input resource invalid.', \MailSo\Log\Enumerations\Type::WARNING);
}
return false;
}
$aOptions = array(
CURLOPT_URL => $sUrl,
CURLOPT_HEADER => false,
CURLOPT_FAILONERROR => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FILE => $rFile,
CURLOPT_TIMEOUT => 10
);
if (0 < \strlen($sCustomUserAgent))
{
$aOptions[CURLOPT_USERAGENT] = $sCustomUserAgent;
}
$oCurl = \curl_init();
\curl_setopt_array($oCurl, $aOptions);
if ($oLogger)
{
$oLogger->Write('cURL: Send request: '.$sUrl);
}
$bResult = \curl_exec($oCurl);
$iCode = (int) \curl_getinfo($oCurl, CURLINFO_HTTP_CODE);
$sContentType = (string) \curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE);
if ($oLogger)
{
$oLogger->Write('cURL: Request result: '.($bResult ? 'true' : 'false').' (Status: '.$iCode.', ContentType: '.$sContentType.')');
if (!$bResult || 200 !== $iCode)
{
$oLogger->Write('cURL: Error: '.\curl_error($oCurl), \MailSo\Log\Enumerations\Type::WARNING);
}
}
if (\is_resource($oCurl))
{
\curl_close($oCurl);
}
return $bResult;
}
/**
* @param string $sUrl
* @param string $sCustomUserAgent = 'MaiSo Http User Agent (v1)'
* @param string $sContentType = ''
* @param int $iCode = 0
* @param \MailSo\Log\Logger $oLogger = null
*
* @return string|bool
*/
public function GetUrlAsString($sUrl, $sCustomUserAgent = 'MaiSo Http User Agent (v1)', &$sContentType = '', &$iCode = 0, $oLogger = null)
{
$rMemFile = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
if ($this->SaveUrlToFile($sUrl, $rMemFile, $sCustomUserAgent, $sContentType, $iCode, $oLogger) && \is_resource($rMemFile))
{
\rewind($rMemFile);
return \stream_get_contents($rMemFile);
}
return false;
}
/**
* @param int $iExpireTime
* @param bool $bSetCacheHeader = true
* @param string $sEtag = ''
*
* @return bool
*/
public function ServerNotModifiedCache($iExpireTime, $bSetCacheHeader = true, $sEtag = '')
{
$bResult = false;
if (0 < $iExpireTime)
{
$iUtcTimeStamp = \time();
$sIfModifiedSince = $this->GetHeader('If-Modified-Since', '');
if (0 === \strlen($sIfModifiedSince))
{
if ($bSetCacheHeader)
{
\header('Cache-Control: public', true);
\header('Pragma: public', true);
\header('Last-Modified: '.\gmdate('D, d M Y H:i:s', $iUtcTimeStamp - $iExpireTime).' UTC', true);
\header('Expires: '.\gmdate('D, j M Y H:i:s', $iUtcTimeStamp + $iExpireTime).' UTC', true);
if (0 < strlen($sEtag))
{
\header('Etag: '.$sEtag, true);
}
}
}
else
{
$this->StatusHeader(304);
$bResult = true;
}
}
return $bResult;
}
/**
* @param int $iStatus
*
* @return void
*/
public function StatusHeader($iStatus, $sCustomStatusText = '')
{
switch ($iStatus)
{
default:
\header('Status: '.$iStatus, true, $iStatus);
break;
case 304:
\header($this->ServerProtocol().' 304 '.(0 === \strlen($sCustomStatusText) ? 'Not Modified' : $sCustomStatusText), true, $iStatus);
break;
case 200:
\header($this->ServerProtocol().' 200 '.(0 === \strlen($sCustomStatusText) ? 'OK' : $sCustomStatusText), true, $iStatus);
break;
case 401:
\header($this->ServerProtocol().' 401 '.(0 === \strlen($sCustomStatusText) ? 'Please sign in' : $sCustomStatusText), true, $iStatus);
break;
case 404:
\header($this->ServerProtocol().' 404 '.(0 === \strlen($sCustomStatusText) ? 'Not Found' : $sCustomStatusText), true, $iStatus);
break;
}
}
/**
* @return string
*/
public function GetPath()
{
$sUrl = \ltrim(\substr($this->GetServer('SCRIPT_NAME', ''), 0, \strrpos($this->GetServer('SCRIPT_NAME', ''), '/')), '/');
return '' === $sUrl ? '/' : '/'.$sUrl.'/';
}
/**
* @return string
*/
public function GetUrl()
{
return '/'.$this->GetServer('REQUEST_URI', '');
}
/**
* @return string
*/
public function GetFullUrl()
{
return $this->GetScheme().'://'.$this->GetHost(true, false).$this->GetPath();
}
/**
* @return string
*/
public function GetFullUrlWithQuery()
{
return $this->GetScheme().'://'.$this->GetHost(true, false).$this->GetUrl();
}
}

View file

@ -0,0 +1,323 @@
<?php
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;
/**
* @access private
*/
private 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->Clear();
}
/**
* @return \MailSo\Base\LinkFinder
*/
public static function NewInstance()
{
return new self();
}
/**
* @return \MailSo\Base\LinkFinder
*/
public function Clear()
{
$this->aPrepearPlainStringUrls = array();
$this->fLinkWrapper = null;
$this->fMailWrapper = null;
$this->sText = '';
return $this;
}
/**
* @param string $sText
*
* @return \MailSo\Base\LinkFinder
*/
public function Text($sText)
{
$this->sText = $sText;
return $this;
}
/**
* @param mixed $fLinkWrapper
*
* @return \MailSo\Base\LinkFinder
*/
public function LinkWrapper($fLinkWrapper)
{
$this->fLinkWrapper = $fLinkWrapper;
return $this;
}
/**
* @param mixed $fMailWrapper
*
* @return \MailSo\Base\LinkFinder
*/
public function MailWrapper($fMailWrapper)
{
$this->fMailWrapper = $fMailWrapper;
return $this;
}
/**
* @param bool $bAddTargetBlank = false
*
* @return \MailSo\Base\LinkFinder
*/
public function UseDefaultWrappers($bAddTargetBlank = false)
{
$this->fLinkWrapper = function ($sLink, $bShortLink = false) use ($bAddTargetBlank) {
if ($bShortLink && \in_array(\strtolower($sLink), array('asp.net', 'vb.net', 'mailbee.net')))
{
return $sLink;
}
$sNameLink = $sLink;
if (!\preg_match('/^[a-z]{3,5}\:\/\//i', \ltrim($sLink)))
{
$sLink = 'http://'.\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;
}
/**
* @param bool $bUseHtmlSpecialChars = true
* @param bool $bFindShortLinks = true
*
* @return string
*/
public function CompileText($bUseHtmlSpecialChars = true, $bFindShortLinks = true)
{
$sText = $this->sText;
$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);
}
if ($bFindShortLinks && null !== $this->fLinkWrapper && \is_callable($this->fLinkWrapper))
{
$sText = $this->findShortLinks($sText, $this->fLinkWrapper);
}
if ($bUseHtmlSpecialChars)
{
$sText = @\htmlentities($sText, $this->iHtmlSpecialCharsFlags, 'UTF-8');
}
if (0 < \count($this->aPrepearPlainStringUrls))
{
for ($iIndex = 0, $iLen = \count($this->aPrepearPlainStringUrls); $iIndex < $iLen; $iIndex++)
{
$sText = \str_replace(\MailSo\Base\LinkFinder::OPEN_LINK.$iIndex.
\MailSo\Base\LinkFinder::CLOSE_LINK, $this->aPrepearPlainStringUrls[$iIndex], $sText);
}
$this->aPrepearPlainStringUrls = array();
}
return $sText;
}
/**
* @param string $sText
* @param mixed $fWrapper
*
* @return string
*/
private function findLinks($sText, $fWrapper)
{
$sPattern = '/([\W]|^)((?:https?:\/\/)|(?:svn:\/\/)|(?:git:\/\/)|(?:s?ftps?:\/\/)|(?:www\.))'.
'((\S+?)(\\/)?)((?:&gt;)?|[^\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 = \call_user_func($fWrapper, $aMatch[2].$aMatch[3]);
if (\is_string($sLinkWithWrap) && 0 < \strlen($sLinkWithWrap))
{
$aPrepearPlainStringUrls[] = \stripslashes($sLinkWithWrap);
return $aMatch[1].
\MailSo\Base\LinkFinder::OPEN_LINK.
(\count($aPrepearPlainStringUrls) - 1).
\MailSo\Base\LinkFinder::CLOSE_LINK.
$aMatch[6];
}
return $aMatch[0];
}
return '';
}, $sText);
if (0 < \count($aPrepearPlainStringUrls))
{
$this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls;
}
return $sText;
}
/**
* @param string $sText
* @param mixed $fWrapper
*
* @return string
*/
private function findShortLinks($sText, $fWrapper)
{
$sPattern = '/([a-z0-9-\.]+\.(?:com|org|net|ru))([^a-z0-9-\.])/i';
$aPrepearPlainStringUrls = $this->aPrepearPlainStringUrls;
$sText = \preg_replace_callback($sPattern, function ($aMatch) use ($fWrapper, &$aPrepearPlainStringUrls) {
if (\is_array($aMatch) && 2 < \count($aMatch) && isset($aMatch[1]) && 0 < \strlen($aMatch[1]))
{
$sLinkWithWrap = \call_user_func_array($fWrapper, array($aMatch[1], true));
if (\is_string($sLinkWithWrap))
{
$aPrepearPlainStringUrls[] = \stripslashes($sLinkWithWrap);
return \MailSo\Base\LinkFinder::OPEN_LINK.
(\count($aPrepearPlainStringUrls) - 1).
\MailSo\Base\LinkFinder::CLOSE_LINK.
$aMatch[2];
}
return $aMatch[0];
}
return '';
}, $sText);
if (0 < \count($aPrepearPlainStringUrls))
{
$this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls;
}
return $sText;
}
/**
* @param string $sText
* @param mixed $fWrapper
*
* @return string
*/
private function findMails($sText, $fWrapper)
{
$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 = \call_user_func($fWrapper, $aMatch[1]);
if (\is_string($sMailWithWrap) && 0 < \strlen($sMailWithWrap))
{
$aPrepearPlainStringUrls[] = \stripslashes($sMailWithWrap);
return \MailSo\Base\LinkFinder::OPEN_LINK.
(\count($aPrepearPlainStringUrls) - 1).
\MailSo\Base\LinkFinder::CLOSE_LINK;
}
return $aMatch[1];
}
return '';
}, $sText);
if (0 < \count($aPrepearPlainStringUrls))
{
$this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls;
}
return $sText;
}
}

View file

@ -0,0 +1,112 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class Loader
{
/**
* @var bool
*/
public static $StoreStatistic = true;
/**
* @var array
*/
private static $aIncStatistic = array();
/**
* @var array
*/
private static $aSetStatistic = array();
/**
* @staticvar bool $bIsInited
*
* @return void
*/
public static function Init()
{
static $bIsInited = false;
if (!$bIsInited)
{
$bIsInited = true;
self::SetStatistic('Inited', \microtime(true));
}
}
/**
* @param string $sName
* @param int $iIncSize = 1
*
* @return void
*/
public static function IncStatistic($sName, $iIncSize = 1)
{
if (self::$StoreStatistic)
{
self::$aIncStatistic[$sName] = isset(self::$aIncStatistic[$sName])
? self::$aIncStatistic[$sName] + $iIncSize : $iIncSize;
}
}
/**
* @param string $sName
* @param mixed $mValue
*
* @return void
*/
public static function SetStatistic($sName, $mValue)
{
if (self::$StoreStatistic)
{
self::$aSetStatistic[$sName] = $mValue;
}
}
/**
* @param string $sName
*
* @return mixed
*/
public static function GetStatistic($sName)
{
return self::$StoreStatistic && isset(self::$aSetStatistic[$sName]) ? self::$aSetStatistic[$sName] : null;
}
/**
* @return array|null
*/
public static function Statistic()
{
$aResult = null;
if (self::$StoreStatistic)
{
$aResult = array(
'php' => array(
'phpversion' => \phpversion(),
'ssl' => (int) \function_exists('openssl_open'),
'iconv' => (int) \function_exists('iconv')
));
if (\MailSo\Base\Utils::FunctionExistsAndEnabled('memory_get_usage') &&
\MailSo\Base\Utils::FunctionExistsAndEnabled('memory_get_peak_usage'))
{
$aResult['php']['memory_get_usage'] =
Utils::FormatFileSize(\memory_get_usage(true), 2);
$aResult['php']['memory_get_peak_usage'] =
Utils::FormatFileSize(\memory_get_peak_usage(true), 2);
}
self::SetStatistic('TimeDelta', \microtime(true) - self::GetStatistic('Inited'));
$aResult['statistic'] = self::$aSetStatistic;
$aResult['counts'] = self::$aIncStatistic;
}
return $aResult;
}
}

View file

@ -0,0 +1,116 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class ResourceRegistry
{
/**
* @var array
*/
public static $Resources = array();
/**
* @access private
*/
private function __construct()
{
}
/**
* @staticvar bool $bInited
*
* @return void
*/
private static function regResourcesShutdownFunc()
{
static $bInited = false;
if (!$bInited)
{
$bInited = true;
\register_shutdown_function(function () {
if (\is_array(\MailSo\Base\ResourceRegistry::$Resources))
{
foreach (\array_keys(\MailSo\Base\ResourceRegistry::$Resources) as $sKey)
{
if (\is_resource(\MailSo\Base\ResourceRegistry::$Resources[$sKey]))
{
\MailSo\Base\Loader::IncStatistic('CloseMemoryResource');
\fclose(\MailSo\Base\ResourceRegistry::$Resources[$sKey]);
}
\MailSo\Base\ResourceRegistry::$Resources[$sKey] = null;
}
}
\MailSo\Base\ResourceRegistry::$Resources = array();
});
}
}
/**
* @param int $iMemoryMaxInMb = 5
*
* @return resource | bool
*/
public static function CreateMemoryResource($iMemoryMaxInMb = 5)
{
self::regResourcesShutdownFunc();
$oResult = @\fopen('php://temp/maxmemory:'.($iMemoryMaxInMb * 1024 * 1024), 'r+b');
if (\is_resource($oResult))
{
\MailSo\Base\Loader::IncStatistic('CreateMemoryResource');
\MailSo\Base\ResourceRegistry::$Resources[(string) $oResult] = $oResult;
return $oResult;
}
return false;
}
/**
* @param string $sString
*
* @return resource | bool
*/
public static function CreateMemoryResourceFromString($sString)
{
$oResult = self::CreateMemoryResource();
if (\is_resource($oResult))
{
\fwrite($oResult, $sString);
\rewind($oResult);
}
return $oResult;
}
/**
* @param resource $rResource
*
* @return void
*/
public static function CloseMemoryResource(&$rResource)
{
if (\is_resource($rResource))
{
$sKey = (string) $rResource;
if (isset(\MailSo\Base\ResourceRegistry::$Resources[$sKey]))
{
\fclose(\MailSo\Base\ResourceRegistry::$Resources[$sKey]);
\MailSo\Base\ResourceRegistry::$Resources[$sKey] = null;
unset(\MailSo\Base\ResourceRegistry::$Resources[$sKey]);
\MailSo\Base\Loader::IncStatistic('CloseMemoryResource');
}
if (\is_resource($rResource))
{
\fclose($rResource);
}
$rResource = null;
}
}
}

View file

@ -0,0 +1,368 @@
<?php
namespace MailSo\Base\StreamWrappers;
/**
* @category MailSo
* @package Base
* @subpackage StreamWrappers
*/
class Binary
{
/**
* @var string
*/
const STREAM_NAME = 'mailsobinary';
/**
* @var array
*/
private static $aStreams = array();
/**
* @var resource
*/
private $rStream;
/**
* @var string
*/
private $sFromEncoding;
/**
* @var string
*/
private $sToEncoding;
/**
* @var string
*/
private $sFunctionName;
/**
* @var int
*/
private $iPos;
/**
* @var string
*/
private $sBuffer;
/**
* @var string
*/
private $sReadEndBuffer;
/**
* @param string $sContentTransferEncoding
* @param bool $bDecode = true
*
* @return string
*/
public static function GetInlineDecodeOrEncodeFunctionName($sContentTransferEncoding, $bDecode = true)
{
$sFunctionName = '';
switch (strtolower($sContentTransferEncoding))
{
case \MailSo\Base\Enumerations\Encoding::BASE64_LOWER:
// InlineBase64Decode
$sFunctionName = $bDecode ? 'InlineBase64Decode' : 'convert.base64-encode';
break;
case \MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE_LOWER:
// InlineQuotedPrintableDecode
$sFunctionName = $bDecode ? 'convert.quoted-printable-decode' : 'convert.quoted-printable-encode';
break;
}
return $sFunctionName;
}
/**
* @param string $sBodyString
* @param string $sEndBuffer
*
* @return string
*/
public static function InlineNullDecode($sBodyString, &$sEndBuffer)
{
$sEndBuffer = '';
return $sBodyString;
}
/**
* @param string $sBaseString
* @param string $sEndBuffer
*
* @return string
*/
public static function InlineBase64Decode($sBaseString, &$sEndBuffer)
{
$sEndBuffer = '';
$sBaseString = str_replace(array("\r", "\n", "\t"), '', $sBaseString);
$iBaseStringLen = strlen($sBaseString);
$iBaseStringNormFloorLen = floor($iBaseStringLen / 4) * 4;
if ($iBaseStringNormFloorLen < $iBaseStringLen)
{
$sEndBuffer = substr($sBaseString, $iBaseStringNormFloorLen);
$sBaseString = substr($sBaseString, 0, $iBaseStringNormFloorLen);
}
return \MailSo\Base\Utils::Base64Decode($sBaseString);
}
/**
* @param string $sQuotedPrintableString
* @param string $sEndBuffer
*
* @return string
*/
public static function InlineQuotedPrintableDecode($sQuotedPrintableString, &$sEndBuffer)
{
$sEndBuffer = '';
$sQuotedPrintableLen = strlen($sQuotedPrintableString);
$iLastSpace = strrpos($sQuotedPrintableString, ' ');
if (false !== $iLastSpace && $iLastSpace + 1 < $sQuotedPrintableLen)
{
$sEndBuffer = substr($sQuotedPrintableString, $iLastSpace + 1);
$sQuotedPrintableString = substr($sQuotedPrintableString, 0, $iLastSpace + 1);
}
return quoted_printable_decode($sQuotedPrintableString);
}
/**
* @param string $sEncodedString
* @param string $sEndBuffer
*
* @return string
*/
public static function InlineConvertDecode($sEncodedString, &$sEndBuffer, $sFromEncoding, $sToEncoding)
{
$sEndBuffer = '';
$sQuotedPrintableLen = strlen($sEncodedString);
$iLastSpace = strrpos($sEncodedString, ' ');
if (false !== $iLastSpace && $iLastSpace + 1 < $sQuotedPrintableLen)
{
$sEndBuffer = substr($sEncodedString, $iLastSpace + 1);
$sEncodedString = substr($sEncodedString, 0, $iLastSpace + 1);
}
return \MailSo\Base\Utils::ConvertEncoding($sEncodedString, $sFromEncoding, $sToEncoding);
}
/**
* @param resource $rStream
* @param string $sUtilsDecodeOrEncodeFunctionName = null
* @param string $sFromEncoding = null
* @param string $sToEncoding = null
*
* @return resource|bool
*/
public static function CreateStream($rStream,
$sUtilsDecodeOrEncodeFunctionName = null, $sFromEncoding = null, $sToEncoding = null)
{
if (!in_array(self::STREAM_NAME, stream_get_wrappers()))
{
stream_wrapper_register(self::STREAM_NAME, '\MailSo\Base\StreamWrappers\Binary');
}
if (null === $sUtilsDecodeOrEncodeFunctionName || 0 === strlen($sUtilsDecodeOrEncodeFunctionName))
{
$sUtilsDecodeOrEncodeFunctionName = 'InlineNullDecode';
}
$sHashName = md5(microtime(true).rand(1000, 9999));
if (null !== $sFromEncoding && null !== $sToEncoding && $sFromEncoding !== $sToEncoding)
{
$rStream = self::CreateStream($rStream, $sUtilsDecodeOrEncodeFunctionName);
$sUtilsDecodeOrEncodeFunctionName = 'InlineConvertDecode';
}
if (in_array($sUtilsDecodeOrEncodeFunctionName, array(
'convert.base64-decode', 'convert.base64-encode',
'convert.quoted-printable-decode', 'convert.quoted-printable-encode'
)))
{
$rFilter = \stream_filter_append($rStream, $sUtilsDecodeOrEncodeFunctionName,
STREAM_FILTER_READ, array(
'line-length' => \MailSo\Mime\Enumerations\Constants::LINE_LENGTH,
'line-break-chars' => \MailSo\Mime\Enumerations\Constants::CRLF
));
return \is_resource($rFilter) ? $rStream : false;
}
self::$aStreams[$sHashName] =
array($rStream, $sUtilsDecodeOrEncodeFunctionName, $sFromEncoding, $sToEncoding);
\MailSo\Base\Loader::IncStatistic('CreateStream/Binary');
return \fopen(self::STREAM_NAME.'://'.$sHashName, 'rb');
}
/**
* @param string $sPath
*
* @return bool
*/
public function stream_open($sPath)
{
$this->iPos = 0;
$this->sBuffer = '';
$this->sReadEndBuffer = '';
$this->rStream = false;
$this->sFromEncoding = null;
$this->sToEncoding = null;
$this->sFunctionName = null;
$bResult = false;
$aPath = parse_url($sPath);
if (isset($aPath['host']) && isset($aPath['scheme']) &&
0 < strlen($aPath['host']) && 0 < strlen($aPath['scheme']) &&
self::STREAM_NAME === $aPath['scheme'])
{
$sHashName = $aPath['host'];
if (isset(self::$aStreams[$sHashName]) &&
is_array(self::$aStreams[$sHashName]) &&
4 === count(self::$aStreams[$sHashName]))
{
$this->rStream = self::$aStreams[$sHashName][0];
$this->sFunctionName = self::$aStreams[$sHashName][1];
$this->sFromEncoding = self::$aStreams[$sHashName][2];
$this->sToEncoding = self::$aStreams[$sHashName][3];
}
$bResult = is_resource($this->rStream);
}
return $bResult;
}
/**
* @param int $iCount
*
* @return string
*/
public function stream_read($iCount)
{
$sReturn = '';
$sFunctionName = $this->sFunctionName;
if ($iCount > 0)
{
if ($iCount < strlen($this->sBuffer))
{
$sReturn = substr($this->sBuffer, 0, $iCount);
$this->sBuffer = substr($this->sBuffer, $iCount);
}
else
{
$sReturn = $this->sBuffer;
while ($iCount > 0)
{
if (feof($this->rStream))
{
if (0 === strlen($this->sBuffer.$sReturn))
{
return false;
}
if (0 < strlen($this->sReadEndBuffer))
{
$sReturn .= self::$sFunctionName($this->sReadEndBuffer,
$this->sReadEndBuffer, $this->sFromEncoding, $this->sToEncoding);
$iDecodeLen = strlen($sReturn);
}
$iCount = 0;
$this->sBuffer = '';
}
else
{
$sReadResult = fread($this->rStream, 8192);
if (false === $sReadResult)
{
return false;
}
$sReturn .= self::$sFunctionName($this->sReadEndBuffer.$sReadResult,
$this->sReadEndBuffer, $this->sFromEncoding, $this->sToEncoding);
$iDecodeLen = strlen($sReturn);
if ($iCount < $iDecodeLen)
{
$this->sBuffer = substr($sReturn, $iCount);
$sReturn = substr($sReturn, 0, $iCount);
$iCount = 0;
}
else
{
$iCount -= $iDecodeLen;
}
}
}
}
$this->iPos += strlen($sReturn);
return $sReturn;
}
return false;
}
/**
* @return int
*/
public function stream_write()
{
return 0;
}
/**
* @return int
*/
public function stream_tell()
{
return $this->iPos;
}
/**
* @return bool
*/
public function stream_eof()
{
return 0 === strlen($this->sBuffer) && feof($this->rStream);
}
/**
*
* @return array
*/
public function stream_stat()
{
return array(
'dev' => 2,
'ino' => 0,
'mode' => 33206,
'nlink' => 1,
'uid' => 0,
'gid' => 0,
'rdev' => 2,
'size' => 0,
'atime' => 1061067181,
'mtime' => 1056136526,
'ctime' => 1056136526,
'blksize' => -1,
'blocks' => -1
);
}
/**
* @return bool
*/
public function stream_seek()
{
return false;
}
}

View file

@ -0,0 +1,185 @@
<?php
namespace MailSo\Base\StreamWrappers;
/**
* @category MailSo
* @package Base
* @subpackage StreamWrappers
*/
class Literal
{
/**
* @var string
*/
const STREAM_NAME = 'mailsoliteral';
/**
* @var array
*/
private static $aStreams = array();
/**
* @var resource
*/
private $rStream;
/**
* @var int
*/
private $iSize;
/**
* @var int
*/
private $iPos;
/**
* @param resource $rStream
* @param int $iLiteralLen
*
* @return resource|bool
*/
public static function CreateStream($rStream, $iLiteralLen)
{
if (!in_array(self::STREAM_NAME, stream_get_wrappers()))
{
stream_wrapper_register(self::STREAM_NAME, '\MailSo\Base\StreamWrappers\Literal');
}
$sHashName = md5(microtime(true).rand(1000, 9999));
self::$aStreams[$sHashName] = array($rStream, $iLiteralLen);
\MailSo\Base\Loader::IncStatistic('CreateStream/Literal');
return fopen(self::STREAM_NAME.'://'.$sHashName, 'rb');
}
/**
* @param string $sPath
*
* @return bool
*/
public function stream_open($sPath)
{
$this->iPos = 0;
$this->iSize = 0;
$this->rStream = false;
$bResult = false;
$aPath = parse_url($sPath);
if (isset($aPath['host']) && isset($aPath['scheme']) &&
0 < strlen($aPath['host']) && 0 < strlen($aPath['scheme']) &&
self::STREAM_NAME === $aPath['scheme'])
{
$sHashName = $aPath['host'];
if (isset(self::$aStreams[$sHashName]) &&
is_array(self::$aStreams[$sHashName]) &&
2 === count(self::$aStreams[$sHashName]))
{
$this->rStream = self::$aStreams[$sHashName][0];
$this->iSize = self::$aStreams[$sHashName][1];
}
$bResult = is_resource($this->rStream);
}
return $bResult;
}
/**
* @param int $iCount
*
* @return string
*/
public function stream_read($iCount)
{
$sResult = false;
if ($this->iSize < $this->iPos + $iCount)
{
$iCount = $this->iSize - $this->iPos;
}
if ($iCount > 0)
{
$sReadResult = '';
$iRead = $iCount;
while (0 < $iRead)
{
$sAddRead = @fread($this->rStream, $iRead);
if (false === $sAddRead)
{
$sReadResult = false;
break;
}
$sReadResult .= $sAddRead;
$iRead -= strlen($sAddRead);
$this->iPos += strlen($sAddRead);
}
if (false !== $sReadResult)
{
$sResult = $sReadResult;
}
}
return $sResult;
}
/**
* @return int
*/
public function stream_write()
{
return 0;
}
/**
* @return int
*/
public function stream_tell()
{
return $this->iPos;
}
/**
* @return bool
*/
public function stream_eof()
{
return $this->iPos >= $this->iSize;
}
/**
* @return array
*/
public function stream_stat()
{
return array(
'dev' => 2,
'ino' => 0,
'mode' => 33206,
'nlink' => 1,
'uid' => 0,
'gid' => 0,
'rdev' => 2,
'size' => $this->iSize,
'atime' => 1061067181,
'mtime' => 1056136526,
'ctime' => 1056136526,
'blksize' => -1,
'blocks' => -1
);
}
/**
* @return bool
*/
public function stream_seek()
{
return false;
}
}

View file

@ -0,0 +1,257 @@
<?php
namespace MailSo\Base\StreamWrappers;
/**
* @category MailSo
* @package Base
* @subpackage StreamWrappers
*/
class SubStreams
{
/**
* @var string
*/
const STREAM_NAME = 'mailsosubstreams';
/**
* @var array
*/
private static $aStreams = array();
/**
* @var array
*/
private $aSubStreams;
/**
* @var int
*/
private $iIndex;
/**
* @var string
*/
private $sBuffer;
/**
* @var bool
*/
private $bIsEnd;
/**
* @var int
*/
private $iPos;
/**
* @param array $aSubStreams
*
* @return resource|bool
*/
public static function CreateStream($aSubStreams)
{
if (!in_array(self::STREAM_NAME, stream_get_wrappers()))
{
stream_wrapper_register(self::STREAM_NAME, '\MailSo\Base\StreamWrappers\SubStreams');
}
$sHashName = md5(microtime(true).rand(1000, 9999));
self::$aStreams[$sHashName] = $aSubStreams;
\MailSo\Base\Loader::IncStatistic('CreateStream/SubStreams');
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;
}
/**
* @param string $sPath
*
* @return bool
*/
public function stream_open($sPath)
{
$this->aSubStreams = array();
$bResult = false;
$aPath = parse_url($sPath);
if (isset($aPath['host']) && isset($aPath['scheme']) &&
0 < strlen($aPath['host']) && 0 < strlen($aPath['scheme']) &&
self::STREAM_NAME === $aPath['scheme'])
{
$sHashName = $aPath['host'];
if (isset(self::$aStreams[$sHashName]) &&
is_array(self::$aStreams[$sHashName]) &&
0 < count(self::$aStreams[$sHashName]))
{
$this->iIndex = 0;
$this->iPos = 0;
$this->bIsEnd = false;
$this->sBuffer = '';
$this->aSubStreams = self::$aStreams[$sHashName];
}
$bResult = 0 < count($this->aSubStreams);
}
return $bResult;
}
/**
* @param int $iCount
*
* @return string
*/
public function stream_read($iCount)
{
$sReturn = '';
$mCurrentPart = null;
if ($iCount > 0)
{
if ($iCount < strlen($this->sBuffer))
{
$sReturn = substr($this->sBuffer, 0, $iCount);
$this->sBuffer = substr($this->sBuffer, $iCount);
}
else
{
$sReturn = $this->sBuffer;
while ($iCount > 0)
{
$mCurrentPart =& $this->getPart();
if (null === $mCurrentPart)
{
$this->bIsEnd = true;
$this->sBuffer = '';
$iCount = 0;
break;
}
if (is_resource($mCurrentPart))
{
if (!feof($mCurrentPart))
{
$sReadResult = fread($mCurrentPart, 8192);
if (false === $sReadResult)
{
return false;
}
$sReturn .= $sReadResult;
$iLen = strlen($sReturn);
if ($iCount < $iLen)
{
$this->sBuffer = substr($sReturn, $iCount);
$sReturn = substr($sReturn, 0, $iCount);
$iCount = 0;
}
else
{
$iCount -= $iLen;
}
}
else
{
$this->iIndex++;
}
}
else if (is_string($mCurrentPart))
{
$sReadResult = substr($mCurrentPart, 0, $iCount);
$sReturn .= $sReadResult;
$iLen = strlen($sReadResult);
if ($iCount < $iLen)
{
$this->sBuffer = substr($sReturn, $iCount);
$sReturn = substr($sReturn, 0, $iCount);
$iCount = 0;
}
else
{
$iCount -= $iLen;
}
$this->iIndex++;
}
}
}
$this->iPos += strlen($sReturn);
return $sReturn;
}
return false;
}
/**
* @return int
*/
public function stream_write()
{
return 0;
}
/**
* @return int
*/
public function stream_tell()
{
return $this->iPos;
}
/**
* @return bool
*/
public function stream_eof()
{
return $this->bIsEnd;
}
/**
* @return array
*/
public function stream_stat()
{
return array(
'dev' => 2,
'ino' => 0,
'mode' => 33206,
'nlink' => 1,
'uid' => 0,
'gid' => 0,
'rdev' => 2,
'size' => 0,
'atime' => 1061067181,
'mtime' => 1056136526,
'ctime' => 1056136526,
'blksize' => -1,
'blocks' => -1
);
}
/**
* @return bool
*/
public function stream_seek()
{
return false;
}
}

View file

@ -0,0 +1,129 @@
<?php
namespace MailSo\Base\StreamWrappers;
/**
* @category MailSo
* @package Base
* @subpackage StreamWrappers
*/
class Test
{
/**
* @var string
*/
const STREAM_NAME = 'mailsotest';
/**
* @var array
*/
private static $aStreams = array();
/**
* @var resource
*/
private $rReadSream;
/**
* @param string $sRawResponse
*
* @return resource|bool
*/
public static function CreateStream($sRawResponse)
{
if (!in_array(self::STREAM_NAME, stream_get_wrappers()))
{
stream_wrapper_register(self::STREAM_NAME, '\MailSo\Base\StreamWrappers\Test');
}
$sHashName = md5(microtime(true).rand(1000, 9999));
$rConnect = fopen('php://memory', 'r+b');
fwrite($rConnect, $sRawResponse);
fseek($rConnect, 0);
self::$aStreams[$sHashName] = $rConnect;
\MailSo\Base\Loader::IncStatistic('CreateStream/Test');
return fopen(self::STREAM_NAME.'://'.$sHashName, 'r+b');
}
/**
* @param string $sPath
*
* @return bool
*/
public function stream_open($sPath)
{
$bResult = false;
$aPath = parse_url($sPath);
if (isset($aPath['host']) && isset($aPath['scheme']) &&
0 < strlen($aPath['host']) && 0 < strlen($aPath['scheme']) &&
self::STREAM_NAME === $aPath['scheme'])
{
$sHashName = $aPath['host'];
if (isset(self::$aStreams[$sHashName]) &&
is_resource(self::$aStreams[$sHashName]))
{
$this->rReadSream = self::$aStreams[$sHashName];
$bResult = true;
}
}
return $bResult;
}
/**
* @param int $iCount
*
* @return string
*/
public function stream_read($iCount)
{
return fread($this->rReadSream, $iCount);
}
/**
* @param string $sInputString
*
* @return int
*/
public function stream_write($sInputString)
{
return strlen($sInputString);
}
/**
* @return int
*/
public function stream_tell()
{
return ftell($this->rReadSream);
}
/**
* @return bool
*/
public function stream_eof()
{
return feof($this->rReadSream);
}
/**
* @return array
*/
public function stream_stat()
{
return fstat($this->rReadSream);
}
/**
* @return bool
*/
public function stream_seek()
{
return false;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,95 @@
<?php
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class Validator
{
/**
* @param string $sEmail
*
* @return bool
*/
public static function EmailString($sEmail)
{
$bResult = false;
if (self::NotEmptyString($sEmail))
{
$bResult = (bool) \preg_match('/^[a-zA-Z0-9][a-zA-Z0-9\.\+\-_]*@[a-zA-Z0-9][a-zA-Z0-9\.\+\-_]*$/', $sEmail);
}
return $bResult;
}
/**
* @param string $sString
* @param bool $bTrim = false
*
* @return bool
*/
public static function NotEmptyString($sString, $bTrim = false)
{
$bResult = false;
if (\is_string($sString))
{
if ($bTrim)
{
$sString = \trim($sString);
}
$bResult = 0 < \strlen($sString);
}
return $bResult;
}
/**
* @param array $aList
*
* @return bool
*/
public static function NotEmptyArray($aList)
{
return \is_array($aList) && 0 < \count($aList);
}
/**
* @param int $iNumber
* @param int $iMin = null
* @param int $iMax = null
*
* @return bool
*/
public static function RangeInt($iNumber, $iMin = null, $iMax = null)
{
$bResult = false;
if (\is_int($iNumber))
{
$bResult = true;
if ($bResult && null !== $iMin)
{
$bResult = $iNumber >= $iMin;
}
if ($bResult && null !== $iMax)
{
$bResult = $iNumber <= $iMax;
}
}
return $bResult;
}
/**
* @param int $iPort
*
* @return bool
*/
public static function PortInt($iPort)
{
return self::RangeInt($iPort, 0, 65535);
}
}

View file

@ -0,0 +1,149 @@
<?php
namespace MailSo\Cache;
/**
* @category MailSo
* @package Cache
*/
class CacheClient
{
/**
* @var \MailSo\Cache\DriverInterface
*/
private $oDriver;
/**
* @var string
*/
private $sCacheIndex;
/**
* @access private
*/
private function __construct()
{
$this->oDriver = null;
$this->sCacheIndex = '';
}
/**
* @return \MailSo\Cache\CacheClient
*/
public static function NewInstance()
{
return new self();
}
/**
* @param string $sKey
* @param string $sValue
*
* @return bool
*/
public function Set($sKey, $sValue)
{
return $this->oDriver ? $this->oDriver->Set($sKey.$this->sCacheIndex, $sValue) : false;
}
/**
* @param string $sKey
*
* @return bool
*/
public function SetTimer($sKey)
{
return $this->Set($sKey.'/TIMER', time());
}
/**
* @param string $sKey
*
* @return string
*/
public function Get($sKey)
{
$sValue = '';
if ($this->oDriver)
{
$sValue = $this->oDriver->Get($sKey.$this->sCacheIndex);
}
return $sValue;
}
/**
* @param string $sKey
*
* @return int
*/
public function GetTimer($sKey)
{
$iTimer = 0;
$sValue = $this->Get($sKey.'/TIMER');
if (0 < strlen($sValue) && is_numeric($sValue))
{
$iTimer = (int) $sValue;
}
return $iTimer;
}
/**
* @param string $sKey
*
* @return \MailSo\Cache\CacheClient
*/
public function Delete($sKey)
{
if ($this->oDriver)
{
$this->oDriver->Delete($sKey.$this->sCacheIndex);
}
return $this;
}
/**
* @param \MailSo\Cache\DriverInterface $oDriver
*
* @return \MailSo\Cache\CacheClient
*/
public function SetDriver(\MailSo\Cache\DriverInterface $oDriver)
{
$this->oDriver = $oDriver;
return $this;
}
/**
* @param int $iTimeToClearInHours = 24
*
* @return bool
*/
public function GC($iTimeToClearInHours = 24)
{
return $this->oDriver ? $this->oDriver->GC($iTimeToClearInHours) : false;
}
/**
* @return bool
*/
public function IsInited()
{
return $this->oDriver instanceof \MailSo\Cache\DriverInterface;
}
/**
* @param string $sCacheIndex
*
* @return \MailSo\Cache\CacheClient
*/
public function SetCacheIndex($sCacheIndex)
{
$this->sCacheIndex = 0 < \strlen($sCacheIndex) ? "\x0".$sCacheIndex : '';
return $this;
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace MailSo\Cache;
/**
* @category MailSo
* @package Cache
*/
interface DriverInterface
{
/**
* @param string $sKey
* @param string $sValue
*
* @return bool
*/
public function Set($sKey, $sValue);
/**
* @param string $sKey
*
* @return string
*/
public function Get($sKey);
/**
* @param string $sKey
*
* @return void
*/
public function Delete($sKey);
/**
* @param int $iTimeToClearInHours = 24
*
* @return bool
*/
public function GC($iTimeToClearInHours = 24);
}

View file

@ -0,0 +1,76 @@
<?php
namespace MailSo\Cache\Drivers;
/**
* @category MailSo
* @package Cache
* @subpackage Drivers
*/
class APC implements \MailSo\Cache\DriverInterface
{
/**
* @return \MailSo\Cache\Drivers\APC
*/
public static function NewInstance()
{
return new self();
}
/**
* @param string $sKey
* @param string $sValue
*
* @return bool
*/
public function Set($sKey, $sValue)
{
return \apc_store($this->generateCachedKey($sKey), (string) $sValue);
}
/**
* @param string $sKey
*
* @return string
*/
public function Get($sKey)
{
$sValue = \apc_fetch($this->generateCachedKey($sKey));
return \is_string($sValue) ? $sValue : '';
}
/**
* @param string $sKey
*
* @return void
*/
public function Delete($sKey)
{
\apc_delete($this->generateCachedKey($sKey));
}
/**
* @param int $iTimeToClearInHours = 24
*
* @return bool
*/
public function GC($iTimeToClearInHours = 24)
{
if (0 === $iTimeToClearInHours)
{
return \apc_clear_cache('user');
}
return false;
}
/**
* @param string $sKey
*
* @return string
*/
private function generateCachedKey($sKey)
{
return \sha1($sKey);
}
}

View file

@ -0,0 +1,126 @@
<?php
namespace MailSo\Cache\Drivers;
/**
* @category MailSo
* @package Cache
* @subpackage Drivers
*/
class File implements \MailSo\Cache\DriverInterface
{
/**
* @var string
*/
private $sCacheFolder;
/**
* @access private
*
* @param string $sCacheFolder
*/
private function __construct($sCacheFolder)
{
$this->sCacheFolder = $sCacheFolder;
$this->sCacheFolder = rtrim(trim($this->sCacheFolder), '\\/').'/';
if (!\is_dir($this->sCacheFolder))
{
@\mkdir($this->sCacheFolder, 0777);
}
}
/**
* @param string $sCacheFolder
*
* @return \MailSo\Cache\Drivers\File
*/
public static function NewInstance($sCacheFolder)
{
return new self($sCacheFolder);
}
/**
* @param string $sKey
* @param string $sValue
*
* @return bool
*/
public function Set($sKey, $sValue)
{
return false !== \file_put_contents($sPath = $this->generateCachedFileName($sKey, true), $sValue);
}
/**
* @param string $sKey
*
* @return string
*/
public function Get($sKey)
{
$sValue = '';
$sPath = $this->generateCachedFileName($sKey);
if (\file_exists($sPath))
{
$sValue = \file_get_contents($sPath);
}
return \is_string($sValue) ? $sValue : '';
}
/**
* @param string $sKey
*
* @return void
*/
public function Delete($sKey)
{
$sPath = $this->generateCachedFileName($sKey);
if (\file_exists($sPath))
{
\unlink($sPath);
}
}
/**
* @param int $iTimeToClearInHours = 24
*
* @return bool
*/
public function GC($iTimeToClearInHours = 24)
{
if (0 < $iTimeToClearInHours)
{
\MailSo\Base\Utils::RecTimeDirRemove($this->sCacheFolder, 60 * 60 * $iTimeToClearInHours, \time());
return true;
}
return false;
}
/**
* @param string $sKey
* @param bool $bMkDir = false
*
* @return string
*/
private function generateCachedFileName($sKey, $bMkDir = false)
{
$sFilePath = '';
if (3 < \strlen($sKey))
{
$sKeyPath = \sha1($sKey);
$sKeyPath = \substr($sKeyPath, 0, 2).'/'.\substr($sKeyPath, 2, 2).'/'.$sKeyPath;
$sFilePath = $this->sCacheFolder.'/'.$sKeyPath;
if ($bMkDir && !\is_dir(\dirname($sFilePath)))
{
if (!\mkdir(\dirname($sFilePath), 0777, true))
{
$sFilePath = '';
}
}
}
return $sFilePath;
}
}

View file

@ -0,0 +1,120 @@
<?php
namespace MailSo\Cache\Drivers;
/**
* @category MailSo
* @package Cache
* @subpackage Drivers
*/
class Memcache implements \MailSo\Cache\DriverInterface
{
/**
* @var string
*/
private $sHost;
/**
* @var int
*/
private $iPost;
/**
* @var int
*/
private $iExpire;
/**
* @var \Memcache|null
*/
private $oMem;
/**
* @param string $sHost = '127.0.0.1'
* @param int $iPost = 11211
* @param int $iExpire = 43200
*/
private function __construct($sHost = '127.0.0.1', $iPost = 11211, $iExpire = 43200)
{
$this->sHost = $sHost;
$this->iPost = $iPost;
$this->iExpire = 0 < $iExpire ? $iExpire : 43200;
$this->oMem = new \Memcache();
if (!$this->oMem->connect($this->sHost, $this->iPost))
{
$this->oMem = null;
}
}
/**
* @param string $sHost = '127.0.0.1'
* @param int $iPost = 11211
*
* @return \MailSo\Cache\Drivers\APC
*/
public static function NewInstance($sHost = '127.0.0.1', $iPost = 11211)
{
return new self($sHost, $iPost);
}
/**
* @param string $sKey
* @param string $sValue
*
* @return bool
*/
public function Set($sKey, $sValue)
{
return $this->oMem ? $this->oMem->set($this->generateCachedKey($sKey), $sValue, 0, $this->iExpire) : false;
}
/**
* @param string $sKey
*
* @return string
*/
public function Get($sKey)
{
$sValue = $this->oMem ? $this->oMem->get($this->generateCachedKey($sKey)) : '';
return \is_string($sValue) ? $sValue : '';
}
/**
* @param string $sKey
*
* @return void
*/
public function Delete($sKey)
{
if ($this->oMem)
{
$this->oMem->delete($this->generateCachedKey($sKey));
}
}
/**
* @param int $iTimeToClearInHours = 24
*
* @return bool
*/
public function GC($iTimeToClearInHours = 24)
{
if (0 === $iTimeToClearInHours && $this->oMem)
{
return $this->oMem->flush();
}
return false;
}
/**
* @param string $sKey
*
* @return string
*/
private function generateCachedKey($sKey)
{
return \sha1($sKey);
}
}

View file

@ -0,0 +1,856 @@
<?php
namespace MailSo\Imap;
/**
* @category MailSo
* @package Imap
*/
class BodyStructure
{
/**
* @var string
*/
private $sContentType;
/**
* @var string
*/
private $sCharset;
/**
* @var array
*/
private $aBodyParams;
/**
* @var string
*/
private $sContentID;
/**
* @var string
*/
private $sDescription;
/**
* @var string
*/
private $sMailEncodingName;
/**
* @var string
*/
private $sDisposition;
/**
* @var array
*/
private $aDispositionParams;
/**
* @var string
*/
private $sFileName;
/**
* @var string
*/
private $sLanguage;
/**
* @var string
*/
private $sLocation;
/**
* @var int
*/
private $iSize;
/**
* @var int
*/
private $iTextLineCount;
/**
* @var string
*/
private $sPartID;
/**
* @var array
*/
private $aSubParts;
/**
* @access private
*
* @param string $sContentType
* @param string $sCharset
* @param array $aBodyParams
* @param string $sContentID
* @param string $sDescription
* @param string $sMailEncodingName
* @param string $sDisposition
* @param array $aDispositionParams
* @param string $sFileName
* @param string $sLanguage
* @param string $sLocation
* @param int $iSize
* @param int $iTextLineCount
* @param string $sPartID
* @param array $aSubParts
*/
private function __construct($sContentType, $sCharset, $aBodyParams, $sContentID,
$sDescription, $sMailEncodingName, $sDisposition, $aDispositionParams, $sFileName,
$sLanguage, $sLocation, $iSize, $iTextLineCount, $sPartID, $aSubParts)
{
$this->sContentType = $sContentType;
$this->sCharset = $sCharset;
$this->aBodyParams = $aBodyParams;
$this->sContentID = $sContentID;
$this->sDescription = $sDescription;
$this->sMailEncodingName = $sMailEncodingName;
$this->sDisposition = $sDisposition;
$this->aDispositionParams = $aDispositionParams;
$this->sFileName = $sFileName;
$this->sLanguage = $sLanguage;
$this->sLocation = $sLocation;
$this->iSize = $iSize;
$this->iTextLineCount = $iTextLineCount;
$this->sPartID = $sPartID;
$this->aSubParts = $aSubParts;
}
/**
* return string
*/
public function MailEncodingName()
{
return $this->sMailEncodingName;
}
/**
* return string
*/
public function PartID()
{
return (string) $this->sPartID;
}
/**
* return string
*/
public function FileName()
{
return $this->sFileName;
}
/**
* return string
*/
public function ContentType()
{
return $this->sContentType;
}
/**
* return int
*/
public function Size()
{
return (int) $this->iSize;
}
/**
* return int
*/
public function EstimatedSize()
{
$fCoefficient = 1;
switch (strtolower($this->MailEncodingName()))
{
case 'base64':
$fCoefficient = 0.75;
break;
case 'quoted-printable':
$fCoefficient = 0.44;
break;
}
return (int) ($this->Size() * $fCoefficient);
}
/**
* return string
*/
public function Charset()
{
return $this->sCharset;
}
/**
* return string
*/
public function ContentID()
{
return (null === $this->sContentID) ? '' : $this->sContentID;
}
/**
* return bool
*/
public function IsInline()
{
return (null === $this->sDisposition) ?
(0 < strlen($this->ContentID())) : ('inline' === strtolower($this->sDisposition));
}
/**
* @return array|null
*/
public function SearchPlainParts()
{
$aReturn = array();
$aParts = $this->SearchByContentType('text/plain');
foreach ($aParts as $oPart)
{
if (!$oPart->isAttachBodyPart())
{
$aReturn[] = $oPart;
}
}
return $aReturn;
}
/**
* @return array|null
*/
public function SearchHtmlParts()
{
$aReturn = array();
$aParts = $this->SearchByContentType('text/html');
foreach ($aParts as $oPart)
{
if (!$oPart->isAttachBodyPart())
{
$aReturn[] = $oPart;
}
}
return $aReturn;
}
/**
* @return array|null
*/
public function SearchHtmlOrPlainParts()
{
$mResult = $this->SearchHtmlParts();
if (null === $mResult || (is_array($mResult) && 0 === count($mResult)))
{
$mResult = $this->SearchPlainParts();
}
return $mResult;
}
/**
* @return string
*/
public function SearchCharset()
{
$sResult = '';
$mHtmlParts = $this->SearchHtmlParts();
$mPlainParts = $this->SearchPlainParts();
$mParts = array();
if (is_array($mHtmlParts) && 0 < count($mHtmlParts))
{
$mParts = array_merge($mParts, $mHtmlParts);
}
if (is_array($mPlainParts) && 0 < count($mPlainParts))
{
$mParts = array_merge($mParts, $mPlainParts);
}
foreach ($mParts as $oPart)
{
$sResult = $oPart ? $oPart->Charset() : '';
if (!empty($sResult))
{
break;
}
}
if (0 === strlen($sResult))
{
$aParts = $this->SearchAttachmentsParts();
foreach ($aParts as $oPart)
{
if (0 === strlen($sResult))
{
$sResult = $oPart ? $oPart->Charset() : '';
}
else
{
break;
}
}
}
return $sResult;
}
/**
* @return bool
*/
protected function isAttachBodyPart()
{
$bResult = (
(null !== $this->sDisposition && 'attachment' === strtolower($this->sDisposition))
);
if (!$bResult && null !== $this->sContentType)
{
$sContentType = strtolower($this->sContentType);
$bResult = false === strpos($sContentType, 'multipart/') &&
'text/html' !== $sContentType && 'text/plain' !== $sContentType;
}
return $bResult;
}
/**
* @return array
*/
public function SearchAttachmentsParts()
{
$aReturn = array();
if ($this->isAttachBodyPart())
{
$aReturn[] = $this;
}
if (is_array($this->aSubParts) && 0 < count($this->aSubParts))
{
foreach ($this->aSubParts as /* @var $oSubPart \MailSo\Imap\BodyStructure */ &$oSubPart)
{
$aReturn = array_merge($aReturn, $oSubPart->SearchAttachmentsParts());
unset($oSubPart);
}
}
return $aReturn;
}
/**
* @param string $sContentType
*
* @return array
*/
public function SearchByContentType($sContentType)
{
$aReturn = array();
if (strtolower($sContentType) === $this->sContentType)
{
$aReturn[] = $this;
}
if (is_array($this->aSubParts) && 0 < count($this->aSubParts))
{
foreach ($this->aSubParts as /* @var $oSubPart \MailSo\Imap\BodyStructure */ &$oSubPart)
{
$aReturn = array_merge($aReturn, $oSubPart->SearchByContentType($sContentType));
}
}
return $aReturn;
}
/**
* @param string $sMimeIndex
*
* @return \MailSo\Imap\BodyStructure
*/
public function GetPartByMimeIndex($sMimeIndex)
{
$oPart = null;
if (0 < strlen($sMimeIndex))
{
if ($sMimeIndex === $this->sPartID)
{
$oPart = $this;
}
if (null === $oPart && is_array($this->aSubParts) && 0 < count($this->aSubParts))
{
foreach ($this->aSubParts as /* @var $oSubPart \MailSo\Imap\BodyStructure */ &$oSubPart)
{
$oPart = $oSubPart->GetPartByMimeIndex($sMimeIndex);
if (null !== $oPart)
{
break;
}
}
}
}
return $oPart;
}
/**
* @param array $aParams
* @param string $sParamName
* @param string $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8
*
* @return string
*/
private static function decodeAttrParamenter($aParams, $sParamName, $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8)
{
$sResult = '';
if (isset($aParams[$sParamName]))
{
$sResult = \MailSo\Base\Utils::DecodeHeaderValue($aParams[$sParamName], $sCharset);
}
else if (isset($aParams[$sParamName.'*']))
{
$aValueParts = explode('\'\'', $aParams[$sParamName.'*'], 2);
if (is_array($aValueParts) && 2 === count($aValueParts))
{
$sCharset = isset($aValueParts[0]) ? $aValueParts[0] : \MailSo\Base\Enumerations\Charset::UTF_8;
$sResult = \MailSo\Base\Utils::ConvertEncoding(
urldecode($aValueParts[1]), $sCharset, \MailSo\Base\Enumerations\Charset::UTF_8);
}
else
{
$sResult = urldecode($aParams[$sParamName.'*']);
}
}
else if (isset($aParams[$sParamName.'*0*']))
{
$sCharset = '';
$aFileNames = array();
foreach ($aParams as $sName => $sValue)
{
$aMatches = array();
if ($sParamName.'*0*' === $sName)
{
if (0 === strlen($sCharset))
{
$aValueParts = explode('\'\'', $sValue, 2);
if (is_array($aValueParts) && 2 === count($aValueParts) && 0 < strlen($aValueParts[0]))
{
$sCharset = $aValueParts[0];
$sValue = $aValueParts[1];
}
}
$aFileNames[0] = $sValue;
}
else if ($sParamName.'*0*' !== $sName && preg_match('/^'.preg_quote($sParamName, '/').'\*([0-9]+)\*$/i', $sName, $aMatches) && 0 < strlen($aMatches[1]))
{
$aFileNames[(int) $aMatches[1]] = $sValue;
}
}
if (0 < count($aFileNames))
{
ksort($aFileNames, SORT_NUMERIC);
$sResult = implode(array_values($aFileNames));
$sResult = urldecode($sResult);
if (0 < strlen($sCharset))
{
$sResult = \MailSo\Base\Utils::ConvertEncoding($sResult,
$sCharset, \MailSo\Base\Enumerations\Charset::UTF_8);
}
}
}
return $sResult;
}
/**
* @param array $aBodyStructure
* @param string $sPartID = ''
*
* @return \MailSo\Imap\BodyStructure
*/
public static function NewInstance(array $aBodyStructure, $sPartID = '')
{
if (!is_array($aBodyStructure) || 2 > count($aBodyStructure))
{
return null;
}
else
{
$sBodyMainType = null;
if (is_string($aBodyStructure[0]) && 'NIL' !== $aBodyStructure[0])
{
$sBodyMainType = $aBodyStructure[0];
}
$sBodySubType = null;
$sContentType = '';
$aSubParts = null;
$aBodyParams = array();
$sName = null;
$sCharset = null;
$sContentID = null;
$sDescription = null;
$sMailEncodingName = null;
$iSize = 0;
$iTextLineCount = 0; // valid for rfc822/message and text parts
$iExtraItemPos = 0; // list index of items which have no well-established position (such as 0, 1, 5, etc).
if (null === $sBodyMainType)
{
// Process multipart body structure
if (!is_array($aBodyStructure[0]))
{
return null;
}
else
{
$sBodyMainType = 'multipart';
$sSubPartIDPrefix = '';
if (0 === strlen($sPartID) || '.' === $sPartID[strlen($sPartID) - 1])
{
// This multi-part is root part of message.
$sSubPartIDPrefix = $sPartID;
$sPartID .= 'TEXT';
}
else if (0 < strlen($sPartID))
{
// This multi-part is a part of another multi-part.
$sSubPartIDPrefix = $sPartID.'.';
}
$aSubParts = array();
$iIndex = 1;
while ($iExtraItemPos < count($aBodyStructure) && is_array($aBodyStructure[$iExtraItemPos]))
{
$oPart = self::NewInstance($aBodyStructure[$iExtraItemPos], $sSubPartIDPrefix.$iIndex);
if (null === $oPart)
{
return null;
}
else
{
// For multipart, we have no charset info in the part itself. Thus,
// obtain charset from nested parts.
if ($sCharset == null)
{
$sCharset = $oPart->Charset();
}
$aSubParts[] = $oPart;
$iExtraItemPos++;
$iIndex++;
}
}
}
if ($iExtraItemPos < count($aBodyStructure))
{
if (!is_string($aBodyStructure[$iExtraItemPos]) || 'NIL' === $aBodyStructure[$iExtraItemPos])
{
return null;
}
$sBodySubType = strtolower($aBodyStructure[$iExtraItemPos]);
$iExtraItemPos++;
}
if ($iExtraItemPos < count($aBodyStructure))
{
$sBodyParamList = $aBodyStructure[$iExtraItemPos];
if (is_array($sBodyParamList))
{
$aBodyParams = self::getKeyValueListFromArrayList($sBodyParamList);
}
}
$iExtraItemPos++;
}
else
{
// Process simple (singlepart) body structure
if (7 > count($aBodyStructure))
{
return null;
}
$sBodyMainType = strtolower($sBodyMainType);
if (!is_string($aBodyStructure[1]) || 'NIL' === $aBodyStructure[1])
{
return null;
}
$sBodySubType = strtolower($aBodyStructure[1]);
$aBodyParamList = $aBodyStructure[2];
if (is_array($aBodyParamList))
{
$aBodyParams = self::getKeyValueListFromArrayList($aBodyParamList);
if (isset($aBodyParams['charset']))
{
$sCharset = $aBodyParams['charset'];
}
if (is_array($aBodyParams))
{
$sName = self::decodeAttrParamenter($aBodyParams, 'name', $sContentType);
}
}
if (null !== $aBodyStructure[3] && 'NIL' !== $aBodyStructure[3])
{
if (!is_string($aBodyStructure[3]))
{
return null;
}
$sContentID = $aBodyStructure[3];
}
if (null !== $aBodyStructure[4] && 'NIL' !== $aBodyStructure[4])
{
if (!is_string($aBodyStructure[4]))
{
return null;
}
$sDescription = $aBodyStructure[4];
}
if (null !== $aBodyStructure[5] && 'NIL' !== $aBodyStructure[5])
{
if (!is_string($aBodyStructure[5]))
{
return null;
}
$sMailEncodingName = $aBodyStructure[5];
}
if (is_numeric($aBodyStructure[6]))
{
$iSize = (int) $aBodyStructure[6];
}
else
{
$iSize = -1;
}
if (0 === strlen($sPartID) || '.' === $sPartID[strlen($sPartID) - 1])
{
// This is the only sub-part of the message (otherwise, it would be
// one of sub-parts of a multi-part, and partID would already be fully set up).
$sPartID .= '1';
}
$iExtraItemPos = 7;
if ('text' === $sBodyMainType)
{
if ($iExtraItemPos < count($aBodyStructure))
{
if (is_numeric($aBodyStructure[$iExtraItemPos]))
{
$iTextLineCount = (int) $aBodyStructure[$iExtraItemPos];
}
else
{
$iTextLineCount = -1;
}
}
else
{
$iTextLineCount = -1;
}
$iExtraItemPos++;
}
else if ('message' === $sBodyMainType && 'rfc822' === $sBodySubType)
{
if ($iExtraItemPos + 2 < count($aBodyStructure))
{
if (is_numeric($aBodyStructure[$iExtraItemPos + 2]))
{
$iTextLineCount = (int) $aBodyStructure[$iExtraItemPos + 2];
}
else
{
$iTextLineCount = -1;
}
}
else
{
$iTextLineCount = -1;
}
$iExtraItemPos += 3;
}
$iExtraItemPos++; // skip MD5 digest of the body because most mail servers leave it NIL anyway
}
$sContentType = $sBodyMainType.'/'.$sBodySubType;
$sDisposition = null;
$aDispositionParams = null;
$sFileName = null;
if ($iExtraItemPos < count($aBodyStructure))
{
$aDispList = $aBodyStructure[$iExtraItemPos];
if (is_array($aDispList) && 1 < count($aDispList))
{
if (null !== $aDispList[0])
{
if (is_string($aDispList[0]) && 'NIL' !== $aDispList[0])
{
$sDisposition = $aDispList[0];
}
else
{
return null;
}
}
}
$aDispParamList = $aDispList[1];
if (is_array($aDispParamList))
{
$aDispositionParams = self::getKeyValueListFromArrayList($aDispParamList);
if (is_array($aDispositionParams))
{
$sFileName = self::decodeAttrParamenter($aDispositionParams, 'filename', $sCharset);
}
}
}
$iExtraItemPos++;
$sLanguage = null;
if ($iExtraItemPos < count($aBodyStructure))
{
if (null !== $aBodyStructure[$iExtraItemPos] && 'NIL' !== $aBodyStructure[$iExtraItemPos])
{
if (is_array($aBodyStructure[$iExtraItemPos]))
{
$sLanguage = implode(',', $aBodyStructure[$iExtraItemPos]);
}
else if (is_string($aBodyStructure[$iExtraItemPos]))
{
$sLanguage = $aBodyStructure[$iExtraItemPos];
}
}
$iExtraItemPos++;
}
$sLocation = null;
if ($iExtraItemPos < count($aBodyStructure))
{
if (null !== $aBodyStructure[$iExtraItemPos] && 'NIL' !== $aBodyStructure[$iExtraItemPos])
{
if (is_string($aBodyStructure[$iExtraItemPos]))
{
$sLocation = $aBodyStructure[$iExtraItemPos];
}
}
$iExtraItemPos++;
}
return new self(
$sContentType,
$sCharset,
$aBodyParams,
$sContentID,
$sDescription,
$sMailEncodingName,
$sDisposition,
$aDispositionParams,
\MailSo\Base\Utils::Utf8Clear(
null === $sFileName || 0 === strlen($sFileName) ? $sName : $sFileName),
$sLanguage,
$sLocation,
$iSize,
$iTextLineCount,
$sPartID,
$aSubParts
);
}
}
/**
* @param array $aBodyStructure
* @param string $sPartID
*
* @return \MailSo\Imap\BodyStructure|null
*/
public static function NewInstanceFromRfc822SubPart(array $aBodyStructure, $sSubPartID)
{
$oBody = null;
$aBodySubStructure = self::findPartByIndexInArray($aBodyStructure, $sSubPartID);
if ($aBodySubStructure && is_array($aBodySubStructure) && isset($aBodySubStructure[8]))
{
$oBody = self::NewInstance($aBodySubStructure[8], $sSubPartID);
}
return $oBody;
}
/**
* @param array $aList
* @param string $sPartID
*
* @return array|null
*/
private static function findPartByIndexInArray(array $aList, $sPartID)
{
$bFind = false;
$aPath = explode('.', ''.$sPartID);
$aCurrentPart = $aList;
foreach ($aPath as $iPos => $iNum)
{
$iIndex = intval($iNum) - 1;
if (0 <= $iIndex && 0 < $iPos ? isset($aCurrentPart[8][$iIndex]) : isset($aCurrentPart[$iIndex]))
{
$aCurrentPart = 0 < $iPos ? $aCurrentPart[8][$iIndex] : $aCurrentPart[$iIndex];
$bFind = true;
}
}
return $bFind ? $aCurrentPart : null;
}
/**
* Returns dict with key="charset" and value="US-ASCII" for array ("CHARSET" "US-ASCII").
* Keys are lowercased (StringDictionary itself does this), values are not altered.
*
* @param array $aList
*
* @return array
*/
private static function getKeyValueListFromArrayList(array $aList)
{
$aDict = null;
if (0 === count($aList) % 2)
{
$aDict = array();
for ($iIndex = 0, $iLen = count($aList); $iIndex < $iLen; $iIndex += 2)
{
if (is_string($aList[$iIndex]) && isset($aList[$iIndex + 1]) && is_string($aList[$iIndex + 1]))
{
$aDict[strtolower($aList[$iIndex])] = $aList[$iIndex + 1];
}
}
}
return $aDict;
}
}

View file

@ -0,0 +1,119 @@
<?php
namespace MailSo\Imap\Enumerations;
/**
* @category MailSo
* @package Imap
* @subpackage Enumerations
*/
class FetchType
{
const ALL = 'ALL';
const FAST = 'FAST';
const FULL = 'FULL';
const BODY = 'BODY';
const BODY_PEEK = 'BODY.PEEK';
const BODY_HEADER = 'BODY[HEADER]';
const BODY_HEADER_PEEK = 'BODY.PEEK[HEADER]';
const BODYSTRUCTURE = 'BODYSTRUCTURE';
const ENVELOPE = 'ENVELOPE';
const FLAGS = 'FLAGS';
const INTERNALDATE = 'INTERNALDATE';
const RFC822 = 'RFC822';
const RFC822_HEADER = 'RFC822.HEADER';
const RFC822_SIZE = 'RFC822.SIZE';
const RFC822_TEXT = 'RFC822.TEXT';
const UID = 'UID';
const INDEX = 'INDEX';
const GMAIL_MSGID = 'X-GM-MSGID';
const GMAIL_THRID = 'X-GM-THRID';
const GMAIL_LABELS = 'X-GM-LABELS';
/**
* @param array $aReturn
*
* @param string|array $mType
*/
private static function addHelper(&$aReturn, $mType)
{
if (is_string($mType))
{
$aReturn[$mType] = '';
}
else if (is_array($mType) && 2 === count($mType) && is_string($mType[0]) &&
is_callable($mType[1]))
{
$aReturn[$mType[0]] = $mType[1];
}
}
/**
* @param array $aHeaders
* @param bool $bPeek = true
*
* @return string
*/
public static function BuildBodyCustomHeaderRequest(array $aHeaders, $bPeek = true)
{
$sResult = '';
if (0 < count($aHeaders))
{
$aHeaders = array_map('trim', $aHeaders);
$aHeaders = array_map('strtoupper', $aHeaders);
$sResult = $bPeek ? self::BODY_PEEK : self::BODY;
$sResult .= '[HEADER.FIELDS ('.implode(' ', $aHeaders).')]';
}
return $sResult;
}
/**
* @param array $aFetchItems
*
* @return array
*/
public static function ChangeFetchItemsBefourRequest(array $aFetchItems)
{
$aReturn = array();
self::addHelper($aReturn, self::UID);
foreach ($aFetchItems as $mFetchKey)
{
switch ($mFetchKey)
{
default:
if (is_string($mFetchKey) || is_array($mFetchKey))
{
self::addHelper($aReturn, $mFetchKey);
}
break;
case self::INDEX:
case self::UID:
break;
case self::ALL:
self::addHelper($aReturn, self::FLAGS);
self::addHelper($aReturn, self::INTERNALDATE);
self::addHelper($aReturn, self::RFC822_SIZE);
self::addHelper($aReturn, self::ENVELOPE);
break;
case self::FAST:
self::addHelper($aReturn, self::FLAGS);
self::addHelper($aReturn, self::INTERNALDATE);
self::addHelper($aReturn, self::RFC822_SIZE);
break;
case self::FULL:
self::addHelper($aReturn, self::FLAGS);
self::addHelper($aReturn, self::INTERNALDATE);
self::addHelper($aReturn, self::RFC822_SIZE);
self::addHelper($aReturn, self::ENVELOPE);
self::addHelper($aReturn, self::BODY);
break;
}
}
return $aReturn;
}
}

View file

@ -0,0 +1,17 @@
<?php
namespace MailSo\Imap\Enumerations;
/**
* @category MailSo
* @package Imap
* @subpackage Enumerations
*/
class FolderResponseStatus
{
const MESSAGES = 'MESSAGES';
const RECENT = 'RECENT';
const UNSEEN = 'UNSEEN';
const UIDNEXT = 'UIDNEXT';
const UIDVALIDITY = 'UIDVALIDITY';
}

View file

@ -0,0 +1,17 @@
<?php
namespace MailSo\Imap\Enumerations;
/**
* @category MailSo
* @package Imap
* @subpackage Enumerations
*/
class FolderStatus
{
const MESSAGES = 'MESSAGES';
const RECENT = 'RECENT';
const UNSEEN = 'UNSEEN';
const UIDNEXT = 'UIDNEXT';
const UIDVALIDITY = 'UIDVALIDITY';
}

View file

@ -0,0 +1,21 @@
<?php
namespace MailSo\Imap\Enumerations;
/**
* @category MailSo
* @package Imap
* @subpackage Enumerations
*/
class FolderType
{
const USER = 0;
const INBOX = 1;
const SENT = 2;
const DRAFTS = 3;
const SPAM = 4;
const TRASH = 5;
const IMPORTANT = 10;
const STARRED = 11;
const ALLMAIL = 12;
}

View file

@ -0,0 +1,18 @@
<?php
namespace MailSo\Imap\Enumerations;
/**
* @category MailSo
* @package Imap
* @subpackage Enumerations
*/
class MessageFlag
{
const RECENT = '\Recent';
const SEEN = '\Seen';
const DELETED = '\Deleted';
const FLAGGED = '\Flagged';
const ANSWERED = '\Answered';
const DRAFT = '\Draft';
}

View file

@ -0,0 +1,17 @@
<?php
namespace MailSo\Imap\Enumerations;
/**
* @category MailSo
* @package Imap
* @subpackage Enumerations
*/
class ResponseStatus
{
const OK = 'OK';
const NO = 'NO';
const BAD = 'BAD';
const BYE = 'BYE';
const PREAUTH = 'PREAUTH';
}

View file

@ -0,0 +1,16 @@
<?php
namespace MailSo\Imap\Enumerations;
/**
* @category MailSo
* @package Imap
* @subpackage Enumerations
*/
class ResponseType
{
const UNKNOWN = 0;
const TAGGED = 1;
const UNTAGGED = 2;
const CONTINUATION = 3;
}

View file

@ -0,0 +1,25 @@
<?php
namespace MailSo\Imap\Enumerations;
/**
* @category MailSo
* @package Imap
* @subpackage Enumerations
*/
class StoreAction
{
const SET_FLAGS = 'FLAGS';
const SET_FLAGS_SILENT = 'FLAGS.SILENT';
const ADD_FLAGS = '+FLAGS';
const ADD_FLAGS_SILENT = '+FLAGS.SILENT';
const REMOVE_FLAGS = '-FLAGS';
const REMOVE_FLAGS_SILENT = '-FLAGS.SILENT';
const SET_GMAIL_LABELS = 'X-GM-LABELS';
const SET_GMAIL_LABELS_SILENT = 'X-GM-LABELS.SILENT';
const ADD_GMAIL_LABELS = '+X-GM-LABELS';
const ADD_GMAIL_LABELS_SILENT = '+X-GM-LABELS.SILENT';
const REMOVE_GMAIL_LABELS = '-X-GM-LABELS';
const REMOVE_GMAIL_LABELS_SILENT = '-X-GM-LABELS.SILENT';
}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Imap\Exceptions;
/**
* @category MailSo
* @package Imap
* @subpackage Exceptions
*/
class Exception extends \MailSo\Base\Exceptions\Exception {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Imap\Exceptions;
/**
* @category MailSo
* @package Imap
* @subpackage Exceptions
*/
class InvalidResponseException extends \MailSo\Imap\Exceptions\ResponseException {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Imap\Exceptions;
/**
* @category MailSo
* @package Imap
* @subpackage Exceptions
*/
class LoginBadCredentialsException extends \MailSo\Imap\Exceptions\LoginException {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Imap\Exceptions;
/**
* @category MailSo
* @package Imap
* @subpackage Exceptions
*/
class LoginBadMethodException extends \MailSo\Imap\Exceptions\LoginException {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Imap\Exceptions;
/**
* @category MailSo
* @package Imap
* @subpackage Exceptions
*/
class LoginException extends \MailSo\Imap\Exceptions\NegativeResponseException {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Imap\Exceptions;
/**
* @category MailSo
* @package Imap
* @subpackage Exceptions
*/
class NegativeResponseException extends \MailSo\Imap\Exceptions\ResponseException {}

View file

@ -0,0 +1,48 @@
<?php
namespace MailSo\Imap\Exceptions;
/**
* @category MailSo
* @package Imap
* @subpackage Exceptions
*/
class ResponseException extends \MailSo\Imap\Exceptions\Exception
{
/**
* @var array
*/
private $aResponses;
/**
* @param array $aResponses = array
* @param string $sMessage = ''
* @param int $iCode = 0
* @param \Exception $oPrevious = null
*/
public function __construct($aResponses = array(), $sMessage = '', $iCode = 0, $oPrevious = null)
{
parent::__construct($sMessage, $iCode, $oPrevious);
if (is_array($aResponses))
{
$this->aResponses = $aResponses;
}
}
/**
* @return array
*/
public function GetResponses()
{
return $this->aResponses;
}
/**
* @return \MailSo\Imap\Response | null
*/
public function GetLastResponse()
{
return 0 < count($this->aResponses) ? $this->aResponses[count($this->aResponses) - 1] : null;
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Imap\Exceptions;
/**
* @category MailSo
* @package Imap
* @subpackage Exceptions
*/
class ResponseNotFoundException extends \MailSo\Imap\Exceptions\Exception {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Imap\Exceptions;
/**
* @category MailSo
* @package Imap
* @subpackage Exceptions
*/
class RuntimeException extends \MailSo\Imap\Exceptions\Exception {}

View file

@ -0,0 +1,225 @@
<?php
namespace MailSo\Imap;
/**
* @category MailSo
* @package Imap
*/
class FetchResponse
{
/**
* @var \MailSo\Imap\Response
*/
private $oImapResponse;
/**
* @var array|null
*/
private $aEnvelopeCache;
/**
* @access private
*
* @param \MailSo\Imap\Response $oImapResponse
*/
private function __construct(&$oImapResponse)
{
$this->oImapResponse =& $oImapResponse;
$this->aEnvelopeCache = null;
}
/**
* @param \MailSo\Imap\Response &$oImapResponse
* @return \MailSo\Imap\FetchResponse
*/
public static function NewInstance(&$oImapResponse)
{
return new self($oImapResponse);
}
/**
* @param bool $bForce = false
*
* @return array|null
*/
public function GetEnvelope($bForce = false)
{
if (null === $this->aEnvelopeCache || $bForce)
{
$this->aEnvelopeCache = $this->GetFetchValue(Enumerations\FetchType::ENVELOPE);
}
return $this->aEnvelopeCache;
}
/**
* @param int $iIndex
* @param mixed $mNullResult = null
*
* @return mixed
*/
public function GetFetchEnvelopeValue($iIndex, $mNullResult)
{
return self::findEnvelopeIndex($this->GetEnvelope(), $iIndex, $mNullResult);
}
/**
* @param int $iIndex
* @param string $sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1
*
* @return \MailSo\Mime\EmailCollection|null
*/
public function GetFetchEnvelopeEmailCollection($iIndex, $sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1)
{
$oResult = null;
$aEmails = $this->GetFetchEnvelopeValue($iIndex, null);
if (is_array($aEmails) && 0 < count($aEmails))
{
$oResult = \MailSo\Mime\EmailCollection::NewInstance();
foreach ($aEmails as $aEmailItem)
{
if (is_array($aEmailItem) && 4 === count($aEmailItem))
{
$sDisplayName = \MailSo\Base\Utils::DecodeHeaderValue(
self::findEnvelopeIndex($aEmailItem, 0, ''), $sParentCharset);
$sRemark = \MailSo\Base\Utils::DecodeHeaderValue(
self::findEnvelopeIndex($aEmailItem, 1, ''), $sParentCharset);
$sLocalPart = self::findEnvelopeIndex($aEmailItem, 2, '');
$sDomainPart = self::findEnvelopeIndex($aEmailItem, 3, '');
if (0 < strlen($sLocalPart) && 0 < strlen($sDomainPart))
{
$oResult->Add(
\MailSo\Mime\Email::NewInstance(
$sLocalPart.'@'.$sDomainPart, $sDisplayName, $sRemark)
);
}
}
}
}
return $oResult;
}
/**
* @param string $sRfc822SubMimeIndex = ''
*
* @return \MailSo\Imap\BodyStructure|null
*/
public function GetFetchBodyStructure($sRfc822SubMimeIndex = '')
{
$oBodyStructure = null;
$aBodyStructureArray = $this->GetFetchValue(Enumerations\FetchType::BODYSTRUCTURE);
if (is_array($aBodyStructureArray))
{
if (0 < strlen($sRfc822SubMimeIndex))
{
$oBodyStructure = BodyStructure::NewInstanceFromRfc822SubPart($aBodyStructureArray, $sRfc822SubMimeIndex);
}
else
{
$oBodyStructure = BodyStructure::NewInstance($aBodyStructureArray);
}
}
return $oBodyStructure;
}
/**
* @param string $sFetchItemName
*
* @return mixed
*/
public function &GetFetchValue($sFetchItemName)
{
$mReturn = null;
$bNextIsValue = false;
if (Enumerations\FetchType::INDEX === $sFetchItemName)
{
$mReturn =& $this->oImapResponse->ResponseList[1];
}
else
{
foreach ($this->oImapResponse->ResponseList[3] as &$mItem)
{
if ($bNextIsValue)
{
$mReturn =& $mItem;
break;
}
if ($sFetchItemName === $mItem)
{
$bNextIsValue = true;
}
}
}
return $mReturn;
}
/**
* @param string $sRfc822SubMimeIndex = ''
*
* @return string
*/
public function GetHeaderFieldsValue($sRfc822SubMimeIndex = '')
{
$sReturn = '';
$bNextIsValue = false;
$sRfc822SubMimeIndex = 0 < \strlen($sRfc822SubMimeIndex) ? ''.$sRfc822SubMimeIndex.'.' : '';
if (isset($this->oImapResponse->ResponseList[3]) && \is_array($this->oImapResponse->ResponseList[3]))
{
foreach ($this->oImapResponse->ResponseList[3] as &$mItem)
{
if ($bNextIsValue)
{
$sReturn = (string) $mItem;
break;
}
if (\is_string($mItem) && (
$mItem === 'BODY['.$sRfc822SubMimeIndex.'HEADER]' ||
0 === \strpos($mItem, 'BODY['.$sRfc822SubMimeIndex.'HEADER.FIELDS') ||
$mItem === 'BODY['.$sRfc822SubMimeIndex.'MIME]'))
{
$bNextIsValue = true;
}
}
}
return $sReturn;
}
/**
* @param \MailSo\Imap\Response $oImapResponse
*
* @return bool
*/
public static function IsValidFetchImapResponse($oImapResponse)
{
return ($oImapResponse && true !== $oImapResponse->IsStatusResponse
&& \MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType
&& 3 < count($oImapResponse->ResponseList) && 'FETCH' === $oImapResponse->ResponseList[2]
&& is_array($oImapResponse->ResponseList[3]));
}
/**
* @param array $aEnvelope
* @param int $iIndex
* @param mixed $mNullResult = null
*
* @return mixed
*/
private static function findEnvelopeIndex($aEnvelope, $iIndex, $mNullResult)
{
return (isset($aEnvelope[$iIndex]) && 'NIL' !== $aEnvelope[$iIndex] && '' !== $aEnvelope[$iIndex])
? $aEnvelope[$iIndex] : $mNullResult;
}
}

View file

@ -0,0 +1,179 @@
<?php
namespace MailSo\Imap;
/**
* @category MailSo
* @package Imap
*/
class Folder
{
/**
* @var string
*/
private $sNameRaw;
/**
* @var string
*/
private $sFullNameRaw;
/**
* @var string
*/
private $sDelimiter;
/**
* @var array
*/
private $aFlags;
/**
* @var array
*/
private $aFlagsLowerCase;
/**
* @var array
*/
private $aExtended;
/**
* @access private
*
* @param string $sFullNameRaw
* @param string $sDelimiter
* @param array $aFlags
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
private function __construct($sFullNameRaw, $sDelimiter, array $aFlags)
{
$this->sNameRaw = '';
$this->sFullNameRaw = '';
$this->sDelimiter = '';
$this->aFlags = array();
$this->aExtended = array();
$sDelimiter = 'NIL' === \strtoupper($sDelimiter) ? '' : $sDelimiter;
if (empty($sDelimiter))
{
$sDelimiter = '.'; // default delimiter
}
if (!\is_array($aFlags) ||
!\is_string($sDelimiter) || 1 < \strlen($sDelimiter) ||
!\is_string($sFullNameRaw) || 0 === \strlen($sFullNameRaw))
{
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
}
$this->sFullNameRaw = $sFullNameRaw;
$this->sDelimiter = $sDelimiter;
$this->aFlags = $aFlags;
$this->aFlagsLowerCase = \array_map('strtolower', $this->aFlags);
$this->sFullNameRaw = 'INBOX'.$this->sDelimiter === \substr(\strtoupper($this->sFullNameRaw), 0, 5 + \strlen($this->sDelimiter)) ?
'INBOX'.\substr($this->sFullNameRaw, 5) : $this->sFullNameRaw;
if ($this->IsInbox())
{
$this->sFullNameRaw = 'INBOX';
}
$this->sNameRaw = $this->sFullNameRaw;
if (0 < \strlen($this->sDelimiter))
{
$aNames = \explode($this->sDelimiter, $this->sFullNameRaw);
$this->sNameRaw = \end($aNames);
}
}
/**
* @param string $sFullNameRaw
* @param string $sDelimiter = '.'
* @param array $aFlags = array()
*
* @return \MailSo\Imap\Folder
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public static function NewInstance($sFullNameRaw, $sDelimiter = '.', $aFlags = array())
{
return new self($sFullNameRaw, $sDelimiter, $aFlags);
}
/**
* @return string
*/
public function NameRaw()
{
return $this->sNameRaw;
}
/**
* @return string
*/
public function FullNameRaw()
{
return $this->sFullNameRaw;
}
/**
* @return string | null
*/
public function Delimiter()
{
return $this->sDelimiter;
}
/**
* @return array
*/
public function Flags()
{
return $this->aFlags;
}
/**
* @return array
*/
public function FlagsLowerCase()
{
return $this->aFlagsLowerCase;
}
/**
* @return bool
*/
public function IsSelectable()
{
return !\in_array('\noselect', $this->aFlagsLowerCase);
}
/**
* @return bool
*/
public function IsInbox()
{
return 'INBOX' === \strtoupper($this->sFullNameRaw) || \in_array('\inbox', $this->aFlagsLowerCase);
}
/**
* @param string $sName
* @param mixed $mData
*/
public function SetExtended($sName, $mData)
{
$this->aExtended[$sName] = $mData;
}
/**
* @param string $sName
* @return mixed
*/
public function GetExtended($sName)
{
return isset($this->aExtended[$sName]) ? $this->aExtended[$sName] : null;
}
}

View file

@ -0,0 +1,95 @@
<?php
namespace MailSo\Imap;
/**
* @category MailSo
* @package Imap
*/
class FolderInformation
{
/**
* @var string
*/
public $FolderName;
/**
* @var bool
*/
public $IsWritable;
/**
* @var array
*/
public $Flags;
/**
* @var array
*/
public $PermanentFlags;
/**
* @var int
*/
public $Exists;
/**
* @var int
*/
public $Recent;
/**
* @var string
*/
public $Uidvalidity;
/**
* @var int
*/
public $Unread;
/**
* @var string
*/
public $Uidnext;
/**
* @access private
*
* @param string $sFolderName
* @param bool $bIsWritable
*/
private function __construct($sFolderName, $bIsWritable)
{
$this->FolderName = $sFolderName;
$this->IsWritable = $bIsWritable;
$this->Exists = null;
$this->Recent = null;
$this->Flags = array();
$this->PermanentFlags = array();
$this->Unread = null;
$this->Uidnext = null;
}
/**
* @param string $sFolderName
* @param bool $bIsWritable
*
* @return \MailSo\Imap\FolderInformation
*/
public static function NewInstance($sFolderName, $bIsWritable)
{
return new self($sFolderName, $bIsWritable);
}
/**
* @param string $sFlag
*
* @return bool
*/
public function IsFlagSupported($sFlag)
{
return in_array('\\*', $this->PermanentFlags) || in_array($sFlag, $this->PermanentFlags);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,123 @@
<?php
namespace MailSo\Imap;
/**
* @category MailSo
* @package Imap
*/
class NamespaceResult
{
/**
* @var string
*/
private $sPersonal;
/**
* @var string
*/
private $sPersonalDelimiter;
/**
* @var string
*/
private $sOtherUser;
/**
* @var string
*/
private $sOtherUserDelimiter;
/**
* @var string
*/
private $sShared;
/**
* @var string
*/
private $sSharedDelimiter;
/**
* @access private
*/
private function __construct()
{
$this->sPersonal = '';
$this->sPersonalDelimiter = '';
$this->sOtherUser = '';
$this->sOtherUserDelimiter = '';
$this->sShared = '';
$this->sSharedDelimiter = '';
}
/**
* @return \MailSo\Imap\NamespaceResult
*/
public static function NewInstance()
{
return new self();
}
/**
* @param \MailSo\Imap\Response $oImapResponse
*
* @return \MailSo\Imap\NamespaceResult
*/
public function InitByImapResponse($oImapResponse)
{
if ($oImapResponse && $oImapResponse instanceof \MailSo\Imap\Response)
{
if (isset($oImapResponse->ResponseList[2][0]) &&
\is_array($oImapResponse->ResponseList[2][0]) &&
2 <= \count($oImapResponse->ResponseList[2][0]))
{
$this->sPersonal = $oImapResponse->ResponseList[2][0][0];
$this->sPersonalDelimiter = $oImapResponse->ResponseList[2][0][1];
$this->sPersonal = 'INBOX'.$this->sPersonalDelimiter === \substr(\strtoupper($this->sPersonal), 0, 6) ?
'INBOX'.$this->sPersonalDelimiter.\substr($this->sPersonal, 6) : $this->sPersonal;
}
if (isset($oImapResponse->ResponseList[3][0]) &&
\is_array($oImapResponse->ResponseList[3][0]) &&
2 <= \count($oImapResponse->ResponseList[3][0]))
{
$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;
}
/**
* @return string
*/
public function GetPersonalNamespace()
{
return $this->sPersonal;
}
/**
* @return string
*/
public function GetPersonalNamespaceDelimiter()
{
return $this->sPersonalDelimiter;
}
}

View file

@ -0,0 +1,67 @@
<?php
namespace MailSo\Imap;
/**
* @category MailSo
* @package Imap
*/
class Response
{
/**
* @var array
*/
public $ResponseList;
/**
* @var array | null
*/
public $OptionalResponse;
/**
* @var string
*/
public $StatusOrIndex;
/**
* @var string
*/
public $HumanReadable;
/**
* @var bool
*/
public $IsStatusResponse;
/**
* @var string
*/
public $ResponseType;
/**
* @var string
*/
public $Tag;
/**
* @access private
*/
private function __construct()
{
$this->ResponseList = array();
$this->OptionalResponse = null;
$this->StatusOrIndex = '';
$this->HumanReadable = '';
$this->IsStatusResponse = false;
$this->ResponseType = \MailSo\Imap\Enumerations\ResponseType::UNKNOWN;
$this->Tag = '';
}
/**
* @return \MailSo\Imap\Response
*/
public static function NewInstance()
{
return new self();
}
}

View file

@ -0,0 +1,104 @@
<?php
namespace MailSo\Imap;
/**
* @category MailSo
* @package Imap
*/
class SearchBuilder
{
/**
* @var array
*/
private $aList;
/**
* @access private
*/
private function __construct()
{
$this->Clear();
}
/**
* @return \MailSo\Imap\SearchBuilder
*/
public static function NewInstance()
{
return new self();
}
/**
* @return \MailSo\Imap\SearchBuilder
*/
public function Clear()
{
$this->aList = array();
return $this;
}
/**
* @param string $sName
* @param string $sValue = ''
*
* @return \MailSo\Imap\SearchBuilder
*/
public function AddAnd($sName, $sValue = '')
{
return $this->addCri('AND', $sName, $sValue);
}
/**
* @param string $sName
* @param string $sValue = ''
*
* @return \MailSo\Imap\SearchBuilder
*/
public function AddOr($sName, $sValue = '')
{
return $this->addCri('OR', $sName, $sValue);
}
/**
* @return string
*/
public function Complete()
{
$sResult = '';
foreach ($this->aList as $iIndex => $aItem)
{
$sResult = trim((0 < $iIndex && 'OR' === $aItem[0] ? $aItem[0] : '').
(0 === strlen($sResult) ? '' : ' ('.$sResult.')').' '.$aItem[1].
(0 < strlen($aItem[2]) ? ' '.$aItem[2] : ''));
}
if (0 === strlen($sResult))
{
$sResult = 'ALL';
}
return $sResult;
}
/**
* @return string
*/
public function __toString()
{
return $this->Complete();
}
/**
* @param string $sType
* @param string $sName
* @param string $sValue = ''
*
* @return \MailSo\Imap\SearchBuilder
*/
private function addCri($sType, $sName, $sValue = '')
{
$this->aList[] = array($sType, $sName, $sValue);
return $this;
}
}

View file

@ -0,0 +1,221 @@
<?php
namespace MailSo\Log;
/**
* @category MailSo
* @package Log
*/
abstract class Driver
{
/**
* @var string
*/
protected $sDatePattern;
/**
* @var string
*/
protected $sName;
/**
* @var array
*/
protected $aPrefixes;
/**
* @var bool
*/
protected $bTimePrefix;
/**
* @var bool
*/
protected $bTypedPrefix;
/**
* @var bool
*/
private $bWriteOnErrorOnly;
/**
* @var bool
*/
private $bFlushCache;
/**
* @var array
*/
private $aCache;
/**
* @access protected
*/
protected function __construct()
{
$this->sDatePattern = 'H:i:s';
$this->sName = 'INFO';
$this->bTimePrefix = true;
$this->bTypedPrefix = true;
$this->bWriteOnErrorOnly = false;
$this->bFlushCache = false;
$this->aCache = array();
$this->aPrefixes = array(
\MailSo\Log\Enumerations\Type::INFO => '[DATA]',
\MailSo\Log\Enumerations\Type::SECURE => '[SECURE]',
\MailSo\Log\Enumerations\Type::NOTE => '[NOTE]',
\MailSo\Log\Enumerations\Type::TIME => '[TIME]',
\MailSo\Log\Enumerations\Type::MEMORY => '[MEMORY]',
\MailSo\Log\Enumerations\Type::NOTICE => '[NOTICE]',
\MailSo\Log\Enumerations\Type::WARNING => '[WARNING]',
\MailSo\Log\Enumerations\Type::ERROR => '[ERROR]',
);
}
/**
* @return \MailSo\Log\Driver
*/
public function DisableTimePrefix()
{
$this->bTimePrefix = false;
return $this;
}
/**
* @param bool $bValue
*
* @return \MailSo\Log\Driver
*/
public function WriteOnErrorOnly($bValue)
{
$this->bWriteOnErrorOnly = !!$bValue;
return $this;
}
/**
* @return \MailSo\Log\Driver
*/
public function DisableTypedPrefix()
{
$this->bTypedPrefix = false;
return $this;
}
/**
* @param string|array $sDesc
* @return bool
*/
abstract protected function writeImplementation($mDesc);
/**
* @return bool
*/
protected function writeEmptyLineImplementation()
{
return $this->writeImplementation('');
}
/**
* @param string $sTimePrefix
* @param string $sDesc
* @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO
* @param array $sName = ''
*
* @return string
*/
protected function loggerLineImplementation($sTimePrefix, $sDesc,
$iDescType = \MailSo\Log\Enumerations\Type::INFO, $sName = '')
{
return ($this->bTimePrefix ? '['.$sTimePrefix.'] ' : '').
($this->bTypedPrefix ? $this->getTypedPrefix($iDescType, $sName) : '').
$sDesc;
}
/**
* @return bool
*/
protected function clearImplementation()
{
return true;
}
/**
* @return string
*/
protected function getTimeWithMicroSec()
{
$aMicroTimeItems = \explode(' ', \microtime());
return \gmdate($this->sDatePattern, $aMicroTimeItems[1]).'.'.
\str_pad((int) ($aMicroTimeItems[0] * 1000), 3, '0', STR_PAD_LEFT);
}
/**
* @param int $iDescType
* @param string $sName = ''
*
* @return string
*/
protected function getTypedPrefix($iDescType, $sName = '')
{
$sName = 0 < \strlen($sName) ? $sName : $this->sName;
return isset($this->aPrefixes[$iDescType]) ? $sName.$this->aPrefixes[$iDescType].': ' : '';
}
/**
* @final
* @param string $sDesc
* @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO
* @param array $sName = ''
*
* @return bool
*/
final public function Write($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO, $sName = '')
{
if ($this->bWriteOnErrorOnly && !$this->bFlushCache)
{
$this->aCache[] = $this->loggerLineImplementation($this->getTimeWithMicroSec(), $sDesc, $iDescType, $sName);
if (\in_array($iDescType, array(
\MailSo\Log\Enumerations\Type::NOTICE,
\MailSo\Log\Enumerations\Type::WARNING,
\MailSo\Log\Enumerations\Type::ERROR
)))
{
$this->bFlushCache = true;
return $this->writeImplementation($this->aCache);
}
return true;
}
return $this->writeImplementation(
$this->loggerLineImplementation($this->getTimeWithMicroSec(), $sDesc, $iDescType, $sName));
}
/**
* @final
* @return bool
*/
final public function Clear()
{
return $this->clearImplementation();
}
/**
* @final
* @return void
*/
final public function WriteEmptyLine()
{
if ($this->bWriteOnErrorOnly && !$this->bFlushCache)
{
$this->aCache[] = '';
}
else
{
$this->writeEmptyLineImplementation();
}
}
}

View file

@ -0,0 +1,74 @@
<?php
namespace MailSo\Log\Drivers;
/**
* @category MailSo
* @package Log
* @subpackage Drivers
*/
class Callback extends \MailSo\Log\Driver
{
/**
* @var mixed
*/
private $fWriteCallback;
/**
* @var mixed
*/
private $fClearCallback;
/**
* @access protected
*
* @param mixed $fWriteCallback
* @param mixed $fClearCallback
*/
protected function __construct($fWriteCallback, $fClearCallback)
{
parent::__construct();
$this->fWriteCallback = \is_callable($fWriteCallback) ? $fWriteCallback : null;
$this->fClearCallback = \is_callable($fClearCallback) ? $fClearCallback : null;
}
/**
* @param mixed $fWriteCallback
* @param mixed $fClearCallback = null
*
* @return \MailSo\Log\Drivers\Callback
*/
public static function NewInstance($fWriteCallback, $fClearCallback = null)
{
return new self($fWriteCallback, $fClearCallback);
}
/**
* @param string|array $sDesc
*
* @return bool
*/
protected function writeImplementation($sDesc)
{
if ($this->fWriteCallback)
{
\call_user_func_array($this->fWriteCallback, array($sDesc));
}
return true;
}
/**
* @return bool
*/
protected function clearImplementation()
{
if ($this->fClearCallback)
{
\call_user_func($this->fClearCallback);
}
return true;
}
}

View file

@ -0,0 +1,87 @@
<?php
namespace MailSo\Log\Drivers;
/**
* @category MailSo
* @package Log
* @subpackage Drivers
*/
class File extends \MailSo\Log\Driver
{
/**
* @var string
*/
private $sLoggerFileName;
/**
* @var string
*/
private $sCrLf;
/**
* @access protected
*
* @param string $sLoggerFileName
* @param string $sCrLf = "\r\n"
*/
protected function __construct($sLoggerFileName, $sCrLf = "\r\n")
{
parent::__construct();
$this->sLoggerFileName = $sLoggerFileName;
$this->sCrLf = $sCrLf;
}
/**
* @param string $sLoggerFileName
*/
public function SetLoggerFileName($sLoggerFileName)
{
$this->sLoggerFileName = $sLoggerFileName;
}
/**
* @param string $sLoggerFileName
* @param string $sCrLf = "\r\n"
*
* @return \MailSo\Log\Drivers\File
*/
public static function NewInstance($sLoggerFileName, $sCrLf = "\r\n")
{
return new self($sLoggerFileName, $sCrLf);
}
/**
* @param string|array $mDesc
*
* @return bool
*/
protected function writeImplementation($mDesc)
{
return $this->writeToLogFile($mDesc);
}
/**
* @return bool
*/
protected function clearImplementation()
{
return \unlink($this->sLoggerFileName);
}
/**
* @param string|array $mDesc
*
* @return bool
*/
private function writeToLogFile($mDesc)
{
if (is_array($mDesc))
{
$mDesc = \implode($this->sCrLf, $mDesc);
}
return \error_log($mDesc.$this->sCrLf, 3, $this->sLoggerFileName);
}
}

View file

@ -0,0 +1,85 @@
<?php
namespace MailSo\Log\Drivers;
/**
* @category MailSo
* @package Log
* @subpackage Drivers
*/
class Inline extends \MailSo\Log\Driver
{
/**
* @var string
*/
private $sNewLine;
/**
* @var bool
*/
private $bHtmlEncodeSpecialChars;
/**
* @access protected
*
* @param string $sNewLine = "\r\n"
* @param bool $bHtmlEncodeSpecialChars = false
*/
protected function __construct($sNewLine = "\r\n", $bHtmlEncodeSpecialChars = false)
{
parent::__construct();
$this->sNewLine = $sNewLine;
$this->bHtmlEncodeSpecialChars = $bHtmlEncodeSpecialChars;
}
/**
* @param string $sNewLine = "\r\n"
* @param bool $bHtmlEncodeSpecialChars = false
*
* @return \MailSo\Log\Drivers\Inline
*/
public static function NewInstance($sNewLine = "\r\n", $bHtmlEncodeSpecialChars = false)
{
return new self($sNewLine, $bHtmlEncodeSpecialChars);
}
/**
* @param string $mDesc
*
* @return bool
*/
protected function writeImplementation($mDesc)
{
if (is_array($mDesc))
{
if ($this->bHtmlEncodeSpecialChars)
{
$mDesc = array_map(function ($sItem) {
$sItem = \htmlspecialchars($mDesc);
}, $mDesc);
}
$mDesc = \implode($this->sNewLine, $mDesc);
}
else
{
echo ($this->bHtmlEncodeSpecialChars) ? \htmlspecialchars($mDesc).$this->sNewLine : $mDesc.$this->sNewLine;
}
return true;
}
/**
* @return bool
*/
protected function clearImplementation()
{
if (\defined('PHP_SAPI') && 'cli' === PHP_SAPI)
{
\system('clear');
}
return true;
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace MailSo\Log\Enumerations;
/**
* @category MailSo
* @package Log
* @subpackage Enumerations
*/
class Type
{
const INFO = 0;
const NOTICE = 1;
const WARNING = 2;
const ERROR = 3;
const SECURE = 4;
const NOTE = 5;
const TIME = 6;
const MEMORY = 7;
}

View file

@ -0,0 +1,214 @@
<?php
namespace MailSo\Log;
/**
* @category MailSo
* @package Log
*/
class Logger extends \MailSo\Base\Collection
{
/**
* @var bool
*/
private $bUsed;
/**
* @var array
*/
private $aForbiddenTypes;
/**
* @var array
*/
private $aSecretWords;
/**
* @access protected
*/
protected function __construct()
{
parent::__construct();
$this->bUsed = false;
$this->aForbiddenTypes = array();
$this->aSecretWords = array();
\register_shutdown_function(array(&$this, '__loggerShutDown'));
}
/**
* @return \MailSo\Log\Logger
*/
public static function NewInstance()
{
return new self();
}
/**
* @staticvar \MailSo\Log\Logger $oInstance;
*
* @return \MailSo\Log\Logger
*/
public static function SingletonInstance()
{
static $oInstance = null;
if (null === $oInstance)
{
$oInstance = self::NewInstance();
}
return $oInstance;
}
/**
* @return bool
*/
public function IsEnabled()
{
return 0 < $this->Count();
}
/**
* @param string $sWord
* @return bool
*/
public function AddSecret($sWord)
{
if (0 < \strlen(\trim($sWord)))
{
$this->aSecretWords[] = $sWord;
$this->aSecretWords = array_unique($this->aSecretWords);
}
}
/**
* @param int $iDescType
*
* @return \MailSo\Log\Logger
*/
public function AddForbiddenType($iType)
{
$this->aForbiddenTypes[$iType] = true;
return $this;
}
/**
* @param int $iDescType
*
* @return \MailSo\Log\Logger
*/
public function RemoveForbiddenType($iType)
{
$this->aForbiddenTypes[$iType] = false;
return $this;
}
/**
* @return void
*/
public function __loggerShutDown()
{
if ($this->bUsed)
{
$aStatistic = \MailSo\Base\Loader::Statistic();
// $this->WriteDump($aStatistic, \MailSo\Log\Enumerations\Type::INFO);
if (\is_array($aStatistic) && isset($aStatistic['php']['memory_get_peak_usage']))
{
$this->Write('Memory peak usage: '.$aStatistic['php']['memory_get_peak_usage'],
\MailSo\Log\Enumerations\Type::MEMORY);
}
}
}
/**
* @return bool
*/
public function WriteEmptyLine()
{
$iResult = 1;
$aLoggers =& $this->GetAsArray();
foreach ($aLoggers as /* @var $oLogger \MailSo\Log\Driver */ &$oLogger)
{
$iResult &= $oLogger->WriteEmptyLine();
}
return (bool) $iResult;
}
/**
* @param string $sDesc
* @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO
* @param string $sName = ''
* @param bool $bSearchWords = false
*
* @return bool
*/
public function Write($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO, $sName = '', $bSearchWords = false)
{
if (isset($this->aForbiddenTypes[$iDescType]) && true === $this->aForbiddenTypes[$iDescType])
{
return true;
}
$this->bUsed = true;
$oLogger = null;
$aLoggers = array();
$iResult = 1;
if ($bSearchWords && 0 < \count($this->aSecretWords))
{
$sDesc = \str_replace($this->aSecretWords, '*******', $sDesc);
}
$aLoggers =& $this->GetAsArray();
foreach ($aLoggers as /* @var $oLogger \MailSo\Log\Driver */ $oLogger)
{
$iResult &= $oLogger->Write($sDesc, $iDescType, $sName);
}
return (bool) $iResult;
}
/**
* @param mixed $oValue
* @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO
* @param string $sName = ''
* @param bool $bSearchSecretWords = false
*
* @return bool
*/
public function WriteDump($oValue, $iDescType = \MailSo\Log\Enumerations\Type::INFO, $sName = '', $bSearchSecretWords = false)
{
return $this->Write(\print_r($oValue, true), $iDescType, $sName, $bSearchSecretWords);
}
/**
* @param \Exception $oException
* @param int $iDescType = \MailSo\Log\Enumerations\Type::NOTICE
* @param string $sName = ''
* @param bool $bSearchSecretWords = true
*
* @return bool
*/
public function WriteException($oException, $iDescType = \MailSo\Log\Enumerations\Type::NOTICE, $sName = '', $bSearchSecretWords = true)
{
if ($oException instanceof \Exception)
{
if (isset($oException->__LOGINNED__))
{
return true;
}
$oException->__LOGINNED__ = true;
return $this->Write((string) $oException, $iDescType, $sName, $bSearchSecretWords);
}
return false;
}
}

View file

@ -0,0 +1,182 @@
<?php
namespace MailSo\Mail;
/**
* @category MailSo
* @package Mail
*/
class Attachment
{
/**
* @var string
*/
private $sFolder;
/**
* @var int
*/
private $iUid;
/**
* @var \MailSo\Imap\BodyStructure
*/
private $oBodyStructure;
/**
* @access private
*/
private function __construct()
{
$this->Clear();
}
/**
* @return \MailSo\Mail\Attachment
*/
public function Clear()
{
$this->sFolder = '';
$this->iUid = 0;
$this->oBodyStructure = null;
return $this;
}
/**
* @return string
*/
public function Folder()
{
return $this->sFolder;
}
/**
* @return int
*/
public function Uid()
{
return $this->iUid;
}
/**
* @return string
*/
public function MimeIndex()
{
return $this->oBodyStructure ? $this->oBodyStructure->PartID() : '';
}
/**
* @param bool $bCalculateOnEmpty = false
*
* @return string
*/
public function FileName($bCalculateOnEmpty = false)
{
$sFileName = '';
if ($this->oBodyStructure)
{
$sFileName = $this->oBodyStructure->FileName();
if ($bCalculateOnEmpty && 0 === \strlen(trim($sFileName)))
{
$sMimeType = \strtolower(\trim($this->MimeType()));
if ('message/rfc822' === $sMimeType)
{
$sFileName = 'message'.$this->MimeIndex().'.eml';
}
else if ('text/calendar' === $sMimeType)
{
$sFileName = 'calendar'.$this->MimeIndex().'.ics';
}
else if (0 < \strlen($sMimeType))
{
$sFileName = \str_replace('/', $this->MimeIndex().'.', $sMimeType);
}
}
}
return $sFileName;
}
/**
* @return string
*/
public function MimeType()
{
return $this->oBodyStructure ? $this->oBodyStructure->ContentType() : '';
}
/**
* @return string
*/
public function ContentTransferEncoding()
{
return $this->oBodyStructure ? $this->oBodyStructure->MailEncodingName() : '';
}
/**
* @return int
*/
public function EncodedSize()
{
return $this->oBodyStructure ? $this->oBodyStructure->Size() : 0;
}
/**
* @return int
*/
public function EstimatedSize()
{
return $this->oBodyStructure ? $this->oBodyStructure->EstimatedSize() : 0;
}
/**
* @return string
*/
public function Cid()
{
return $this->oBodyStructure ? $this->oBodyStructure->ContentID() : '';
}
/**
* @return bool
*/
public function IsInline()
{
return $this->oBodyStructure ? $this->oBodyStructure->IsInline() : false;
}
/**
* @return \MailSo\Mail\Attachment
*/
public static function NewInstance()
{
return new self();
}
/**
* @param string $sFolder
* @param int $iUid
* @param \MailSo\Imap\BodyStructure $oBodyStructure
* @return \MailSo\Mail\Attachment
*/
public static function NewBodyStructureInstance($sFolder, $iUid, $oBodyStructure)
{
return self::NewInstance()->InitByBodyStructure($sFolder, $iUid, $oBodyStructure);
}
/**
* @param string $sFolder
* @param int $iUid
* @param \MailSo\Imap\BodyStructure $oBodyStructure
* @return \MailSo\Mail\Attachment
*/
public function InitByBodyStructure($sFolder, $iUid, $oBodyStructure)
{
$this->sFolder = $sFolder;
$this->iUid = $iUid;
$this->oBodyStructure = $oBodyStructure;
return $this;
}
}

View file

@ -0,0 +1,50 @@
<?php
namespace MailSo\Mail;
/**
* @category MailSo
* @package Mail
*/
class AttachmentCollection extends \MailSo\Base\Collection
{
/**
* @access protected
*/
protected function __construct()
{
parent::__construct();
}
/**
* @return \MailSo\Mail\AttachmentCollection
*/
public static function NewInstance()
{
return new self();
}
/**
* @return int
*/
public function InlineCount()
{
$aList = $this->FilterList(function ($oAttachment) {
return $oAttachment && $oAttachment->IsInline();
});
return \is_array($aList) ? \count($aList) : 0;
}
/**
* @return int
*/
public function NonInlineCount()
{
$aList = $this->FilterList(function ($oAttachment) {
return $oAttachment && !$oAttachment->IsInline();
});
return \is_array($aList) ? \count($aList) : 0;
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Mail\Exceptions;
/**
* @category MailSo
* @package Mail
* @subpackage Exceptions
*/
class Exception extends \MailSo\Base\Exceptions\Exception {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Mail\Exceptions;
/**
* @category MailSo
* @package Mail
* @subpackage Exceptions
*/
class NonEmptyFolder extends \MailSo\Mail\Exceptions\RuntimeException {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Mail\Exceptions;
/**
* @category MailSo
* @package Mail
* @subpackage Exceptions
*/
class RuntimeException extends \MailSo\Mail\Exceptions\Exception {}

View file

@ -0,0 +1,305 @@
<?php
namespace MailSo\Mail;
/**
* @category MailSo
* @package Mail
*/
class Folder
{
/**
* @var string
*/
private $sParentFullNameRaw;
/**
* @var int
*/
private $iNestingLevel;
/**
* @var bool
*/
private $bExisten;
/**
* @var bool
*/
private $bSubscribed;
/**
* @var \MailSo\Imap\Folder
*/
private $oImapFolder;
/**
* @var \MailSo\Mail\FolderCollection
*/
private $oSubFolders;
/**
* @access private
*
* @param \MailSo\Imap\Folder $oImapFolder
* @param bool $bSubscribed = true
* @param bool $bExisten = true
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
private function __construct($oImapFolder, $bSubscribed = true, $bExisten = true)
{
if ($oImapFolder instanceof \MailSo\Imap\Folder)
{
$this->oImapFolder = $oImapFolder;
$this->oSubFolders = null;
$aNames = \explode($this->oImapFolder->Delimiter(), $this->oImapFolder->FullNameRaw());
$this->iNestingLevel = \count($aNames);
$this->sParentFullNameRaw = '';
if (1 < $this->iNestingLevel)
{
\array_pop($aNames);
$this->sParentFullNameRaw = \implode($this->oImapFolder->Delimiter(), $aNames);
}
$this->bSubscribed = $bSubscribed;
$this->bExisten = $bExisten;
}
else
{
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
}
}
/**
* @param \MailSo\Imap\Folder $oImapFolder
* @param bool $bSubscribed = true
* @param bool $bExisten = true
*
* @return \MailSo\Mail\Folder
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public static function NewInstance($oImapFolder, $bSubscribed = true, $bExisten = true)
{
return new self($oImapFolder, $bSubscribed, $bExisten);
}
/**
* @param string $sFullNameRaw
* @param string $sDelimiter
*
* @return \MailSo\Mail\Folder
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public static function NewNonExistenInstance($sFullNameRaw, $sDelimiter)
{
return self::NewInstance(
\MailSo\Imap\Folder::NewInstance($sFullNameRaw, $sDelimiter, array('\NoSelect')), true, false);
}
/**
* @return string
*/
public function Name()
{
return \MailSo\Base\Utils::ConvertEncoding($this->NameRaw(),
\MailSo\Base\Enumerations\Charset::UTF_7_IMAP,
\MailSo\Base\Enumerations\Charset::UTF_8);
}
/**
* @return string
*/
public function FullName()
{
return \MailSo\Base\Utils::ConvertEncoding($this->FullNameRaw(),
\MailSo\Base\Enumerations\Charset::UTF_7_IMAP,
\MailSo\Base\Enumerations\Charset::UTF_8);
}
/**
* @return string
*/
public function NameRaw()
{
return $this->oImapFolder->NameRaw();
}
/**
* @return string
*/
public function FullNameRaw()
{
return $this->oImapFolder->FullNameRaw();
}
/**
* @return string
*/
public function ParentFullName()
{
return \MailSo\Base\Utils::ConvertEncoding($this->sParentFullNameRaw,
\MailSo\Base\Enumerations\Charset::UTF_7_IMAP,
\MailSo\Base\Enumerations\Charset::UTF_8);
}
/**
* @return string
*/
public function ParentFullNameRaw()
{
return $this->sParentFullNameRaw;
}
/**
* @return string
*/
public function Delimiter()
{
return $this->oImapFolder->Delimiter();
}
/**
* @return array
*/
public function Flags()
{
return $this->oImapFolder->Flags();
}
/**
* @return array
*/
public function FlagsLowerCase()
{
return $this->oImapFolder->FlagsLowerCase();
}
/**
* @param bool $bCreateIfNull = false
* @return \MailSo\Mail\FolderCollection
*/
public function SubFolders($bCreateIfNull = false)
{
if ($bCreateIfNull && !$this->oSubFolders)
{
$this->oSubFolders = FolderCollection::NewInstance();
}
return $this->oSubFolders;
}
/**
* @return bool
*/
public function HasSubFolders()
{
return $this->oSubFolders && 0 < $this->oSubFolders->Count();
}
/**
* @return bool
*/
public function HasVisibleSubFolders()
{
$sList = array();
if ($this->oSubFolders)
{
$sList = $this->oSubFolders->FilterList(function (\MailSo\Mail\Folder $oFolder) {
return $oFolder->IsSubscribed();
});
}
return 0 < \count($sList);
}
/**
* @return bool
*/
public function IsSubscribed()
{
return $this->bSubscribed;
}
/**
* @return bool
*/
public function IsExisten()
{
return $this->bExisten;
}
/**
* @return bool
*/
public function IsSelectable()
{
return $this->IsExisten() && $this->oImapFolder->IsSelectable();
}
/**
* @return mixed
*/
public function Status()
{
return $this->oImapFolder->GetExtended('STATUS');
}
/**
* @return bool
*/
public function IsInbox()
{
return $this->oImapFolder->IsInbox();
}
/**
* @return int
*/
public function GetFolderXListType()
{
$aFlags = $this->oImapFolder->FlagsLowerCase();
$iXListType = \MailSo\Imap\Enumerations\FolderType::USER;
if (\is_array($aFlags))
{
switch (true)
{
case \in_array('\inbox', $aFlags):
$iXListType = \MailSo\Imap\Enumerations\FolderType::INBOX;
break;
case \in_array('\sent', $aFlags):
$iXListType = \MailSo\Imap\Enumerations\FolderType::SENT;
break;
case \in_array('\drafts', $aFlags):
$iXListType = \MailSo\Imap\Enumerations\FolderType::DRAFTS;
break;
case \in_array('\spam', $aFlags):
$iXListType = \MailSo\Imap\Enumerations\FolderType::SPAM;
break;
case \in_array('\bin', $aFlags):
case \in_array('\trash', $aFlags):
$iXListType = \MailSo\Imap\Enumerations\FolderType::TRASH;
break;
case \in_array('\important', $aFlags):
$iXListType = \MailSo\Imap\Enumerations\FolderType::IMPORTANT;
break;
case \in_array('\starred', $aFlags):
$iXListType = \MailSo\Imap\Enumerations\FolderType::STARRED;
break;
case \in_array('\all', $aFlags):
case \in_array('\archive', $aFlags):
case \in_array('\allmail', $aFlags):
$iXListType = \MailSo\Imap\Enumerations\FolderType::ALLMAIL;
break;
}
}
return $iXListType;
}
}

View file

@ -0,0 +1,200 @@
<?php
namespace MailSo\Mail;
/**
* @category MailSo
* @package Mail
*/
class FolderCollection extends \MailSo\Base\Collection
{
/**
* @var string
*/
private $sNamespace;
/**
* @var string
*/
public $FoldersHash;
/**
* @var array
*/
public $SystemFolders;
/**
* @access protected
*/
protected function __construct()
{
parent::__construct();
$this->sNamespace = '';
$this->FoldersHash = '';
$this->SystemFolders = array();
}
/**
* @return \MailSo\Mail\FolderCollection
*/
public static function NewInstance()
{
return new self();
}
/**
* @param string $sFullNameRaw
*
* @return \MailSo\Mail\Folder|null
*/
public function &GetByFullNameRaw($sFullNameRaw)
{
$mResult = null;
foreach ($this->aItems as /* @var $oFolder \MailSo\Mail\Folder */ $oFolder)
{
if ($oFolder->FullNameRaw() === $sFullNameRaw)
{
$mResult = $oFolder;
break;
}
}
return $mResult;
}
/**
* @return string
*/
public function GetNamespace()
{
return $this->sNamespace;
}
/**
* @param string $sNamespace
*
* @return \MailSo\Mail\FolderCollection
*/
public function SetNamespace($sNamespace)
{
$this->sNamespace = $sNamespace;
return $this;
}
/**
* @param array $aUnsortedMailFolders
*
* @return void
*/
public function InitByUnsortedMailFolderArray($aUnsortedMailFolders)
{
$this->Clear();
$aSortedByLenImapFolders = array();
foreach ($aUnsortedMailFolders as /* @var $oMailFolder \MailSo\Mail\Folder */ &$oMailFolder)
{
$aSortedByLenImapFolders[$oMailFolder->FullNameRaw()] =& $oMailFolder;
unset($oMailFolder);
}
unset($aUnsortedMailFolders);
$aAddedFolders = array();
foreach ($aSortedByLenImapFolders as /* @var $oMailFolder \MailSo\Mail\Folder */ $oMailFolder)
{
$sDelimiter = $oMailFolder->Delimiter();
$aFolderExplode = \explode($sDelimiter, $oMailFolder->FullNameRaw());
if (1 < \count($aFolderExplode))
{
\array_pop($aFolderExplode);
$sNonExistenFolderFullNameRaw = '';
foreach ($aFolderExplode as $sFolderExplodeItem)
{
$sNonExistenFolderFullNameRaw .= (0 < \strlen($sNonExistenFolderFullNameRaw))
? $sDelimiter.$sFolderExplodeItem : $sFolderExplodeItem;
if (!isset($aSortedByLenImapFolders[$sNonExistenFolderFullNameRaw]))
{
$aAddedFolders[$sNonExistenFolderFullNameRaw] =
Folder::NewNonExistenInstance($sNonExistenFolderFullNameRaw, $sDelimiter);
}
}
}
}
$aSortedByLenImapFolders = \array_merge($aSortedByLenImapFolders, $aAddedFolders);
unset($aAddedFolders);
\uasort($aSortedByLenImapFolders, function ($oFolderA, $oFolderB) {
return \strnatcmp($oFolderA->FullNameRaw(), $oFolderB->FullNameRaw());
});
foreach ($aSortedByLenImapFolders as /* @var $oMailFolder \MailSo\Mail\Folder */ &$oMailFolder)
{
$this->AddWithPositionSearch($oMailFolder);
unset($oMailFolder);
}
unset($aSortedByLenImapFolders);
}
/**
* @param \MailSo\Mail\Folder $oMailFolder
*
* @return bool
*/
public function AddWithPositionSearch($oMailFolder)
{
$oItemFolder = null;
$bIsAdded = false;
$aList =& $this->GetAsArray();
foreach ($aList as /* @var $oItemFolder \MailSo\Mail\Folder */ $oItemFolder)
{
if ($oMailFolder instanceof \MailSo\Mail\Folder &&
0 === \strpos($oMailFolder->FullNameRaw(), $oItemFolder->FullNameRaw().$oItemFolder->Delimiter()))
{
if ($oItemFolder->SubFolders(true)->AddWithPositionSearch($oMailFolder))
{
$bIsAdded = true;
}
break;
}
}
if (!$bIsAdded && $oMailFolder instanceof \MailSo\Mail\Folder)
{
$bIsAdded = true;
$this->Add($oMailFolder);
}
return $bIsAdded;
}
/**
* @param callable $fCallback
*
* @return void
*/
public function SortByCallback($fCallback)
{
if (\is_callable($fCallback))
{
$aList =& $this->GetAsArray();
\usort($aList, $fCallback);
foreach ($aList as &$oItemFolder)
{
if ($oItemFolder->HasSubFolders())
{
$oItemFolder->SubFolders()->SortByCallback($fCallback);
}
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,739 @@
<?php
namespace MailSo\Mail;
/**
* @category MailSo
* @package Mail
*/
class Message
{
/**
* @var string
*/
private $sFolder;
/**
* @var int
*/
private $iUid;
/**
* @var string
*/
private $sSubject;
/**
* @var string
*/
private $sMessageId;
/**
* @var string
*/
private $sContentType;
/**
* @var int
*/
private $iSize;
/**
* @var int
*/
private $iInternalTimeStampInUTC;
/**
* @var int
*/
private $iHeaderTimeStampInUTC;
/**
* @var string
*/
private $sHeaderDate;
/**
* @var array
*/
private $aFlags;
/**
* @var array
*/
private $aFlagsLowerCase;
/**
* @var \MailSo\Mime\EmailCollection
*/
private $oFrom;
/**
* @var \MailSo\Mime\EmailCollection
*/
private $oSender;
/**
* @var \MailSo\Mime\EmailCollection
*/
private $oReplyTo;
/**
* @var \MailSo\Mime\EmailCollection
*/
private $oTo;
/**
* @var \MailSo\Mime\EmailCollection
*/
private $oCc;
/**
* @var \MailSo\Mime\EmailCollection
*/
private $oBcc;
/**
* @var string
*/
private $sInReplyTo;
/**
* @var string
*/
private $sPlain;
/**
* @var string
*/
private $sHtml;
/**
* @var \MailSo\Mail\AttachmentCollection
*/
private $oAttachments;
/**
* @var array
*/
private $aDraftInfo;
/**
* @var string
*/
private $sReferences;
/**
* @var int
*/
private $iSensitivity;
/**
* @var int
*/
private $iPriority;
/**
* @var string
*/
private $sReadingConfirmation;
/**
* @var array
*/
private $aThreads;
/**
* @var int
*/
private $iParentThread;
/**
* @var int
*/
private $iThreadsLen;
/**
* @access private
*/
private function __construct()
{
$this->Clear();
}
/**
* @return \MailSo\Mail\Message
*/
public function Clear()
{
$this->sFolder = '';
$this->iUid = 0;
$this->sSubject = '';
$this->sMessageId = '';
$this->sContentType = '';
$this->iSize = 0;
$this->iInternalTimeStampInUTC = 0;
$this->iHeaderTimeStampInUTC = 0;
$this->sHeaderDate = '';
$this->aFlags = array();
$this->aFlagsLowerCase = array();
$this->oFrom = null;
$this->oSender = null;
$this->oReplyTo = null;
$this->oTo = null;
$this->oCc = null;
$this->oBcc = null;
$this->sPlain = '';
$this->sHtml = '';
$this->oAttachments = null;
$this->aDraftInfo = null;
$this->sInReplyTo = '';
$this->sReferences = '';
$this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::NOTHING;
$this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::NORMAL;
$this->sReadingConfirmation = '';
$this->aThreads = array();
$this->iThreadsLen = 0;
$this->iParentThread = 0;
return $this;
}
/**
* @return \MailSo\Mail\Message
*/
public static function NewInstance()
{
return new self();
}
/**
* @return string
*/
public function Plain()
{
return $this->sPlain;
}
/**
* @return string
*/
public function Html()
{
return $this->sHtml;
}
/**
* @param string $sHtml
*
* @retun void
*/
public function SetHtml($sHtml)
{
$this->sHtml = $sHtml;
}
/**
* @return string
*/
public function Folder()
{
return $this->sFolder;
}
/**
* @return int
*/
public function Uid()
{
return $this->iUid;
}
/**
* @return string
*/
public function MessageId()
{
return $this->sMessageId;
}
/**
* @return string
*/
public function Subject()
{
return $this->sSubject;
}
/**
* @return string
*/
public function ContentType()
{
return $this->sContentType;
}
/**
* @return int
*/
public function Size()
{
return $this->iSize;
}
/**
* @return int
*/
public function InternalTimeStampInUTC()
{
return $this->iInternalTimeStampInUTC;
}
/**
* @return int
*/
public function HeaderTimeStampInUTC()
{
return $this->iHeaderTimeStampInUTC;
}
/**
* @return string
*/
public function HeaderDate()
{
return $this->sHeaderDate;
}
/**
* @return array
*/
public function Flags()
{
return $this->aFlags;
}
/**
* @return array
*/
public function FlagsLowerCase()
{
return $this->aFlagsLowerCase;
}
/**
* @return \MailSo\Mime\EmailCollection
*/
public function From()
{
return $this->oFrom;
}
/**
* @return int
*/
public function Sensitivity()
{
return $this->iSensitivity;
}
/**
* @return int
*/
public function Priority()
{
return $this->iPriority;
}
/**
* @return \MailSo\Mime\EmailCollection
*/
public function Sender()
{
return $this->oSender;
}
/**
* @return \MailSo\Mime\EmailCollection
*/
public function ReplyTo()
{
return $this->oReplyTo;
}
/**
* @return \MailSo\Mime\EmailCollection
*/
public function To()
{
return $this->oTo;
}
/**
* @return \MailSo\Mime\EmailCollection
*/
public function Cc()
{
return $this->oCc;
}
/**
* @return \MailSo\Mime\EmailCollection
*/
public function Bcc()
{
return $this->oBcc;
}
/**
* @return \MailSo\Mail\AttachmentCollection
*/
public function Attachments()
{
return $this->oAttachments;
}
/**
* @return string
*/
public function InReplyTo()
{
return $this->sInReplyTo;
}
/**
* @return string
*/
public function References()
{
return $this->sReferences;
}
/**
* @return string
*/
public function ReadingConfirmation()
{
return $this->sReadingConfirmation;
}
/**
* @return array | null
*/
public function DraftInfo()
{
return $this->aDraftInfo;
}
/**
* @return array
*/
public function Threads()
{
return $this->aThreads;
}
/**
* @param array $aThreads
*/
public function SetThreads($aThreads)
{
$this->aThreads = \is_array($aThreads) ? $aThreads : array();
}
/**
* @return int
*/
public function ThreadsLen()
{
return $this->iThreadsLen;
}
/**
* @param int $iThreadsLen
*/
public function SetThreadsLen($iThreadsLen)
{
$this->iThreadsLen = $iThreadsLen;
}
/**
* @return int
*/
public function ParentThread()
{
return $this->iParentThread;
}
/**
* @param int $iParentThread
*/
public function SetParentThread($iParentThread)
{
$this->iParentThread = $iParentThread;
}
/**
* @param string $sFolder
* @param \MailSo\Imap\FetchResponse $oFetchResponse
* @param \MailSo\Imap\BodyStructure $oBodyStructure = null
*
* @return \MailSo\Mail\Message
*/
public static function NewFetchResponseInstance($sFolder, $oFetchResponse, $oBodyStructure = null)
{
return self::NewInstance()->InitByFetchResponse($sFolder, $oFetchResponse, $oBodyStructure);
}
/**
* @param string $sFolder
* @param \MailSo\Imap\FetchResponse $oFetchResponse
* @param \MailSo\Imap\BodyStructure $oBodyStructure = null
*
* @return \MailSo\Mail\Message
*/
public function InitByFetchResponse($sFolder, $oFetchResponse, $oBodyStructure = null)
{
if (!$oBodyStructure)
{
$oBodyStructure = $oFetchResponse->GetFetchBodyStructure();
}
$aTextParts = $oBodyStructure ? $oBodyStructure->SearchHtmlOrPlainParts() : array();
$sUid = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::UID);
$sSize = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::RFC822_SIZE);
$sInternalDate = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::INTERNALDATE);
$aFlags = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::FLAGS);
$this->sFolder = $sFolder;
$this->iUid = \is_numeric($sUid) ? (int) $sUid : 0;
$this->iSize = \is_numeric($sSize) ? (int) $sSize : 0;
$this->aFlags = \is_array($aFlags) ? $aFlags : array();
$this->aFlagsLowerCase = \array_map('strtolower', $this->aFlags);
$this->iInternalTimeStampInUTC =
\MailSo\Base\DateTimeHelper::ParseInternalDateString($sInternalDate);
$sCharset = $oBodyStructure ? $oBodyStructure->SearchCharset() : '';
$sHeaders = $oFetchResponse->GetHeaderFieldsValue();
if (0 < \strlen($sHeaders))
{
$oHeaders = \MailSo\Mime\HeaderCollection::NewInstance()->Parse($sHeaders);
$sContentTypeCharset = $oHeaders->ParameterValue(
\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
\MailSo\Mime\Enumerations\Parameter::CHARSET
);
if (0 < \strlen($sContentTypeCharset))
{
$sCharset = $sContentTypeCharset;
}
if (0 < \strlen($sCharset))
{
$oHeaders->SetParentCharset($sCharset);
}
$this->sSubject = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::SUBJECT, true);
$this->sMessageId = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::MESSAGE_ID);
$this->sContentType = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE);
$this->oFrom = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::FROM_, true);
$this->oTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::TO_, true);
$this->oCc = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::CC, true);
$this->oBcc = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::BCC, true);
$this->oSender = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::SENDER);
$this->oReplyTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::REPLY_TO, true);
$this->sInReplyTo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IN_REPLY_TO);
$this->sReferences = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::REFERENCES);
$sHeaderDate = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DATE);
$this->sHeaderDate = $sHeaderDate;
$this->iHeaderTimeStampInUTC = \MailSo\Base\DateTimeHelper::ParseRFC2822DateString($sHeaderDate);
// Sensitivity
$this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::NOTHING;
$sSensitivity = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::SENSITIVITY);
switch (\strtolower($sSensitivity))
{
case 'personal':
$this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::PERSONAL;
break;
case 'private':
$this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::PRIVATE_;
break;
case 'company-confidential':
$this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::CONFIDENTIAL;
break;
}
// Priority
$this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::NORMAL;
$sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_MSMAIL_PRIORITY);
if (0 === \strlen($sPriority))
{
$sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IMPORTANCE);
}
if (0 === \strlen($sPriority))
{
$sPriority = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_PRIORITY);
}
if (0 < \strlen($sPriority))
{
switch (\str_replace(' ', '', \strtolower($sPriority)))
{
case 'high':
case '1(highest)':
case '2(high)':
case '1':
case '2':
$this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::HIGH;
break;
case 'low':
case '4(low)':
case '5(lowest)':
case '4':
case '5':
$this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::LOW;
break;
}
}
// ReadingConfirmation
$this->sReadingConfirmation = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DISPOSITION_NOTIFICATION_TO);
if (0 === \strlen($this->sReadingConfirmation))
{
$this->sReadingConfirmation = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_CONFIRM_READING_TO);
}
$this->sReadingConfirmation = \trim($this->sReadingConfirmation);
$sDraftInfo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::X_DRAFT_INFO);
if (0 < \strlen($sDraftInfo))
{
$sType = '';
$sFolder = '';
$sUid = '';
\MailSo\Mime\ParameterCollection::NewInstance($sDraftInfo)
->ForeachList(function ($oParameter) use (&$sType, &$sFolder, &$sUid) {
switch (\strtolower($oParameter->Name()))
{
case 'type':
$sType = $oParameter->Value();
break;
case 'uid':
$sUid = $oParameter->Value();
break;
case 'folder':
$sFolder = \base64_decode($oParameter->Value());
break;
}
})
;
if (0 < \strlen($sType) && 0 < \strlen($sFolder) && 0 < \strlen($sUid))
{
$this->aDraftInfo = array($sType, $sUid, $sFolder);
}
}
}
else if ($oFetchResponse->GetEnvelope())
{
if (0 === \strlen($sCharset) && $oBodyStructure)
{
$sCharset = $oBodyStructure->SearchCharset();
}
if (0 === \strlen($sCharset))
{
$sCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1;
}
// date, subject, from, sender, reply-to, to, cc, bcc, in-reply-to, message-id
$this->sMessageId = $oFetchResponse->GetFetchEnvelopeValue(9, '');
$this->sSubject = \MailSo\Base\Utils::DecodeHeaderValue($oFetchResponse->GetFetchEnvelopeValue(1, ''), $sCharset);
$this->oFrom = $oFetchResponse->GetFetchEnvelopeEmailCollection(2, $sCharset);
$this->oSender = $oFetchResponse->GetFetchEnvelopeEmailCollection(3, $sCharset);
$this->oReplyTo = $oFetchResponse->GetFetchEnvelopeEmailCollection(4, $sCharset);
$this->oTo = $oFetchResponse->GetFetchEnvelopeEmailCollection(5, $sCharset);
$this->oCc = $oFetchResponse->GetFetchEnvelopeEmailCollection(6, $sCharset);
$this->oBcc = $oFetchResponse->GetFetchEnvelopeEmailCollection(7, $sCharset);
$this->sInReplyTo = $oFetchResponse->GetFetchEnvelopeValue(8, '');
}
if (\is_array($aTextParts) && 0 < \count($aTextParts))
{
$sHtmlParts = array();
$sPlainParts = array();
foreach ($aTextParts as $oPart)
{
$sText = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY.'['.$oPart->PartID().']');
if (\is_string($sText) && 0 < \strlen($sText))
{
$sTextCharset = $oPart->Charset();
if (empty($sTextCharset))
{
$sTextCharset = $sCharset;
}
$sText = \MailSo\Base\Utils::DecodeEncodingValue($sText, $oPart->MailEncodingName());
$sText = \MailSo\Base\Utils::ConvertEncoding($sText, $sTextCharset, \MailSo\Base\Enumerations\Charset::UTF_8);
$sText = \MailSo\Base\Utils::Utf8Clear($sText);
if ('text/html' === $oPart->ContentType())
{
$sHtmlParts[] = $sText;
}
else
{
$sPlainParts[] = $sText;
}
}
}
if (0 < \count($sHtmlParts))
{
$this->sHtml = \implode('<br />', $sHtmlParts);
}
else
{
$this->sPlain = \implode("\n", $sPlainParts);
}
unset($sHtmlParts, $sPlainParts);
}
if ($oBodyStructure)
{
$aAttachmentsParts = $oBodyStructure->SearchAttachmentsParts();
if ($aAttachmentsParts && 0 < count($aAttachmentsParts))
{
$this->oAttachments = AttachmentCollection::NewInstance();
foreach ($aAttachmentsParts as /* @var $oAttachmentItem \MailSo\Imap\BodyStructure */ $oAttachmentItem)
{
$this->oAttachments->Add(
\MailSo\Mail\Attachment::NewBodyStructureInstance($this->sFolder, $this->iUid, $oAttachmentItem)
);
}
}
}
return $this;
}
}

View file

@ -0,0 +1,108 @@
<?php
namespace MailSo\Mail;
/**
* @category MailSo
* @package Mail
*/
class MessageCollection extends \MailSo\Base\Collection
{
/**
* @var string
*/
public $FolderHash;
/**
* @var int
*/
public $MessageCount;
/**
* @var int
*/
public $MessageUnseenCount;
/**
* @var int
*/
public $MessageResultCount;
/**
* @var string
*/
public $FolderName;
/**
* @var int
*/
public $Offset;
/**
* @var int
*/
public $Limit;
/**
* @var string
*/
public $Search;
/**
* @var string
*/
public $UidNext;
/**
* @var array
*/
public $NewMessages;
/**
* @var array
*/
public $LastCollapsedThreadUids;
/**
* @access protected
*/
protected function __construct()
{
parent::__construct();
$this->Clear();
}
/**
* @return \MailSo\Mail\MessageCollection
*/
public static function NewInstance()
{
return new self();
}
/**
* @return \MailSo\Mail\MessageCollection
*/
public function Clear()
{
parent::Clear();
$this->FolderHash = '';
$this->MessageCount = 0;
$this->MessageUnseenCount = 0;
$this->MessageResultCount = 0;
$this->FolderName = '';
$this->Offset = 0;
$this->Limit = 0;
$this->Search = '';
$this->UidNext = '';
$this->NewMessages = array();
$this->LastCollapsedThreadUids = array();
return $this;
}
}

View file

@ -0,0 +1,23 @@
<?php
namespace MailSo;
if (!\defined('MAILSO_LIBRARY_ROOT_PATH'))
{
\define('MAILSO_LIBRARY_ROOT_PATH', \defined('MAILSO_LIBRARY_USE_PHAR')
? 'phar://mailso.phar/' : \rtrim(\realpath(__DIR__), '\\/').'/');
\spl_autoload_register(function ($sClassName) {
return (0 === \strpos($sClassName, 'MailSo') && false !== \strpos($sClassName, '\\')) ?
include MAILSO_LIBRARY_ROOT_PATH.\str_replace('\\', '/', \substr($sClassName, 7)).'.php' : false;
});
if (\class_exists('MailSo\Base\Loader'))
{
\MailSo\Base\Loader::Init();
}
else
{
throw new \Exception('MailSo initialisation error');
}
}

View file

@ -0,0 +1,140 @@
<?php
namespace MailSo\Mime;
/**
* @category MailSo
* @package Mime
*/
class Attachment
{
/**
* @var resource
*/
private $rResource;
/**
* @var string
*/
private $sFileName;
/**
* @var int
*/
private $iFileSize;
/**
* @var string
*/
private $sCID;
/**
* @var bool
*/
private $bIsInline;
/**
* @var bool
*/
private $bIsLinked;
/**
* @var array
*/
private $aCustomContentTypeParams;
/**
* @access private
*/
private function __construct($rResource, $sFileName, $iFileSize, $bIsInline, $bIsLinked, $sCID, $aCustomContentTypeParams = array())
{
$this->rResource = $rResource;
$this->sFileName = $sFileName;
$this->iFileSize = $iFileSize;
$this->bIsInline = $bIsInline;
$this->bIsLinked = $bIsLinked;
$this->sCID = $sCID;
$this->aCustomContentTypeParams = $aCustomContentTypeParams;
}
/**
* @param resource $rResource
* @param string $sFileName = ''
* @param int $iFileSize = 0
* @param bool $bIsInline = false
* @param bool $bIsLinked = false
* @param string $sCID = ''
* @param array $aCustomContentTypeParams = array()
*
* @return \MailSo\Mime\Attachment
*/
public static function NewInstance($rResource, $sFileName = '', $iFileSize = 0, $bIsInline = false,
$bIsLinked = false, $sCID = '', $aCustomContentTypeParams = array())
{
return new self($rResource, $sFileName, $iFileSize, $bIsInline, $bIsLinked, $sCID, $aCustomContentTypeParams);
}
/**
* @return resource
*/
public function Resource()
{
return $this->rResource;
}
/**
* @return string
*/
public function ContentType()
{
return \MailSo\Base\Utils::MimeContentType($this->sFileName);
}
/**
* @return array
*/
public function CustomContentTypeParams()
{
return $this->aCustomContentTypeParams;
}
/**
* @return string
*/
public function CID()
{
return $this->sCID;
}
/**
* @return string
*/
public function FileName()
{
return $this->sFileName;
}
/**
* @return int
*/
public function FileSize()
{
return $this->iFileSize;
}
/**
* @return bool
*/
public function IsInline()
{
return $this->bIsInline;
}
/**
* @return bool
*/
public function IsLinked()
{
return $this->bIsLinked && 0 < \strlen($this->sCID);
}
}

View file

@ -0,0 +1,62 @@
<?php
namespace MailSo\Mime;
/**
* @category MailSo
* @package Mime
*/
class AttachmentCollection extends \MailSo\Base\Collection
{
/**
* @access protected
*/
protected function __construct()
{
parent::__construct();
}
/**
* @return \MailSo\Mime\AttachmentCollection
*/
public static function NewInstance()
{
return new self();
}
/**
* @return array
*/
public function LinkedAttachments()
{
return $this->FilterList(function ($oItem) {
return $oItem && $oItem->IsLinked();
});
}
/**
* @return array
*/
public function UnlinkedAttachments()
{
return $this->FilterList(function ($oItem) {
return $oItem && !$oItem->IsLinked();
});
}
/**
* @return int
*/
public function SizeOfAttachments()
{
$iResult = 0;
$this->ForeachList(function ($oItem) use (&$iResult) {
if ($oItem)
{
$iResult += $oItem->FileSize();
}
});
return $iResult;
}
}

View file

@ -0,0 +1,275 @@
<?php
namespace MailSo\Mime;
/**
* @category MailSo
* @package Mime
*/
class Email
{
/**
* @var string
*/
private $sDisplayName;
/**
* @var string
*/
private $sEmail;
/**
* @var string
*/
private $sRemark;
/**
* @access private
*
* @param string $sEmail
* @param string $sDisplayName = ''
* @param string $sRemark = ''
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
private function __construct($sEmail, $sDisplayName = '', $sRemark = '')
{
if (!\MailSo\Base\Validator::NotEmptyString($sEmail, true))
{
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
}
$this->sEmail = \trim($sEmail);
$this->sDisplayName = \trim($sDisplayName);
$this->sRemark = \trim($sRemark);
}
/**
* @param string $sEmail
* @param string $sDisplayName = ''
* @param string $sRemark = ''
*
* @return \MailSo\Mime\Email
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public static function NewInstance($sEmail, $sDisplayName = '', $sRemark = '')
{
return new self($sEmail, $sDisplayName, $sRemark);
}
/**
* @param string $sEmailAddress
* @return \MailSo\Mime\Email
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public static function Parse($sEmailAddress)
{
if (!\MailSo\Base\Validator::NotEmptyString($sEmailAddress, true))
{
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
}
$sName = '';
$sEmail = '';
$sComment = '';
$bInName = false;
$bInAddress = false;
$bInComment = false;
$iStartIndex = 0;
$iEndIndex = 0;
$iCurrentIndex = 0;
while ($iCurrentIndex < \strlen($sEmailAddress))
{
switch ($sEmailAddress{$iCurrentIndex})
{
// case '\'':
case '"':
// $sQuoteChar = $sEmailAddress{$iCurrentIndex};
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
{
$bInName = true;
$iStartIndex = $iCurrentIndex;
}
else if ((!$bInAddress) && (!$bInComment))
{
$iEndIndex = $iCurrentIndex;
$sName = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
$iEndIndex = 0;
$iCurrentIndex = 0;
$iStartIndex = 0;
$bInName = false;
}
break;
case '<':
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
{
if ($iCurrentIndex > 0 && \strlen($sName) == 0)
{
$sName = \substr($sEmailAddress, 0, $iCurrentIndex);
}
$bInAddress = true;
$iStartIndex = $iCurrentIndex;
}
break;
case '>':
if ($bInAddress)
{
$iEndIndex = $iCurrentIndex;
$sEmail = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
$iEndIndex = 0;
$iCurrentIndex = 0;
$iStartIndex = 0;
$bInAddress = false;
}
break;
case '(':
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
{
$bInComment = true;
$iStartIndex = $iCurrentIndex;
}
break;
case ')':
if ($bInComment)
{
$iEndIndex = $iCurrentIndex;
$sComment = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
$iEndIndex = 0;
$iCurrentIndex = 0;
$iStartIndex = 0;
$bInComment = false;
}
break;
case '\\':
$iCurrentIndex++;
break;
}
$iCurrentIndex++;
}
if (strlen($sEmail) == 0)
{
$aRegs = array('');
if (\preg_match('/[^@\s]+@\S+/i', $sEmailAddress, $aRegs) && isset($aRegs[0]))
{
$sEmail = $aRegs[0];
}
else
{
$sName = $sEmailAddress;
}
}
if ((\strlen($sEmail) > 0) && (\strlen($sName) == 0) && (strlen($sComment) == 0))
{
$sName = \str_replace($sEmail, '', $sEmailAddress);
}
$sEmail = \trim(\trim($sEmail), '<>');
$sName = \trim(\trim($sName), '"');
$sComment = \trim(\trim($sComment), '()');
// Remove backslash
$sName = \preg_replace('/\\\\(.)/s', '$1', $sName);
$sComment = \preg_replace('/\\\\(.)/s', '$1', $sComment);
return Email::NewInstance($sEmail, $sName, $sComment);
}
/**
* @return string
*/
public function GetEmail()
{
return $this->sEmail;
}
/**
* @return string
*/
public function GetDisplayName()
{
return $this->sDisplayName;
}
/**
* @return string
*/
public function GetRemark()
{
return $this->sRemark;
}
/**
* @return string
*/
public function GetAccountName()
{
return \MailSo\Base\Utils::GetAccountNameFromEmail($this->sEmail);
}
/**
* @return string
*/
public function GetDomain()
{
return \MailSo\Base\Utils::GetDomainFromEmail($this->sEmail);
}
/**
* @return array
*/
public function ToArray()
{
return array($this->sDisplayName, $this->sEmail, $this->sRemark);
}
/**
* @param bool $bConvertSpecialsName = false
*
* @return string
*/
public function ToString($bConvertSpecialsName = false)
{
$sReturn = '';
$sRemark = \str_replace(')', '\)', $this->sRemark);
$sDisplayName = \str_replace('"', '\"', $this->sDisplayName);
if ($bConvertSpecialsName)
{
$sDisplayName = 0 === \strlen($sDisplayName) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue(
\MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
$sDisplayName);
$sRemark = 0 === \strlen($sRemark) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue(
\MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
$sRemark);
}
$sDisplayName = 0 === \strlen($sDisplayName) ? '' : '"'.$sDisplayName.'"';
$sRemark = 0 === \strlen($sRemark) ? '' : '('.$sRemark.')';
if (0 < \strlen($this->sEmail))
{
$sReturn = $this->sEmail;
if (0 < \strlen($sDisplayName.$sRemark))
{
$sReturn = $sDisplayName.' <'.$sReturn.'> '.$sRemark;
}
}
return \trim($sReturn);
}
}

View file

@ -0,0 +1,228 @@
<?php
namespace MailSo\Mime;
/**
* @category MailSo
* @package Mime
*/
class EmailCollection extends \MailSo\Base\Collection
{
/**
* @access protected
*
* @param string $sEmailAddresses = ''
*/
protected function __construct($sEmailAddresses = '')
{
parent::__construct();
if (0 < \strlen($sEmailAddresses))
{
$this->parseEmailAddresses($sEmailAddresses);
}
}
/**
* @param string $sEmailAddresses = ''
*
* @return \MailSo\Mime\EmailCollection
*/
public static function NewInstance($sEmailAddresses = '')
{
return new self($sEmailAddresses);
}
/**
* @param string $sEmailAddresses
*
* @return \MailSo\Mime\EmailCollection
*/
public static function Parse($sEmailAddresses)
{
return self::NewInstance($sEmailAddresses);
}
/**
* @return array
*/
public function ToArray()
{
$aReturn = $aEmails = array();
$aEmails =& $this->GetAsArray();
foreach ($aEmails as /* @var $oEmail \MailSo\Mime\Email */ $oEmail)
{
$aReturn[] = $oEmail->ToArray();
}
return $aReturn;
}
/**
* @param \MailSo\Mime\EmailCollection $oEmails
*
* @return \MailSo\Mime\EmailCollection
*/
public function MergeWithOtherCollection(\MailSo\Mime\EmailCollection $oEmails)
{
$aEmails =& $oEmails->GetAsArray();
foreach ($aEmails as /* @var $oEmail \MailSo\Mime\Email */ $oEmail)
{
$this->Add($oEmail);
}
return $this;
}
/**
* @return \MailSo\Mime\EmailCollection
*/
public function Unique()
{
$aCache = array();
$aReturn = array();
$aEmails =& $this->GetAsArray();
foreach ($aEmails as /* @var $oEmail \MailSo\Mime\Email */ $oEmail)
{
$sEmail = $oEmail->GetEmail();
if (!isset($aCache[$sEmail]))
{
$aCache[$sEmail] = true;
$aReturn[] = $oEmail;
}
}
$this->SetAsArray($aReturn);
return $this;
}
/**
* @param bool $bConvertSpecialsName = false
*
* @return string
*/
public function ToString($bConvertSpecialsName = false)
{
$aReturn = $aEmails = array();
$aEmails =& $this->GetAsArray();
foreach ($aEmails as /* @var $oEmail \MailSo\Mime\Email */ $oEmail)
{
$aReturn[] = $oEmail->ToString($bConvertSpecialsName);
}
return \implode(', ', $aReturn);
}
/**
* @param string $sRawEmails
*
* @return \MailSo\Mime\EmailCollection
*/
private function parseEmailAddresses($sRawEmails)
{
$this->Clear();
$sWorkingRecipients = \trim($sRawEmails);
if (0 === \strlen($sWorkingRecipients))
{
return $this;
}
$iEmailStartPos = 0;
$iEmailEndPos = 0;
$bIsInQuotes = false;
$sChQuote = '"';
$bIsInAngleBrackets = false;
$bIsInBrackets = false;
$iCurrentPos = 0;
$sWorkingRecipientsLen = \strlen($sWorkingRecipients);
while ($iCurrentPos < $sWorkingRecipientsLen)
{
switch ($sWorkingRecipients{$iCurrentPos})
{
case '\'':
case '"':
if (!$bIsInQuotes)
{
$sChQuote = $sWorkingRecipients{$iCurrentPos};
$bIsInQuotes = true;
}
else if ($sChQuote == $sWorkingRecipients{$iCurrentPos})
{
$bIsInQuotes = false;
}
break;
case '<':
if (!$bIsInAngleBrackets)
{
$bIsInAngleBrackets = true;
}
break;
case '>':
if ($bIsInAngleBrackets)
{
$bIsInAngleBrackets = false;
}
break;
case '(':
if (!$bIsInBrackets)
{
$bIsInBrackets = true;
}
break;
case ')':
if ($bIsInBrackets)
{
$bIsInBrackets = false;
}
break;
case ',':
case ';':
if (!$bIsInAngleBrackets && !$bIsInBrackets && !$bIsInQuotes)
{
$iEmailEndPos = $iCurrentPos;
try
{
$this->Add(
\MailSo\Mime\Email::Parse(\substr($sWorkingRecipients, $iEmailStartPos, $iEmailEndPos - $iEmailStartPos))
);
$iEmailStartPos = $iCurrentPos + 1;
}
catch (\MailSo\Base\Exceptions\InvalidArgumentException $oException)
{
}
}
break;
}
$iCurrentPos++;
}
if ($iEmailStartPos < $iCurrentPos)
{
try
{
$this->Add(
\MailSo\Mime\Email::Parse(\substr($sWorkingRecipients, $iEmailStartPos, $iCurrentPos - $iEmailStartPos))
);
}
catch (\MailSo\Base\Exceptions\InvalidArgumentException $oException) {}
}
return $this;
}
}

View file

@ -0,0 +1,16 @@
<?php
namespace MailSo\Mime\Enumerations;
/**
* @category MailSo
* @package Mime
* @subpackage Enumerations
*/
class Constants
{
const TAB = "\t";
const CRLF = "\r\n";
const LINE_LENGTH = 74;
}

View file

@ -0,0 +1,49 @@
<?php
namespace MailSo\Mime\Enumerations;
/**
* @category MailSo
* @package Mime
* @subpackage Enumerations
*/
class Header
{
const DATE = 'Date';
const RECEIVED = 'Received';
const SUBJECT = 'Subject';
const TO_ = 'To';
const FROM_ = 'From';
const CC = 'Cc';
const BCC = 'Bcc';
const REPLY_TO = 'Reply-To';
const SENDER = 'Sender';
const RETURN_PATH = 'Return-Path';
const MESSAGE_ID = 'Message-ID';
const IN_REPLY_TO = 'In-Reply-To';
const REFERENCES = 'References';
const X_DRAFT_INFO = 'X-Draft-Info';
const X_ORIGINATING_IP = 'X-Originating-IP';
const CONTENT_TYPE = 'Content-Type';
const CONTENT_TRANSFER_ENCODING = 'Content-Transfer-Encoding';
const CONTENT_DISPOSITION = 'Content-Disposition';
const CONTENT_DESCRIPTION = 'Content-Description';
const CONTENT_ID = 'Content-ID';
const CONTENT_LOCATION = 'Content-Location';
const SENSITIVITY = 'Sensitivity';
const DISPOSITION_NOTIFICATION_TO = 'Disposition-Notification-To';
const X_CONFIRM_READING_TO = 'X-Confirm-Reading-To';
const MIME_VERSION = 'Mime-Version';
const X_MAILER = 'X-Mailer';
const X_MSMAIL_PRIORITY = 'X-MSMail-Priority';
const IMPORTANCE = 'Importance';
const X_PRIORITY = 'X-Priority';
}

View file

@ -0,0 +1,15 @@
<?php
namespace MailSo\Mime\Enumerations;
/**
* @category MailSo
* @package Mime
* @subpackage Enumerations
*/
class MessagePriority
{
const LOW = 5;
const NORMAL = 3;
const HIGH = 1;
}

View file

@ -0,0 +1,27 @@
<?php
namespace MailSo\Mime\Enumerations;
/**
* @category MailSo
* @package Mime
* @subpackage Enumerations
*/
class MimeType
{
const TEXT_PLAIN = 'text/plain';
const TEXT_HTML = 'text/html';
const MULTIPART_ALTERNATIVE = 'multipart/alternative';
const MULTIPART_RELATED = 'multipart/related';
const MULTIPART_MIXED = 'multipart/mixed';
const MULTIPART_SIGNED = 'multipart/signed';
const MESSAGE_RFC822 = 'message/rfc822';
const MESSAGE_PARTIAL = 'message/partial';
const MESSAGE_REPORT = 'message/report';
const APPLICATION_MS_TNEF = 'application/ms-tnef';
const APPLICATION_PKCS7_MIME = 'application/pkcs7-mime';
const APPLICATION_PKCS7_SIGNATURE = 'application/pkcs7-signature';
}

View file

@ -0,0 +1,16 @@
<?php
namespace MailSo\Mime\Enumerations;
/**
* @category MailSo
* @package Mime
* @subpackage Enumerations
*/
class Parameter
{
const CHARSET = 'charset';
const NAME = 'name';
const FILENAME = 'filename';
const BOUNDARY = 'boundary';
}

View file

@ -0,0 +1,16 @@
<?php
namespace MailSo\Mime\Enumerations;
/**
* @category MailSo
* @package Mime
* @subpackage Enumerations
*/
class Sensitivity
{
const NOTHING = 0;
const CONFIDENTIAL = 1;
const PRIVATE_ = 2;
const PERSONAL = 3;
}

View file

@ -0,0 +1,299 @@
<?php
namespace MailSo\Mime;
/**
* @category MailSo
* @package Mime
*/
class Header
{
/**
* @var string
*/
private $sName;
/**
* @var string
*/
private $sValue;
/**
* @var string
*/
private $sFullValue;
/**
* @var string
*/
private $sEncodedValueForReparse;
/**
* @var ParameterCollection
*/
private $oParameters;
/**
* @var strign
*/
private $sParentCharset;
/**
* @access private
*
* @param string $sName
* @param string $sValue
* @param string $sEncodedValueForReparse
*/
private function __construct($sName, $sValue, $sEncodedValueForReparse)
{
$this->sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1;
$this->initInputData($sName, $sValue, $sEncodedValueForReparse);
}
/**
* @param string $sName
* @param string $sValue
* @param string $sEncodedValueForReparse
*
* @return void
*/
private function initInputData($sName, $sValue, $sEncodedValueForReparse)
{
$this->sName = trim($sName);
$this->sFullValue = trim($sValue);
$this->sEncodedValueForReparse = '';
$this->oParameters = null;
if (0 < \strlen($sEncodedValueForReparse) && $this->IsReparsed())
{
$this->sEncodedValueForReparse = \trim($sEncodedValueForReparse);
}
if (0 < \strlen($this->sFullValue) && $this->IsParameterized())
{
$aRawExplode = \explode(';', $this->sFullValue, 2);
if (2 === \count($aRawExplode))
{
$this->sValue = $aRawExplode[0];
$this->oParameters =
\MailSo\Mime\ParameterCollection::NewInstance($aRawExplode[1]);
}
else
{
$this->sValue = $this->sFullValue;
}
}
else
{
$this->sValue = $this->sFullValue;
}
}
/**
* @param string $sName
* @param string $sValue = ''
* @param string $sEncodedValueForReparse = ''
*
* @return \MailSo\Mime\Header
*/
public static function NewInstance($sName, $sValue = '', $sEncodedValueForReparse = '')
{
return new self($sName, $sValue, $sEncodedValueForReparse);
}
/**
* @param string $sEncodedLines
* @param string $sIncomingCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1
*
* @return \MailSo\Mime\Header | false
*/
public static function NewInstanceFromEncodedString($sEncodedLines, $sIncomingCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1)
{
$aParts = \explode(':', \str_replace("\r", '', $sEncodedLines), 2);
if (isset($aParts[0]) && isset($aParts[1]) && 0 < \strlen($aParts[0]) && 0 < \strlen($aParts[1]))
{
return self::NewInstance(
\trim($aParts[0]),
\trim(\MailSo\Base\Utils::DecodeHeaderValue(\trim($aParts[1]), $sIncomingCharset)),
\trim($aParts[1])
);
}
return false;
}
/**
* @return string
*/
public function Name()
{
return $this->sName;
}
/**
* @return string
*/
public function NameWithDelimitrom()
{
return $this->Name().': ';
}
/**
* @return string
*/
public function Value()
{
return $this->sValue;
}
/**
* @return string
*/
public function FullValue()
{
return $this->sFullValue;
}
/**
* @param string $sParentCharset
* @return \MailSo\Mime\Header
*/
public function SetParentCharset($sParentCharset)
{
if ($this->sParentCharset !== $sParentCharset && $this->IsReparsed() && 0 < \strlen($this->sEncodedValueForReparse))
{
$this->initInputData(
$this->sName,
\trim(\MailSo\Base\Utils::DecodeHeaderValue($this->sEncodedValueForReparse, $sParentCharset)),
$this->sEncodedValueForReparse);
}
$this->sParentCharset = $sParentCharset;
return $this;
}
/**
* @return \MailSo\Mime\ParameterCollection | null
*/
public function Parameters()
{
return $this->oParameters;
}
/**
* @param string $sValue
* @return string
*/
private function wordWrapHelper($sValue, $sGlue = "\r\n ")
{
return \trim(substr(wordwrap($this->NameWithDelimitrom().$sValue,
\MailSo\Mime\Enumerations\Constants::LINE_LENGTH, $sGlue
), \strlen($this->NameWithDelimitrom())));
}
/**
* @return string
*/
public function EncodedValue()
{
$sResult = $this->sFullValue;
if ($this->IsSubject())
{
if (!\MailSo\Base\Utils::IsAscii($sResult) && \function_exists('iconv_mime_encode'))
{
$aPreferences = array(
// 'scheme' => \MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE_SHORT,
'scheme' => \MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
'input-charset' => \MailSo\Base\Enumerations\Charset::UTF_8,
'output-charset' => \MailSo\Base\Enumerations\Charset::UTF_8,
'line-length' => \MailSo\Mime\Enumerations\Constants::LINE_LENGTH,
'line-break-chars' => \MailSo\Mime\Enumerations\Constants::CRLF
);
return \iconv_mime_encode($this->Name(), $sResult, $aPreferences);
}
}
else if ($this->IsParameterized() && $this->oParameters && 0 < $this->oParameters->Count())
{
$sResult = $this->sValue.'; '.$this->oParameters->ToString(true);
}
else if ($this->IsEmail())
{
$oEmailCollection = \MailSo\Mime\EmailCollection::NewInstance($this->sFullValue);
if ($oEmailCollection && 0 < $oEmailCollection->Count())
{
$sResult = $oEmailCollection->ToString(true);
}
}
return $this->NameWithDelimitrom().$this->wordWrapHelper($sResult);
}
/**
* @return bool
*/
public function IsSubject()
{
return \strtolower(\MailSo\Mime\Enumerations\Header::SUBJECT) === \strtolower($this->Name());
}
/**
* @return bool
*/
public function IsParameterized()
{
return \in_array(\strtolower($this->sName), array(
\strtolower(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE),
\strtolower(\MailSo\Mime\Enumerations\Header::CONTENT_DISPOSITION)
));
}
/**
* @return bool
*/
public function IsEmail()
{
return \in_array(\strtolower($this->sName), array(
\strtolower(\MailSo\Mime\Enumerations\Header::FROM_),
\strtolower(\MailSo\Mime\Enumerations\Header::TO_),
\strtolower(\MailSo\Mime\Enumerations\Header::CC),
\strtolower(\MailSo\Mime\Enumerations\Header::BCC),
\strtolower(\MailSo\Mime\Enumerations\Header::REPLY_TO),
\strtolower(\MailSo\Mime\Enumerations\Header::RETURN_PATH),
\strtolower(\MailSo\Mime\Enumerations\Header::SENDER)
));
}
/**
* @return string
*/
public function ValueWithCharsetAutoDetect()
{
$sValue = $this->Value();
if (!\MailSo\Base\Utils::IsAscii($sValue) &&
0 < \strlen($this->sEncodedValueForReparse) &&
!\MailSo\Base\Utils::IsAscii($this->sEncodedValueForReparse))
{
$sValueCharset = \MailSo\Base\Utils::CharsetDetect($this->sEncodedValueForReparse);
if (0 < \strlen($sValueCharset))
{
$this->SetParentCharset($sValueCharset);
$sValue = $this->Value();
}
}
return $sValue;
}
/**
* @return bool
*/
public function IsReparsed()
{
return $this->IsEmail() || $this->IsSubject() || $this->IsParameterized();
}
}

View file

@ -0,0 +1,362 @@
<?php
namespace MailSo\Mime;
/**
* @category MailSo
* @package Mime
*/
class HeaderCollection extends \MailSo\Base\Collection
{
/**
* @return string
*/
protected $sRawHeaders;
/**
* @var strign
*/
protected $sParentCharset;
/**
* @access protected
*
* @param string $sRawHeaders = ''
* @param bool $bStoreRawHeaders = true
*/
protected function __construct($sRawHeaders = '', $bStoreRawHeaders = true)
{
parent::__construct();
$this->sRawHeaders = '';
$this->sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1;
if (0 < \strlen($sRawHeaders))
{
$this->Parse($sRawHeaders, $bStoreRawHeaders);
}
}
/**
* @param string $sRawHeaders = ''
* @param bool $bStoreRawHeaders = true
*
* @return \MailSo\Mime\HeaderCollection
*/
public static function NewInstance($sRawHeaders = '', $bStoreRawHeaders = true)
{
return new self($sRawHeaders, $bStoreRawHeaders);
}
/**
* @param string $sName
* @param string $sValue
* @param bool $bToTop = false
*
* @return \MailSo\Mime\HeaderCollection
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public function AddByName($sName, $sValue, $bToTop = false)
{
return $this->Add(Header::NewInstance($sName, $sValue), $bToTop);
}
/**
* @param string $sName
* @param string $sValue
* @param bool $bToTop = false
*
* @return \MailSo\Mime\HeaderCollection
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public function SetByName($sName, $sValue, $bToTop = false)
{
return $this->RemoveByName($sName)->Add(Header::NewInstance($sName, $sValue), $bToTop);
}
/**
* @return \MailSo\Mime\Header | null
*/
public function &GetByIndex($iIndex)
{
$mResult = null;
$mResult =& parent::GetByIndex($iIndex);
return $mResult;
}
/**
* @param string $sHeaderName
* @param bool $bCharsetAutoDetect = false
* @return string
*/
public function ValueByName($sHeaderName, $bCharsetAutoDetect = false)
{
$oHeader = null;
$oHeader =& $this->GetByName($sHeaderName);
return (null !== $oHeader) ? ($bCharsetAutoDetect ? $oHeader->ValueWithCharsetAutoDetect() : $oHeader->Value()) : '';
}
/**
* @param string $sHeaderName
* @param bool $bCharsetAutoDetect = false
* @return array
*/
public function ValuesByName($sHeaderName, $bCharsetAutoDetect = false)
{
$aResult = array();
$oHeader = null;
$sHeaderNameLower = \strtolower($sHeaderName);
$aHeaders =& $this->GetAsArray();
foreach ($aHeaders as /* @var $oHeader \MailSo\Mime\Header */ &$oHeader)
{
if ($sHeaderNameLower === \strtolower($oHeader->Name()))
{
$aResult[] = $bCharsetAutoDetect ? $oHeader->ValueWithCharsetAutoDetect() : $oHeader->Value();
}
}
return $aResult;
}
/**
* @param string $sHeaderName
*
* @return \MailSo\Mime\HeaderCollection
*/
public function RemoveByName($sHeaderName)
{
$aResult = $this->FilterList(function ($oHeader) use ($sHeaderName) {
return $oHeader && \strtolower($oHeader->Name()) !== \strtolower($sHeaderName);
});
return $this->SetAsArray($aResult);
}
/**
* @param string $sHeaderName
* @param bool $bCharsetAutoDetect = false
* @return string
*/
public function GetAsEmailCollection($sHeaderName, $bCharsetAutoDetect = false)
{
$oResult = null;
$sValue = $this->ValueByName($sHeaderName, $bCharsetAutoDetect);
if (0 < \strlen($sValue))
{
$oResult = \MailSo\Mime\EmailCollection::NewInstance($sValue);
}
return $oResult && 0 < $oResult->Count() ? $oResult : null;
}
/**
* @param string $sHeaderName
* @return \MailSo\Mime\ParameterCollection | null
*/
public function ParametersByName($sHeaderName)
{
$oParameters = $oHeader = null;
$oHeader =& $this->GetByName($sHeaderName);
if ($oHeader)
{
$oParameters = $oHeader->Parameters();
}
return $oParameters;
}
/**
* @param string $sHeaderName
* @param string $sParamName
* @return string
*/
public function ParameterValue($sHeaderName, $sParamName)
{
$oParameters = $this->ParametersByName($sHeaderName);
return (null !== $oParameters) ? $oParameters->ParameterValueByName($sParamName) : '';
}
/**
* @param string $sHeaderName
* @return \MailSo\Mime\Header | false
*/
public function &GetByName($sHeaderName)
{
$oResult = $oHeader = null;
$sHeaderNameLower = \strtolower($sHeaderName);
$aHeaders =& $this->GetAsArray();
foreach ($aHeaders as /* @var $oHeader \MailSo\Mime\Header */ &$oHeader)
{
if ($sHeaderNameLower === \strtolower($oHeader->Name()))
{
$oResult =& $oHeader;
break;
}
}
return $oResult;
}
/**
* @param array $aList
* @return \MailSo\Mime\HeaderCollection
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public function SetAsArray($aList)
{
parent::SetAsArray($aList);
return $this;
}
/**
* @param string $sParentCharset
* @return \MailSo\Mime\HeaderCollection
*/
public function SetParentCharset($sParentCharset)
{
if (0 < \strlen($sParentCharset))
{
if ($this->sParentCharset !== $sParentCharset)
{
$oHeader = null;
$aHeaders =& $this->GetAsArray();
foreach ($aHeaders as /* @var $oHeader \MailSo\Mime\Header */ &$oHeader)
{
$oHeader->SetParentCharset($sParentCharset);
}
$this->sParentCharset = $sParentCharset;
}
}
return $this;
}
/**
* @return void
*/
public function Clear()
{
parent::Clear();
$this->sRawHeaders = '';
}
/**
* @param string $sRawHeaders
* @param bool $bStoreRawHeaders = false
* @param string $sParentCharset = ''
*
* @return \MailSo\Mime\HeaderCollection
*/
public function Parse($sRawHeaders, $bStoreRawHeaders = false, $sParentCharset = '')
{
$this->Clear();
if ($bStoreRawHeaders)
{
$this->sRawHeaders = $sRawHeaders;
}
if (0 === \strlen($this->sParentCharset))
{
$this->sParentCharset = $sParentCharset;
}
$aHeaders = \explode("\n", \str_replace("\r", '', $sRawHeaders));
$sName = null;
$sValue = null;
foreach ($aHeaders as $sHeadersValue)
{
if (0 === strlen($sHeadersValue))
{
continue;
}
$sFirstChar = \substr($sHeadersValue, 0, 1);
if ($sFirstChar !== ' ' && $sFirstChar !== "\t" && false === \strpos($sHeadersValue, ':'))
{
continue;
}
else if (null !== $sName && ($sFirstChar === ' ' || $sFirstChar === "\t"))
{
$sValue = \is_null($sValue) ? '' : $sValue;
if ('?=' === \substr(\rtrim($sHeadersValue), -2))
{
$sHeadersValue = \rtrim($sHeadersValue);
}
if ('=?' === \substr(\ltrim($sHeadersValue), 0, 2))
{
$sHeadersValue = \ltrim($sHeadersValue);
}
if ('=?' === \substr($sHeadersValue, 0, 2))
{
$sValue .= $sHeadersValue;
}
else
{
$sValue .= "\n".$sHeadersValue;
}
}
else
{
if (null !== $sName)
{
$oHeader = Header::NewInstanceFromEncodedString($sName.': '.$sValue, $this->sParentCharset);
if ($oHeader)
{
$this->Add($oHeader);
}
$sName = null;
$sValue = null;
}
$aHeaderParts = \explode(':', $sHeadersValue, 2);
$sName = $aHeaderParts[0];
$sValue = isset($aHeaderParts[1]) ? $aHeaderParts[1] : '';
if ('?=' === \substr(\rtrim($sValue), -2))
{
$sValue = \rtrim($sValue);
}
}
}
if (null !== $sName)
{
$oHeader = Header::NewInstanceFromEncodedString($sName.': '.$sValue, $this->sParentCharset);
if ($oHeader)
{
$this->Add($oHeader);
}
}
return $this;
}
/**
* @return string
*/
public function ToEncodedString()
{
$aResult = array();
$aHeaders =& $this->GetAsArray();
foreach ($aHeaders as /* @var $oHeader \MailSo\Mime\Header */ &$oHeader)
{
$aResult[] = $oHeader->EncodedValue();
}
return \implode(\MailSo\Mime\Enumerations\Constants::CRLF, $aResult);
}
}

View file

@ -0,0 +1,808 @@
<?php
namespace MailSo\Mime;
/**
* @category MailSo
* @package Mime
*/
class Message
{
/**
* @var array
*/
private $aHeadersValue;
/**
* @var array
*/
private $aAlternativeParts;
/**
* @var \MailSo\Mime\AttachmentCollection
*/
private $oAttachmentCollection;
/**
* @var string
*/
private $sMessageId;
/**
* @var string
*/
private $sCustomXMailer;
/**
* @access private
*/
private function __construct()
{
$this->aHeadersValue = array();
$this->aAlternativeParts = array();
$this->oAttachmentCollection = AttachmentCollection::NewInstance();
$this->sMessageId = '';
$this->sCustomXMailer = '';
$this->bAddEmptyTextPart = true;
}
/**
* @return \MailSo\Mime\Message
*/
public static function NewInstance()
{
return new self();
}
/**
* @return void
*/
public function DoesNotCreateEmptyTextPart()
{
$this->bAddEmptyTextPart = false;
}
/**
* @return string
*/
public function MessageId()
{
return $this->sMessageId;
}
/**
* @param string $sMessageId
*
* @return void
*/
public function SetMessageId($sMessageId)
{
$this->sMessageId = $sMessageId;
}
/**
* @param string $sHostName = ''
*
* @return void
*/
public function RegenerateMessageId($sHostName = '')
{
$this->SetMessageId($this->generateNewMessageId($sHostName));
}
/**
* @return \MailSo\Mime\AttachmentCollection
*/
public function Attachments()
{
return $this->oAttachmentCollection;
}
/**
* @return \MailSo\Mime\EmailCollection
*/
public function GetTo()
{
$oResult = \MailSo\Mime\EmailCollection::NewInstance();
if (isset($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_]) &&
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_] instanceof \MailSo\Mime\EmailCollection)
{
$oResult->MergeWithOtherCollection($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_]);
}
return $oResult->Unique();
}
/**
* @return \MailSo\Mime\EmailCollection
*/
public function GetRcpt()
{
$oResult = \MailSo\Mime\EmailCollection::NewInstance();
if (isset($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_]) &&
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_] instanceof \MailSo\Mime\EmailCollection)
{
$oResult->MergeWithOtherCollection($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_]);
}
if (isset($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::CC]) &&
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::CC] instanceof \MailSo\Mime\EmailCollection)
{
$oResult->MergeWithOtherCollection($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::CC]);
}
if (isset($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::BCC]) &&
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::BCC] instanceof \MailSo\Mime\EmailCollection)
{
$oResult->MergeWithOtherCollection($this->aHeadersValue[\MailSo\Mime\Enumerations\Header::BCC]);
}
return $oResult->Unique();
}
/**
* @param string $sHeader
* @param string $sValue
*
* @return \MailSo\Mime\Message
*/
public function SetCustomHeader($sHeaderName, $sValue)
{
$sHeaderName = \trim($sHeaderName);
if (0 < \strlen($sHeaderName))
{
$this->aHeadersValue[$sHeaderName] = $sValue;
}
return $this;
}
/**
* @param string $sSubject
*
* @return \MailSo\Mime\Message
*/
public function SetSubject($sSubject)
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::SUBJECT] = $sSubject;
return $this;
}
/**
* @param string $sInReplyTo
*
* @return \MailSo\Mime\Message
*/
public function SetInReplyTo($sInReplyTo)
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::IN_REPLY_TO] = $sInReplyTo;
return $this;
}
/**
* @param string $sReferences
*
* @return \MailSo\Mime\Message
*/
public function SetReferences($sReferences)
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::REFERENCES] = $sReferences;
return $this;
}
/**
* @param string $sEmail
*
* @return \MailSo\Mime\Message
*/
public function SetReadConfirmation($sEmail)
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::DISPOSITION_NOTIFICATION_TO] = $sEmail;
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::X_CONFIRM_READING_TO] = $sEmail;
return $this;
}
/**
* @param int $iValue
*
* @return \MailSo\Mime\Message
*/
public function SetPriority($iValue)
{
$sResult = '';
switch ($iValue)
{
case \MailSo\Mime\Enumerations\MessagePriority::HIGH:
$sResult = \MailSo\Mime\Enumerations\MessagePriority::HIGH.' (Highest)';
break;
case \MailSo\Mime\Enumerations\MessagePriority::NORMAL:
$sResult = \MailSo\Mime\Enumerations\MessagePriority::NORMAL.' (Normal)';
break;
case \MailSo\Mime\Enumerations\MessagePriority::LOW:
$sResult = \MailSo\Mime\Enumerations\MessagePriority::LOW.' (Lowest)';
break;
}
if (0 < \strlen($sResult))
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::X_PRIORITY] = $sResult;
}
return $this;
}
/**
* @param int $iValue
*
* @return \MailSo\Mime\Message
*/
public function SetSensitivity($iValue)
{
$sResult = '';
switch ($iValue)
{
case \MailSo\Mime\Enumerations\Sensitivity::CONFIDENTIAL:
$sResult = 'Company-Confidential';
break;
case \MailSo\Mime\Enumerations\Sensitivity::PERSONAL:
$sResult = 'Personal';
break;
case \MailSo\Mime\Enumerations\Sensitivity::PRIVATE_:
$sResult = 'Private';
break;
}
if (0 < \strlen($sResult))
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::SENSITIVITY] = $sResult;
}
return $this;
}
/**
* @param string $sXMailer
*
* @return \MailSo\Mime\Message
*/
public function SetXMailer($sXMailer)
{
$this->sCustomXMailer = $sXMailer;
return $this;
}
/**
* @param \MailSo\Mime\Email $oEmail
*
* @return \MailSo\Mime\Message
*/
public function SetFrom(\MailSo\Mime\Email $oEmail)
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::FROM_] = $oEmail;
return $this;
}
/**
* @param \MailSo\Mime\EmailCollection $oEmails
*
* @return \MailSo\Mime\Message
*/
public function SetTo(\MailSo\Mime\EmailCollection $oEmails)
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::TO_] = $oEmails;
return $this;
}
/**
* @param \MailSo\Mime\EmailCollection $oEmails
*
* @return \MailSo\Mime\Message
*/
public function SetReplyTo(\MailSo\Mime\EmailCollection $oEmails)
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::REPLY_TO] = $oEmails;
return $this;
}
/**
* @param \MailSo\Mime\EmailCollection $oEmails
*
* @return \MailSo\Mime\Message
*/
public function SetCc(\MailSo\Mime\EmailCollection $oEmails)
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::CC] = $oEmails;
return $this;
}
/**
* @param \MailSo\Mime\EmailCollection $oEmails
*
* @return \MailSo\Mime\Message
*/
public function SetBcc(\MailSo\Mime\EmailCollection $oEmails)
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::BCC] = $oEmails;
return $this;
}
/**
* @param \MailSo\Mime\EmailCollection $oEmails
*
* @return \MailSo\Mime\Message
*/
public function SetSender(\MailSo\Mime\EmailCollection $oEmails)
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::SENDER] = $oEmails;
return $this;
}
/**
* @param string $sType
* @param string $sUid
* @param string $sFolder
*
* @return \MailSo\Mime\Message
*/
public function SetDraftInfo($sType, $sUid, $sFolder)
{
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::X_DRAFT_INFO] = \MailSo\Mime\ParameterCollection::NewInstance()
->Add(\MailSo\Mime\Parameter::NewInstance('type', $sType))
->Add(\MailSo\Mime\Parameter::NewInstance('uid', $sUid))
->Add(\MailSo\Mime\Parameter::NewInstance('folder', base64_encode($sFolder)))
;
return $this;
}
/**
* @param string $sPlain
*
* @return \MailSo\Mime\Message
*/
public function AddPlain($sPlain)
{
return $this->AddAlternative(
\MailSo\Mime\Enumerations\MimeType::TEXT_PLAIN, trim($sPlain),
\MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE);
}
/**
* @param string $sHtml
*
* @return \MailSo\Mime\Message
*/
public function AddHtml($sHtml)
{
return $this->AddAlternative(
\MailSo\Mime\Enumerations\MimeType::TEXT_HTML, trim($sHtml),
\MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE);
}
/**
* @param string $sHtmlOrPlainText
* @param bool $bIsHtml = false
*
* @return \MailSo\Mime\Message
*/
public function AddText($sHtmlOrPlainText, $bIsHtml = false)
{
return $bIsHtml ? $this->AddHtml($sHtmlOrPlainText) : $this->AddPlain($sHtmlOrPlainText);
}
/**
* @param string $sContentType
* @param string|resource $mData
* @param string $sContentTransferEncoding = ''
* @param array $aCustomContentTypeParams = array()
*
* @return \MailSo\Mime\Message
*/
public function AddAlternative($sContentType, $mData, $sContentTransferEncoding = '', $aCustomContentTypeParams = array())
{
$this->aAlternativeParts[] = array($sContentType, $mData, $sContentTransferEncoding, $aCustomContentTypeParams);
return $this;
}
/**
* @return string
*/
private function generateNewBoundary()
{
return '----=_Part_'.rand(100, 999).'_'.rand(100000000, 999999999).'.'.time();
}
/**
* @param string $sHostName = ''
*
* @return string
*/
private function generateNewMessageId($sHostName = '')
{
if (0 === strlen($sHostName))
{
$sHostName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'mailso';
}
return '<'.md5(rand(100000, 999999).time().$sHostName).'@'.$sHostName.'>';
}
/**
* @param \MailSo\Mime\Attachment $oAttachment
*
* @return \MailSo\Mime\Part
*/
private function createNewMessageAttachmentBody($oAttachment)
{
$oAttachmentPart = Part::NewInstance();
$sFileName = $oAttachment->FileName();
$sCID = $oAttachment->CID();
$oContentTypeParameters = null;
$oContentDispositionParameters = null;
if (0 < strlen(trim($sFileName)))
{
$oContentTypeParameters =
ParameterCollection::NewInstance()->Add(Parameter::NewInstance(
\MailSo\Mime\Enumerations\Parameter::NAME, $sFileName));
$oContentDispositionParameters =
ParameterCollection::NewInstance()->Add(Parameter::NewInstance(
\MailSo\Mime\Enumerations\Parameter::FILENAME, $sFileName));
}
$oAttachmentPart->Headers->Add(
Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
$oAttachment->ContentType().';'.
(($oContentTypeParameters) ? ' '.$oContentTypeParameters->ToString() : '')
)
);
$oAttachmentPart->Headers->Add(
Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_DISPOSITION,
($oAttachment->IsInline() ? 'inline' : 'attachment').';'.
(($oContentDispositionParameters) ? ' '.$oContentDispositionParameters->ToString() : '')
)
);
if (0 < strlen($sCID))
{
$oAttachmentPart->Headers->Add(
Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_ID, $sCID)
);
}
$oAttachmentPart->Body = $oAttachment->Resource();
if ('message/rfc822' !== strtolower($oAttachment->ContentType()))
{
$oAttachmentPart->Headers->Add(
Header::NewInstance(
\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING,
\MailSo\Base\Enumerations\Encoding::BASE64
)
);
if (is_resource($oAttachmentPart->Body))
{
$oAttachmentPart->Body =
\MailSo\Base\StreamWrappers\Binary::CreateStream($oAttachmentPart->Body,
\MailSo\Base\StreamWrappers\Binary::GetInlineDecodeOrEncodeFunctionName(
\MailSo\Base\Enumerations\Encoding::BASE64, false));
}
}
return $oAttachmentPart;
}
/**
* @param array $aAlternativeData
*
* @return \MailSo\Mime\Part
*/
private function createNewMessageAlternativePartBody($aAlternativeData)
{
$oAlternativePart = null;
if (is_array($aAlternativeData) && isset($aAlternativeData[0]))
{
$oAlternativePart = Part::NewInstance();
$oParameters = ParameterCollection::NewInstance();
$oParameters->Add(
Parameter::NewInstance(
\MailSo\Mime\Enumerations\Parameter::CHARSET,
\MailSo\Base\Enumerations\Charset::UTF_8)
);
if (isset($aAlternativeData[3]) && \is_array($aAlternativeData[3]) && 0 < \count($aAlternativeData[3]))
{
foreach ($aAlternativeData[3] as $sName => $sValue)
{
$oParameters->Add(Parameter::NewInstance($sName, $sValue));
}
}
$oAlternativePart->Headers->Add(
Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
$aAlternativeData[0].'; '.$oParameters->ToString())
);
$oAlternativePart->Body = null;
if (isset($aAlternativeData[1]))
{
if (is_resource($aAlternativeData[1]))
{
$oAlternativePart->Body = $aAlternativeData[1];
}
else if (is_string($aAlternativeData[1]) && 0 < strlen($aAlternativeData[1]))
{
$oAlternativePart->Body =
\MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString($aAlternativeData[1]);
}
}
if (isset($aAlternativeData[2]) && 0 < strlen($aAlternativeData[2]))
{
$oAlternativePart->Headers->Add(
Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING,
$aAlternativeData[2]
)
);
if (is_resource($oAlternativePart->Body))
{
$oAlternativePart->Body =
\MailSo\Base\StreamWrappers\Binary::CreateStream($oAlternativePart->Body,
\MailSo\Base\StreamWrappers\Binary::GetInlineDecodeOrEncodeFunctionName(
$aAlternativeData[2], false));
}
}
if (!is_resource($oAlternativePart->Body))
{
$oAlternativePart->Body =
\MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString('');
}
}
return $oAlternativePart;
}
/**
* @param \MailSo\Mime\Part $oPlainPart
* @param \MailSo\Mime\Part $oHtmlPart
*
* @return \MailSo\Mime\Part
*/
private function createNewMessageSimpleOrAlternativeBody()
{
$oResultPart = null;
if (1 < count($this->aAlternativeParts))
{
$oResultPart = Part::NewInstance();
$oResultPart->Headers->Add(
Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
\MailSo\Mime\Enumerations\MimeType::MULTIPART_ALTERNATIVE.'; '.
ParameterCollection::NewInstance()->Add(
Parameter::NewInstance(
\MailSo\Mime\Enumerations\Parameter::BOUNDARY,
$this->generateNewBoundary())
)->ToString()
)
);
foreach ($this->aAlternativeParts as $aAlternativeData)
{
$oAlternativePart = $this->createNewMessageAlternativePartBody($aAlternativeData);
if ($oAlternativePart)
{
$oResultPart->SubParts->Add($oAlternativePart);
}
unset($oAlternativePart);
}
}
else if (1 === count($this->aAlternativeParts))
{
$oAlternativePart = $this->createNewMessageAlternativePartBody($this->aAlternativeParts[0]);
if ($oAlternativePart)
{
$oResultPart = $oAlternativePart;
}
}
if (!$oResultPart)
{
if ($this->bAddEmptyTextPart)
{
$oResultPart = $this->createNewMessageAlternativePartBody(array(
\MailSo\Mime\Enumerations\MimeType::TEXT_PLAIN, null
));
}
else
{
$aAttachments = $this->oAttachmentCollection->CloneAsArray();
if (1 === count($aAttachments) && isset($aAttachments[0]))
{
$this->oAttachmentCollection->Clear();
$oResultPart = $this->createNewMessageAlternativePartBody(array(
$aAttachments[0]->ContentType(), $aAttachments[0]->Resource(),
'', $aAttachments[0]->CustomContentTypeParams()
));
}
}
}
return $oResultPart;
}
/**
* @param \MailSo\Mime\Part $oIncPart
*
* @return \MailSo\Mime\Part
*/
private function createNewMessageRelatedBody($oIncPart)
{
$oResultPart = null;
$aAttachments = $this->oAttachmentCollection->LinkedAttachments();
if (0 < count($aAttachments))
{
$oResultPart = Part::NewInstance();
$oResultPart->Headers->Add(
Header::NewInstance(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
\MailSo\Mime\Enumerations\MimeType::MULTIPART_RELATED.'; '.
ParameterCollection::NewInstance()->Add(
Parameter::NewInstance(
\MailSo\Mime\Enumerations\Parameter::BOUNDARY,
$this->generateNewBoundary())
)->ToString()
)
);
$oResultPart->SubParts->Add($oIncPart);
foreach ($aAttachments as $oAttachment)
{
$oResultPart->SubParts->Add($this->createNewMessageAttachmentBody($oAttachment));
}
}
else
{
$oResultPart = $oIncPart;
}
return $oResultPart;
}
/**
* @param \MailSo\Mime\Part $oIncPart
*
* @return \MailSo\Mime\Part
*/
private function createNewMessageMixedBody($oIncPart)
{
$oResultPart = null;
$aAttachments = $this->oAttachmentCollection->UnlinkedAttachments();
if (0 < count($aAttachments))
{
$oResultPart = Part::NewInstance();
$oResultPart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
\MailSo\Mime\Enumerations\MimeType::MULTIPART_MIXED.'; '.
ParameterCollection::NewInstance()->Add(
Parameter::NewInstance(
\MailSo\Mime\Enumerations\Parameter::BOUNDARY,
$this->generateNewBoundary())
)->ToString()
);
$oResultPart->SubParts->Add($oIncPart);
foreach ($aAttachments as $oAttachment)
{
$oResultPart->SubParts->Add($this->createNewMessageAttachmentBody($oAttachment));
}
}
else
{
$oResultPart = $oIncPart;
}
return $oResultPart;
}
/**
* @param \MailSo\Mime\Part $oIncPart
* @param bool $bWithoutBcc = false
*
* @return \MailSo\Mime\Part
*/
private function setDefaultHeaders($oIncPart, $bWithoutBcc = false)
{
$oIncPart->Headers->SetByName(\MailSo\Mime\Enumerations\Header::DATE, \gmdate('r'), true);
if (0 < \strlen($this->sMessageId))
{
$oIncPart->Headers->SetByName(\MailSo\Mime\Enumerations\Header::MESSAGE_ID, $this->sMessageId, true);
}
$oIncPart->Headers->SetByName(\MailSo\Mime\Enumerations\Header::X_MAILER,
0 === \strlen($this->sCustomXMailer) ? \MailSo\Version::XMailer() : $this->sCustomXMailer, true);
$oIncPart->Headers->SetByName(\MailSo\Mime\Enumerations\Header::MIME_VERSION, '1.0', true);
foreach ($this->aHeadersValue as $sName => $mValue)
{
if (\is_object($mValue))
{
if ($mValue instanceof \MailSo\Mime\EmailCollection || $mValue instanceof \MailSo\Mime\Email ||
$mValue instanceof \MailSo\Mime\ParameterCollection)
{
$mValue = $mValue->ToString();
}
}
if (!($bWithoutBcc && \strtolower(\MailSo\Mime\Enumerations\Header::BCC) === \strtolower($sName)))
{
$oIncPart->Headers->SetByName($sName, (string) $mValue);
}
}
return $oIncPart;
}
/**
* @param bool $bWithoutBcc = false
*
* @return \MailSo\Mime\Part
*/
public function ToPart($bWithoutBcc = false)
{
$oPart = $this->createNewMessageSimpleOrAlternativeBody();
$oPart = $this->createNewMessageRelatedBody($oPart);
$oPart = $this->createNewMessageMixedBody($oPart);
$oPart = $this->setDefaultHeaders($oPart, $bWithoutBcc);
return $oPart;
}
/**
* @param bool $bWithoutBcc = false
*
* @return resource
*/
public function ToStream($bWithoutBcc = false)
{
return $this->ToPart($bWithoutBcc)->ToStream();
}
/**
* @param bool $bWithoutBcc = false
*
* @return string
*/
public function ToString($bWithoutBcc = false)
{
return \stream_get_contents($this->ToStream($bWithoutBcc));
}
}

View file

@ -0,0 +1,132 @@
<?php
namespace MailSo\Mime;
/**
* @category MailSo
* @package Mime
*/
class Parameter
{
/**
* @var string
*/
private $sName;
/**
* @var string
*/
private $sValue;
/**
* @access private
*
* @param string $sName
* @param string $sValue
*/
private function __construct($sName, $sValue)
{
$this->sName = $sName;
$this->sValue = $sValue;
}
/**
* @param string $sName
* @param string $sValue = ''
*
* @return \MailSo\Mime\Parameter
*/
public static function NewInstance($sName, $sValue = '')
{
return new self($sName, $sValue);
}
/**
* @param string $sName
* @param string $sValue = ''
*
* @return \MailSo\Mime\Parameter
*/
public static function CreateFromParameterLine($sRawParam)
{
$oParameter = self::NewInstance('');
return $oParameter->Parse($sRawParam);
}
/**
* @return \MailSo\Mime\Parameter
*/
public function Reset()
{
$this->sName = '';
$this->sValue = '';
return $this;
}
/**
* @return string
*/
public function Name()
{
return $this->sName;
}
/**
* @return string
*/
public function Value()
{
return $this->sValue;
}
/**
* @param string $sRawParam
* @param string $sSeparator = '='
*
* @return \MailSo\Mime\Parameter
*/
public function Parse($sRawParam, $sSeparator = '=')
{
$this->Reset();
$aParts = explode($sSeparator, $sRawParam, 2);
$this->sName = trim(trim($aParts[0]), '"\'');
if (2 === count($aParts))
{
$this->sValue = trim(trim($aParts[1]), '"\'');
}
return $this;
}
/**
* @param bool $bConvertSpecialsName = false
*
* @return string
*/
public function ToString($bConvertSpecialsName = false)
{
$sResult = '';
if (0 < strlen($this->sName))
{
$sResult = $this->sName.'=';
if ($bConvertSpecialsName && in_array(strtolower($this->sName), array(
strtolower(\MailSo\Mime\Enumerations\Parameter::NAME),
strtolower(\MailSo\Mime\Enumerations\Parameter::FILENAME)
)))
{
$sResult .= '"'.\MailSo\Base\Utils::EncodeUnencodedValue(
\MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
$this->sValue).'"';
}
else
{
$sResult .= '"'.$this->sValue.'"';
}
}
return $sResult;
}
}

View file

@ -0,0 +1,197 @@
<?php
namespace MailSo\Mime;
/**
* @category MailSo
* @package Mime
*/
class ParameterCollection extends \MailSo\Base\Collection
{
/**
* @access protected
*
* @param string $sRawParams = ''
*/
protected function __construct($sRawParams = '')
{
parent::__construct();
if (0 < strlen($sRawParams))
{
$this->Parse($sRawParams);
}
}
/**
* @param string $sRawParams = ''
*
* @return \MailSo\Mime\ParameterCollection
*/
public static function NewInstance($sRawParams = '')
{
return new self($sRawParams);
}
/**
* @return \MailSo\Mime\Parameter|null
*/
public function &GetByIndex($iIndex)
{
$mResult = null;
$mResult =& parent::GetByIndex($iIndex);
return $mResult;
}
/**
* @param array $aList
*
* @return \MailSo\Mime\ParameterCollection
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public function SetAsArray($aList)
{
parent::SetAsArray($aList);
return $this;
}
/**
* @param string $sName
*
* @return string
*/
public function ParameterValueByName($sName)
{
$sResult = '';
$sName = trim($sName);
$aParams =& $this->GetAsArray();
foreach ($aParams as /* @var $oParam \MailSo\Mime\ParameterCollection */ $oParam)
{
if (strtolower($sName) === strtolower($oParam->Name()))
{
$sResult = $oParam->Value();
break;
}
}
return $sResult;
}
/**
* @param string $sRawParams
*
* @return \MailSo\Mime\ParameterCollection
*/
public function Parse($sRawParams)
{
$this->Clear();
$aDataToParse = explode(';', $sRawParams);
foreach ($aDataToParse as $sParam)
{
$this->Add(Parameter::CreateFromParameterLine($sParam));
}
$this->reParseParameters();
return $this;
}
/**
* @param bool $bConvertSpecialsName = false
*
* @return string
*/
public function ToString($bConvertSpecialsName = false)
{
$aResult = array();
$aParams =& $this->GetAsArray();
foreach ($aParams as /* @var $oParam \MailSo\Mime\Parameter */ $oParam)
{
$sLine = $oParam->ToString($bConvertSpecialsName);
if (0 < strlen($sLine))
{
$aResult[] = $sLine;
}
}
return 0 < count($aResult) ? implode('; ', $aResult) : '';
}
/**
* @return void
*/
private function reParseParameters()
{
$aDataToReParse = $this->CloneAsArray();
$sCharset = \MailSo\Base\Enumerations\Charset::UTF_8;
$this->Clear();
$aPreParams = array();
foreach ($aDataToReParse as /* @var $oParam \MailSo\Mime\Parameter */ $oParam)
{
$aMatch = array();
$sParamName = $oParam->Name();
if (preg_match('/([^\*]+)\*([\d]{1,2})\*/', $sParamName, $aMatch) && isset($aMatch[1], $aMatch[2])
&& 0 < strlen($aMatch[1]) && is_numeric($aMatch[2]))
{
if (!isset($aPreParams[$aMatch[1]]))
{
$aPreParams[$aMatch[1]] = array();
}
$sValue = $oParam->Value();
$aValueParts = explode('\'\'', $sValue, 2);
if (is_array($aValueParts) && 2 === count($aValueParts) && 0 < strlen($aValueParts[1]))
{
$sCharset = $aValueParts[0];
$sValue = $aValueParts[1];
}
$aPreParams[$aMatch[1]][(int) $aMatch[2]] = $sValue;
}
else if (preg_match('/([^\*]+)\*/', $sParamName, $aMatch) && isset($aMatch[1]))
{
if (!isset($aPreParams[$aMatch[1]]))
{
$aPreParams[$aMatch[1]] = array();
}
$sValue = $oParam->Value();
$aValueParts = explode('\'\'', $sValue, 2);
if (is_array($aValueParts) && 2 === count($aValueParts) && 0 < strlen($aValueParts[1]))
{
$sCharset = $aValueParts[0];
$sValue = $aValueParts[1];
}
$aPreParams[$aMatch[1]][0] = $sValue;
}
else
{
$this->Add($oParam);
}
}
foreach ($aPreParams as $sName => $aValues)
{
ksort($aValues);
$sResult = implode(array_values($aValues));
$sResult = urldecode($sResult);
if (0 < strlen($sCharset))
{
$sResult = \MailSo\Base\Utils::ConvertEncoding($sResult,
$sCharset, \MailSo\Base\Enumerations\Charset::UTF_8);
}
$this->Add(Parameter::NewInstance($sName, $sResult));
}
}
}

View file

@ -0,0 +1,72 @@
<?php
namespace MailSo\Mime\Parser;
/**
* @category MailSo
* @package Mime
* @subpackage Parser
*/
class ParserEmpty implements ParserInterface
{
/**
* @param \MailSo\Mime\Part $oPart
*
* @return void
*/
public function StartParse(\MailSo\Mime\Part &$oPart)
{
}
/**
* @param \MailSo\Mime\Part $oPart
*
* @return void
*/
public function EndParse(\MailSo\Mime\Part &$oPart)
{
}
/**
* @param \MailSo\Mime\Part $oPart
*
* @return void
*/
public function StartParseMimePart(\MailSo\Mime\Part &$oPart)
{
}
/**
* @param \MailSo\Mime\Part $oMimePart
*
* @return void
*/
public function EndParseMimePart(\MailSo\Mime\Part &$oPart)
{
}
/**
* @return void
*/
public function InitMimePartHeader()
{
}
/**
* @param string $sBuffer
*
* @return void
*/
public function ReadBuffer($sBuffer)
{
}
/**
* @param string $sBuffer
*
* @return void
*/
public function WriteBody($sBuffer)
{
}
}

View file

@ -0,0 +1,57 @@
<?php
namespace MailSo\Mime\Parser;
/**
* @category MailSo
* @package Mime
* @subpackage Parser
*/
interface ParserInterface
{
/**
* @param \MailSo\Mime\Part $oPart
*
* @return void
*/
public function StartParse(\MailSo\Mime\Part &$oPart);
/**
* @param \MailSo\Mime\Part $oPart
*
* @return void
*/
public function EndParse(\MailSo\Mime\Part &$oPart);
/**
* @param \MailSo\Mime\Part $oPart
*
* @return void
*/
public function StartParseMimePart(\MailSo\Mime\Part &$oPart);
/**
* @param \MailSo\Mime\Part $oMimePart
*
* @return void
*/
public function EndParseMimePart(\MailSo\Mime\Part &$oPart);
/**
* @return void
*/
public function InitMimePartHeader();
/**
* @param string $sBuffer
*
* @return void
*/
public function ReadBuffer($sBuffer);
/**
* @param string $sBuffer
* @return void
*/
public function WriteBody($sBuffer);
}

View file

@ -0,0 +1,44 @@
<?php
namespace MailSo\Mime\Parser;
/**
* @category MailSo
* @package Mime
* @subpackage Parser
*/
class ParserMemory extends ParserEmpty implements ParserInterface
{
/**
* @var \MailSo\Mime\Part
*/
protected $oCurrentMime = null;
/**
* @param \MailSo\Mime\Part $oMimePart
*
* @return void
*/
public function StartParseMimePart(\MailSo\Mime\Part &$oPart)
{
$this->oCurrentMime = $oPart;
}
/**
* @param string $sBuffer
*
* @return void
*/
public function WriteBody($sBuffer)
{
if (null === $this->oCurrentMime->Body)
{
$this->oCurrentMime->Body = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
}
if (\is_resource($this->oCurrentMime->Body))
{
\fwrite($this->oCurrentMime->Body, $sBuffer);
}
}
}

View file

@ -0,0 +1,618 @@
<?php
namespace MailSo\Mime;
/**
* @category MailSo
* @package Mime
*/
class Part
{
const POS_HEADERS = 1;
const POS_BODY = 2;
const POS_SUBPARTS = 3;
const POS_CLOSE_BOUNDARY = 4;
const DEFAUL_BUFFER = 8192;
/**
* @var string
*/
public static $DefaultCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1;
/**
* @var string
*/
public static $ForceCharset = '';
/**
* @var \MailSo\Mime\HeaderCollection
*/
public $Headers;
/**
* @var resource
*/
public $Body;
/**
* @var \MailSo\Mime\PartCollection
*/
public $SubParts;
/**
* @var array
*/
public $LineParts;
/**
* @var string
*/
private $sBoundary;
/**
* @var string
*/
private $sParentCharset;
/**
* @var int
*/
private $iParseBuffer;
/**
* @access private
*/
private function __construct()
{
$this->iParseBuffer = \MailSo\Mime\Part::DEFAUL_BUFFER;
$this->Reset();
}
/**
* @return \MailSo\Mime\Part
*/
public static function NewInstance()
{
return new self();
}
/**
* @return \MailSo\Mime\Part
*/
public function Reset()
{
\MailSo\Base\ResourceRegistry::CloseMemoryResource($this->Body);
$this->Body = null;
$this->Headers = HeaderCollection::NewInstance();
$this->SubParts = PartCollection::NewInstance();
$this->LineParts = array();
$this->sBoundary = '';
$this->sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1;
return $this;
}
/**
* @return string
*/
public function Boundary()
{
return $this->sBoundary;
}
/**
* @return string
*/
public function ParentCharset()
{
return (0 < strlen($this->sCharset)) ? $this->sParentCharset : self::$DefaultCharset;
}
/**
* @param string $sParentCharset
* @return \MailSo\Mime\Part
*/
public function SetParentCharset($sParentCharset)
{
$this->sParentCharset = $sParentCharset;
return $this;
}
/**
* @param string $sBoundary
* @return \MailSo\Mime\Part
*/
public function SetBoundary($sBoundary)
{
$this->sBoundary = $sBoundary;
return $this;
}
/**
* @param int $iParseBuffer
* @return \MailSo\Mime\Part
*/
public function SetParseBuffer($iParseBuffer)
{
$this->iParseBuffer = $iParseBuffer;
return $this;
}
/**
* @return string
*/
public function HeaderCharset()
{
return ($this->Headers) ? trim(strtolower($this->Headers->ParameterValue(
\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
\MailSo\Mime\Enumerations\Parameter::CHARSET))) : '';
}
/**
* @return string
*/
public function HeaderBoundary()
{
return ($this->Headers) ? trim($this->Headers->ParameterValue(
\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
\MailSo\Mime\Enumerations\Parameter::BOUNDARY)) : '';
}
/**
* @return string
*/
public function ContentType()
{
return ($this->Headers) ?
trim(strtolower($this->Headers->ValueByName(
\MailSo\Mime\Enumerations\Header::CONTENT_TYPE))) : '';
}
/**
* @return string
*/
public function ContentTransferEncoding()
{
return ($this->Headers) ?
trim(strtolower($this->Headers->ValueByName(
\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING))) : '';
}
/**
* @return string
*/
public function ContentID()
{
return ($this->Headers) ? trim($this->Headers->ValueByName(
\MailSo\Mime\Enumerations\Header::CONTENT_ID)) : '';
}
/**
* @return string
*/
public function ContentLocation()
{
return ($this->Headers) ? trim($this->Headers->ValueByName(
\MailSo\Mime\Enumerations\Header::CONTENT_LOCATION)) : '';
}
/**
* @return string
*/
public function FileName()
{
$sResult = '';
if ($this->Headers)
{
$sResult = trim($this->Headers->ParameterValue(
\MailSo\Mime\Enumerations\Header::CONTENT_DISPOSITION,
\MailSo\Mime\Enumerations\Parameter::FILENAME));
if (0 === strlen($sResult))
{
$sResult = trim($this->Headers->ParameterValue(
\MailSo\Mime\Enumerations\Header::CONTENT_TYPE,
\MailSo\Mime\Enumerations\Parameter::NAME));
}
}
return $sResult;
}
/**
* @param string $sFileName
* @return \MailSo\Mime\Part
*/
public function ParseFromFile($sFileName)
{
$rStreamHandle = (@file_exists($sFileName)) ? @fopen($sFileName, 'rb') : false;
if (is_resource($rStreamHandle))
{
$this->ParseFromStream($rStreamHandle);
if (is_resource($rStreamHandle))
{
fclose($rStreamHandle);
}
}
return $this;
}
/**
* @param string $sRawMessage
* @return \MailSo\Mime\Part
*/
public function ParseFromString($sRawMessage)
{
$rStreamHandle = (0 < strlen($sRawMessage)) ?
\MailSo\Base\ResourceRegistry::CreateMemoryResource() : false;
if (is_resource($rStreamHandle))
{
fwrite($rStreamHandle, $sRawMessage);
unset($sRawMessage);
fseek($rStreamHandle, 0);
$this->ParseFromStream($rStreamHandle);
\MailSo\Base\ResourceRegistry::CloseMemoryResource($rStreamHandle);
}
return $this;
}
/**
* @param resource $rStreamHandle
* @return \MailSo\Mime\Part
*/
public function ParseFromStream($rStreamHandle)
{
$this->Reset();
$oParserClass = new \MailSo\Mime\Parser\ParserMemory();
$oMimePart = null;
$bIsOef = false;
$iOffset = 0;
$sBuffer = '';
$sPrevBuffer = '';
$aBoundaryStack = array();
$oParserClass->StartParse($this);
$this->LineParts[] =& $this;
$this->ParseFromStreamRecursion($rStreamHandle, $oParserClass, $iOffset,
$sPrevBuffer, $sBuffer, $aBoundaryStack, $bIsOef);
$sFirstNotNullCharset = null;
foreach ($this->LineParts as /* @var $oMimePart \MailSo\Mime\Part */ &$oMimePart)
{
$sCharset = $oMimePart->HeaderCharset();
if (0 < strlen($sCharset))
{
$sFirstNotNullCharset = $sCharset;
break;
}
}
$sForceCharset = self::$ForceCharset;
if (0 < strlen($sForceCharset))
{
foreach ($this->LineParts as /* @var $oMimePart \MailSo\Mime\Part */ &$oMimePart)
{
$oMimePart->SetParentCharset($sForceCharset);
$oMimePart->Headers->SetParentCharset($sForceCharset);
}
}
else
{
$sFirstNotNullCharset = (null !== $sFirstNotNullCharset)
? $sFirstNotNullCharset : self::$DefaultCharset;
foreach ($this->LineParts as /* @var $oMimePart \MailSo\Mime\Part */ &$oMimePart)
{
$sHeaderCharset = $oMimePart->HeaderCharset();
$oMimePart->SetParentCharset((0 < strlen($sHeaderCharset)) ? $sHeaderCharset : $sFirstNotNullCharset);
$oMimePart->Headers->SetParentCharset($sHeaderCharset);
}
}
$oParserClass->EndParse($this);
return $this;
}
/**
* @param resource $rStreamHandle
* @return \MailSo\Mime\Part
*/
public function ParseFromStreamRecursion($rStreamHandle, &$oCallbackClass, &$iOffset,
&$sPrevBuffer, &$sBuffer, &$aBoundaryStack, &$bIsOef, $bNotFirstRead = false)
{
$oCallbackClass->StartParseMimePart($this);
$iPos = 0;
$iParsePosition = self::POS_HEADERS;
$sCurrentBoundary = '';
$bIsBoundaryCheck = false;
$aHeadersLines = array();
while (true)
{
if (!$bNotFirstRead)
{
$sPrevBuffer = $sBuffer;
$sBuffer = '';
}
if (!$bIsOef && !feof($rStreamHandle))
{
if (!$bNotFirstRead)
{
$sBuffer = @fread($rStreamHandle, $this->iParseBuffer);
if (false === $sBuffer)
{
break;
}
$oCallbackClass->ReadBuffer($sBuffer);
}
else
{
$bNotFirstRead = false;
}
}
else if ($bIsOef && 0 === strlen($sBuffer))
{
break;
}
else
{
$bIsOef = true;
}
while (true)
{
$sCurrentLine = $sPrevBuffer.$sBuffer;
if (self::POS_HEADERS === $iParsePosition)
{
$iEndLen = 4;
$iPos = strpos($sCurrentLine, "\r\n\r\n", $iOffset);
if (false === $iPos)
{
$iEndLen = 2;
$iPos = strpos($sCurrentLine, "\n\n", $iOffset);
}
if (false !== $iPos)
{
$aHeadersLines[] = substr($sCurrentLine, $iOffset, $iPos + $iEndLen - $iOffset);
$this->Headers->Parse(implode($aHeadersLines))->SetParentCharset($this->HeaderCharset());
$aHeadersLines = array();
$oCallbackClass->InitMimePartHeader();
$sBoundary = $this->HeaderBoundary();
if (0 < strlen($sBoundary))
{
$sBoundary = '--'.$sBoundary;
$sCurrentBoundary = $sBoundary;
array_unshift($aBoundaryStack, $sBoundary);
}
$iOffset = $iPos + $iEndLen;
$iParsePosition = self::POS_BODY;
continue;
}
else
{
$iBufferLen = strlen($sPrevBuffer);
if ($iBufferLen > $iOffset)
{
$aHeadersLines[] = substr($sPrevBuffer, $iOffset);
$iOffset = 0;
}
else
{
$iOffset -= $iBufferLen;
}
break;
}
}
else if (self::POS_BODY === $iParsePosition)
{
$iPos = false;
$sBoundaryLen = 0;
$bIsBoundaryEnd = false;
$bCurrentPartBody = false;
$bIsBoundaryCheck = 0 < count($aBoundaryStack);
foreach ($aBoundaryStack as $sKey => $sBoundary)
{
if (false !== ($iPos = strpos($sCurrentLine, $sBoundary, $iOffset)))
{
if ($sCurrentBoundary === $sBoundary)
{
$bCurrentPartBody = true;
}
$sBoundaryLen = strlen($sBoundary);
if ('--' === substr($sCurrentLine, $iPos + $sBoundaryLen, 2))
{
$sBoundaryLen += 2;
$bIsBoundaryEnd = true;
unset($aBoundaryStack[$sKey]);
$sCurrentBoundary = (isset($aBoundaryStack[$sKey + 1]))
? $aBoundaryStack[$sKey + 1] : '';
}
break;
}
}
if (false !== $iPos)
{
$oCallbackClass->WriteBody(substr($sCurrentLine, $iOffset, $iPos - $iOffset));
$iOffset = $iPos;
if ($bCurrentPartBody)
{
$iParsePosition = self::POS_SUBPARTS;
continue;
}
$oCallbackClass->EndParseMimePart($this);
return true;
}
else
{
$iBufferLen = strlen($sPrevBuffer);
if ($iBufferLen > $iOffset)
{
$oCallbackClass->WriteBody(substr($sPrevBuffer, $iOffset));
$iOffset = 0;
}
else
{
$iOffset -= $iBufferLen;
}
break;
}
}
else if (self::POS_SUBPARTS === $iParsePosition)
{
$iPos = false;
$sBoundaryLen = 0;
$bIsBoundaryEnd = false;
$bCurrentPartBody = false;
$bIsBoundaryCheck = 0 < count($aBoundaryStack);
foreach ($aBoundaryStack as $sKey => $sBoundary)
{
if (false !== ($iPos = strpos($sCurrentLine, $sBoundary, $iOffset)))
{
if ($sCurrentBoundary === $sBoundary)
{
$bCurrentPartBody = true;
}
$sBoundaryLen = strlen($sBoundary);
if ('--' === substr($sCurrentLine, $iPos + $sBoundaryLen, 2))
{
$sBoundaryLen += 2;
$bIsBoundaryEnd = true;
unset($aBoundaryStack[$sKey]);
$sCurrentBoundary = (isset($aBoundaryStack[$sKey + 1]))
? $aBoundaryStack[$sKey + 1] : '';
}
break;
}
}
if (false !== $iPos && $bCurrentPartBody)
{
$iOffset = $iPos + $sBoundaryLen;
$oSubPart = self::NewInstance();
$oSubPart
->SetParseBuffer($this->iParseBuffer)
->ParseFromStreamRecursion($rStreamHandle, $oCallbackClass,
$iOffset, $sPrevBuffer, $sBuffer, $aBoundaryStack, $bIsOef, true);
$this->SubParts->Add($oSubPart);
$this->LineParts[] =& $oSubPart;
//$iParsePosition = self::POS_HEADERS;
unset($oSubPart);
}
else
{
$oCallbackClass->EndParseMimePart($this);
return true;
}
}
}
}
if (0 < strlen($sPrevBuffer))
{
if (self::POS_HEADERS === $iParsePosition)
{
$aHeadersLines[] = ($iOffset < strlen($sPrevBuffer))
? substr($sPrevBuffer, $iOffset)
: $sPrevBuffer;
$this->Headers->Parse(implode($aHeadersLines))->SetParentCharset($this->HeaderCharset());
$aHeadersLines = array();
$oCallbackClass->InitMimePartHeader();
}
else if (self::POS_BODY === $iParsePosition)
{
if (!$bIsBoundaryCheck)
{
$oCallbackClass->WriteBody(($iOffset < strlen($sPrevBuffer))
? substr($sPrevBuffer, $iOffset) : $sPrevBuffer);
}
}
}
else
{
if (self::POS_HEADERS === $iParsePosition && 0 < count($aHeadersLines))
{
$this->Headers->Parse(implode($aHeadersLines))->SetParentCharset($this->HeaderCharset());
$aHeadersLines = array();
$oCallbackClass->InitMimePartHeader();
}
}
$oCallbackClass->EndParseMimePart($this);
return $this;
}
/**
* @return resorce
*/
public function ToStream()
{
$aSubStreams = array(
$this->Headers->ToEncodedString().
\MailSo\Mime\Enumerations\Constants::CRLF.
\MailSo\Mime\Enumerations\Constants::CRLF,
null === $this->Body ? '' : $this->Body,
\MailSo\Mime\Enumerations\Constants::CRLF
);
if (0 < $this->SubParts->Count())
{
$sBoundary = $this->HeaderBoundary();
if (0 < strlen($sBoundary))
{
$aSubStreams[] = '--'.$sBoundary.\MailSo\Mime\Enumerations\Constants::CRLF;
$rSubPartsStream = $this->SubParts->ToStream($sBoundary);
if (is_resource($rSubPartsStream))
{
$aSubStreams[] = $rSubPartsStream;
}
$aSubStreams[] = \MailSo\Mime\Enumerations\Constants::CRLF.
'--'.$sBoundary.'--'.\MailSo\Mime\Enumerations\Constants::CRLF;
}
}
return \MailSo\Base\StreamWrappers\SubStreams::CreateStream($aSubStreams);
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace MailSo\Mime;
/**
* @category MailSo
* @package Mime
*/
class PartCollection extends \MailSo\Base\Collection
{
/**
* @access protected
*/
protected function __construct()
{
parent::__construct();
}
/**
* @return \MailSo\Mime\PartCollection
*/
public static function NewInstance()
{
return new self();
}
/**
* @param string $sBoundary
*
* @return resorce
*/
public function ToStream($sBoundary)
{
$rResult = null;
if (0 < strlen($sBoundary))
{
$aResult = array();
$aParts =& $this->GetAsArray();
foreach ($aParts as /* @var $oPart \MailSo\Mime\Part */ &$oPart)
{
if (0 < count($aResult))
{
$aResult[] = \MailSo\Mime\Enumerations\Constants::CRLF.
'--'.$sBoundary.\MailSo\Mime\Enumerations\Constants::CRLF;
}
$aResult[] = $oPart->ToStream();
}
return \MailSo\Base\StreamWrappers\SubStreams::CreateStream($aResult);
}
return $rResult;
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace MailSo\Net\Enumerations;
/**
* @category MailSo
* @package Net
* @subpackage Enumerations
*/
class ConnectionSecurityType
{
const NONE = 0;
const SSL = 1;
const STARTTLS = 2;
const AUTO_DETECT = 9;
/**
* @param int $iPort
* @param int $iSecurityType
*
* @return bool
*/
public static function UseSSL($iPort, $iSecurityType)
{
$iPort = (int) $iPort;
$iResult = (int) $iSecurityType;
if (self::AUTO_DETECT === $iSecurityType)
{
switch (true)
{
case 993 === $iPort:
case 995 === $iPort:
case 465 === $iPort:
$iResult = self::SSL;
break;
}
}
if (self::SSL === $iResult && !\in_array('ssl', \stream_get_transports()))
{
$iResult = self::NONE;
}
return self::SSL === $iResult;
}
/**
* @param bool $bSupported
* @param int $iSecurityType
* @param bool $bHasSupportedAuth = true
*
* @return bool
*/
public static function UseStartTLS($bSupported, $iSecurityType, $bHasSupportedAuth = true)
{
return ($bSupported &&
(self::STARTTLS === $iSecurityType || (self::AUTO_DETECT === $iSecurityType && !$bHasSupportedAuth)) &&
\defined('STREAM_CRYPTO_METHOD_TLS_CLIENT') && \MailSo\Base\Utils::FunctionExistsAndEnabled('stream_socket_enable_crypto'));
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Net\Exceptions;
/**
* @category MailSo
* @package Net
* @subpackage Exceptions
*/
class ConnectionException extends \MailSo\Net\Exceptions\Exception {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Net\Exceptions;
/**
* @category MailSo
* @package Net
* @subpackage Exceptions
*/
class Exception extends \MailSo\Base\Exceptions\Exception {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Net\Exceptions;
/**
* @category MailSo
* @package Net
* @subpackage Exceptions
*/
class InvalidArgumentException extends \MailSo\Net\Exceptions\Exception {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Net\Exceptions;
/**
* @category MailSo
* @package Net
* @subpackage Exceptions
*/
class SocketAlreadyConnectedException extends \MailSo\Net\Exceptions\ConnectionException {}

View file

@ -0,0 +1,52 @@
<?php
namespace MailSo\Net\Exceptions;
/**
* @category MailSo
* @package Net
* @subpackage Exceptions
*/
class SocketCanNotConnectToHostException extends \MailSo\Net\Exceptions\ConnectionException
{
/**
* @var string
*/
private $sSocketMessage;
/**
* @var int
*/
private $iSocketCode;
/**
* @param string $sSocketMessage = ''
* @param int $iSocketCode = 0
* @param string $sMessage = ''
* @param int $iCode = 0
* @param \Exception $oPrevious = null
*/
public function __construct($sSocketMessage = '', $iSocketCode = 0, $sMessage = '', $iCode = 0, $oPrevious = null)
{
parent::__construct($sMessage, $iCode, $oPrevious);
$this->sSocketMessage = $sSocketMessage;
$this->iSocketCode = $iSocketCode;
}
/**
* @return string
*/
public function getSocketMessage()
{
return $this->sSocketMessage;
}
/**
* @return int
*/
public function getSocketCode()
{
return $this->sSocketMessage;
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Net\Exceptions;
/**
* @category MailSo
* @package Net
* @subpackage Exceptions
*/
class SocketConnectionDoesNotAvailableException extends \MailSo\Net\Exceptions\ConnectionException {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Net\Exceptions;
/**
* @category MailSo
* @package Net
* @subpackage Exceptions
*/
class SocketReadException extends \MailSo\Net\Exceptions\Exception {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Net\Exceptions;
/**
* @category MailSo
* @package Net
* @subpackage Exceptions
*/
class SocketReadTimeoutException extends \MailSo\Net\Exceptions\Exception {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Net\Exceptions;
/**
* @category MailSo
* @package Net
* @subpackage Exceptions
*/
class SocketUnreadBufferException extends \MailSo\Net\Exceptions\Exception {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Net\Exceptions;
/**
* @category MailSo
* @package Net
* @subpackage Exceptions
*/
class SocketUnsuppoterdSecureConnectionException extends \MailSo\Net\Exceptions\ConnectionException {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Net\Exceptions;
/**
* @category MailSo
* @package Net
* @subpackage Exceptions
*/
class SocketWriteException extends \MailSo\Net\Exceptions\Exception {}

View file

@ -0,0 +1,487 @@
<?php
namespace MailSo\Net;
/**
* @category MailSo
* @package Net
*/
abstract class NetClient
{
/**
* @var resource
*/
protected $rConnect;
/**
* @var bool
*/
protected $bUnreadBuffer;
/**
* @var string
*/
protected $sResponseBuffer;
/**
* @var int
*/
protected $iSecurityType;
/**
* @var string
*/
protected $sConnectedHost;
/**
* @var int
*/
protected $iConnectedPort;
/**
* @var bool
*/
protected $bSecure;
/**
* @var int
*/
protected $iConnectTimeOut;
/**
* @var int
*/
protected $iSocketTimeOut;
/**
* @var int
*/
protected $iStartConnectTime;
/**
* @var \MailSo\Log\Logger
*/
protected $oLogger;
/**
* @access protected
*/
protected function __construct()
{
$this->rConnect = null;
$this->bUnreadBuffer = false;
$this->oLogger = null;
$this->sResponseBuffer = '';
$this->iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::NONE;
$this->sConnectedHost = '';
$this->iConnectedPort = 0;
$this->bSecure = false;
$this->iConnectTimeOut = 10;
$this->iSocketTimeOut = 10;
$this->Clear();
}
/**
* @return void
*/
public function __destruct()
{
$this->LogoutAndDisconnect();
}
/**
* @return void
*/
public function Clear()
{
$this->sResponseBuffer = '';
$this->sConnectedHost = '';
$this->iConnectedPort = 0;
$this->iStartConnectTime = 0;
$this->bSecure = false;
}
/**
* @return string
*/
public function GetConnectedHost()
{
return $this->sConnectedHost;
}
/**
* @return int
*/
public function GetConnectedPort()
{
return $this->iConnectedPort;
}
/**
* @param int $iConnectTimeOut = 10
* @param int $iSocketTimeOut = 10
*
* @return void
*/
public function SetTimeOuts($iConnectTimeOut = 10, $iSocketTimeOut = 10)
{
$this->iConnectTimeOut = $iConnectTimeOut;
$this->iSocketTimeOut = $iSocketTimeOut;
}
/**
* @return resource|null
*/
public function ConnectionResource()
{
return $this->rConnect;
}
/**
* @param string $sServerName
* @param int $iPort
* @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT
*
* @return void
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
* @throws \MailSo\Net\Exceptions\SocketAlreadyConnectedException
* @throws \MailSo\Net\Exceptions\SocketCanNotConnectToHostException
*/
public function Connect($sServerName, $iPort,
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT)
{
if (!\MailSo\Base\Validator::NotEmptyString($sServerName, true) || !\MailSo\Base\Validator::PortInt($iPort))
{
$this->writeLogException(
new \MailSo\Base\Exceptions\InvalidArgumentException(),
\MailSo\Log\Enumerations\Type::ERROR, true);
}
if ($this->IsConnected())
{
$this->writeLogException(
new Exceptions\SocketAlreadyConnectedException(),
\MailSo\Log\Enumerations\Type::ERROR, true);
}
$sServerName = \trim($sServerName);
$sErrorStr = '';
$iErrorNo = 0;
$this->iSecurityType = $iSecurityType;
$this->iConnectedPort = $iPort;
$this->bSecure = \MailSo\Net\Enumerations\ConnectionSecurityType::UseSSL($iPort, $iSecurityType);
$this->sConnectedHost = $this->bSecure ? 'ssl://'.$sServerName : $sServerName;
if (!$this->bSecure && \MailSo\Net\Enumerations\ConnectionSecurityType::SSL === $this->iSecurityType)
{
$this->writeLogException(
new \MailSo\Net\Exceptions\SocketUnsuppoterdSecureConnectionException('SSL isn\'t supported'),
\MailSo\Log\Enumerations\Type::ERROR, true);
}
$this->iStartConnectTime = \microtime(true);
$this->writeLog('Start connection to "'.$this->sConnectedHost.':'.$this->iConnectedPort.'"',
\MailSo\Log\Enumerations\Type::NOTE);
$this->rConnect = @\fsockopen($this->sConnectedHost, $this->iConnectedPort,
$iErrorNo, $sErrorStr, $this->iConnectTimeOut);
if (!is_resource($this->rConnect))
{
$this->writeLogException(
new Exceptions\SocketCanNotConnectToHostException(
$sErrorStr, $iErrorNo,
'Can\'t connect to host "'.$this->sConnectedHost.':'.$this->iConnectedPort.'"'
), \MailSo\Log\Enumerations\Type::NOTICE, true);
}
$this->writeLog((\microtime(true) - $this->iStartConnectTime).' (raw connection)',
\MailSo\Log\Enumerations\Type::TIME);
if ($this->rConnect)
{
if (\MailSo\Base\Utils::FunctionExistsAndEnabled('stream_set_timeout'))
{
@\stream_set_timeout($this->rConnect, $this->iSocketTimeOut);
}
if (\MailSo\Base\Utils::FunctionExistsAndEnabled('stream_set_blocking'))
{
@\stream_set_blocking($this->rConnect, 1);
}
}
}
/**
* @return void
*/
public function Disconnect()
{
if (\is_resource($this->rConnect))
{
$bResult = \fclose($this->rConnect);
$this->writeLog('Disconnected from "'.$this->sConnectedHost.':'.$this->iConnectedPort.'" ('.
(($bResult) ? 'success' : 'unsuccess').')', \MailSo\Log\Enumerations\Type::NOTE);
if (0 !== $this->iStartConnectTime)
{
$this->writeLog((\microtime(true) - $this->iStartConnectTime).' (net session)',
\MailSo\Log\Enumerations\Type::TIME);
$this->iStartConnectTime = 0;
}
$this->rConnect = null;
}
}
/**
* @retun void
*
* @throws \MailSo\Net\Exceptions\Exception
*/
public function LogoutAndDisconnect()
{
if (\method_exists($this, 'Logout') && !$this->bUnreadBuffer)
{
$this->Logout();
}
$this->Disconnect();
}
/**
* @param bool $bThrowExceptionOnFalse = false
*
* @return bool
*/
public function IsConnected($bThrowExceptionOnFalse = false)
{
$bResult = \is_resource($this->rConnect);
if (!$bResult && $bThrowExceptionOnFalse)
{
$this->writeLogException(
new Exceptions\SocketConnectionDoesNotAvailableException(),
\MailSo\Log\Enumerations\Type::ERROR, true);
}
return $bResult;
}
/**
* @return void
*
* @throws \MailSo\Net\Exceptions\SocketConnectionDoesNotAvailableException
*/
public function IsConnectedWithException()
{
$this->IsConnected(true);
}
/**
* @param string $sRaw
* @param bool $bWriteToLog = true
* @param string $sFakeRaw = ''
*
* @return void
*
* @throws \MailSo\Net\Exceptions\SocketConnectionDoesNotAvailableException
* @throws \MailSo\Net\Exceptions\SocketWriteException
*/
protected function sendRaw($sRaw, $bWriteToLog = true, $sFakeRaw = '')
{
if ($this->bUnreadBuffer)
{
$this->writeLogException(
new Exceptions\SocketUnreadBufferException(),
\MailSo\Log\Enumerations\Type::ERROR, true);
}
$bFake = 0 < \strlen($sFakeRaw);
$sRaw .= "\r\n";
if ($bFake)
{
$sFakeRaw .= "\r\n";
}
$mResult = @\fwrite($this->rConnect, $sRaw);
if (false === $mResult)
{
$this->IsConnected(true);
$this->writeLogException(
new Exceptions\SocketWriteException(),
\MailSo\Log\Enumerations\Type::ERROR, true);
}
else
{
\MailSo\Base\Loader::IncStatistic('NetWrite', $mResult);
if ($bWriteToLog)
{
$this->writeLogWithCrlf('> '.($bFake ? $sFakeRaw : $sRaw), //.' ['.$iWriteSize.']',
$bFake ? \MailSo\Log\Enumerations\Type::SECURE : \MailSo\Log\Enumerations\Type::INFO);
}
}
}
/**
* @param mixed $mReadLen = null
* @param bool $bForceLogin = false
*
* @return void
*
* @throws \MailSo\Net\Exceptions\SocketConnectionDoesNotAvailableException
* @throws \MailSo\Net\Exceptions\SocketReadException
*/
protected function getNextBuffer($mReadLen = null, $bForceLogin = false)
{
if (null === $mReadLen)
{
$this->sResponseBuffer = @\fgets($this->rConnect);
}
else
{
$this->sResponseBuffer = '';
$iRead = $mReadLen;
while (0 < $iRead)
{
$sAddRead = @\fread($this->rConnect, $iRead);
if (false === $sAddRead)
{
$this->sResponseBuffer = false;
break;
}
$this->sResponseBuffer .= $sAddRead;
$iRead -= \strlen($sAddRead);
}
}
if (false === $this->sResponseBuffer)
{
$this->IsConnected(true);
$this->bUnreadBuffer = true;
$aSocketStatus = @\stream_get_meta_data($this->rConnect);
if (isset($aSocketStatus['timed_out']) && $aSocketStatus['timed_out'])
{
$this->writeLogException(
new Exceptions\SocketReadTimeoutException(),
\MailSo\Log\Enumerations\Type::ERROR, true);
}
else
{
$this->writeLogException(
new Exceptions\SocketReadException(),
\MailSo\Log\Enumerations\Type::ERROR, true);
}
}
else
{
$iReadedLen = \strlen($this->sResponseBuffer);
if (null === $mReadLen || $bForceLogin)
{
$this->writeLogWithCrlf('< '.$this->sResponseBuffer, //.' ['.$iReadedLen.']',
\MailSo\Log\Enumerations\Type::INFO);
}
else
{
$this->writeLog('Received '.$iReadedLen.'/'.$mReadLen.' bytes.',
\MailSo\Log\Enumerations\Type::INFO);
}
\MailSo\Base\Loader::IncStatistic('NetRead', $iReadedLen);
}
}
/**
* @return string
*/
protected function getLogName()
{
return 'NET';
}
/**
* @param string $sDesc
* @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO
*
* @return void
*/
protected function writeLog($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO)
{
if ($this->oLogger)
{
$this->oLogger->Write($sDesc, $iDescType, $this->getLogName());
}
}
/**
* @param string $sDesc
* @param int $iDescType = \MailSo\Log\Enumerations\Type::INFO
*
* @return void
*/
protected function writeLogWithCrlf($sDesc, $iDescType = \MailSo\Log\Enumerations\Type::INFO)
{
$this->writeLog(\strtr($sDesc, array("\r" => '\r', "\n" => '\n')), $iDescType);
}
/**
* @param \Exception $oException
* @param int $iDescType = \MailSo\Log\Enumerations\Type::NOTICE
* @param bool $bThrowException = false
*
* @return void
*/
protected function writeLogException($oException,
$iDescType = \MailSo\Log\Enumerations\Type::NOTICE, $bThrowException = false)
{
if ($this->oLogger)
{
$this->oLogger->WriteException($oException, $iDescType, $this->getLogName());
}
if ($bThrowException)
{
throw $oException;
}
}
/**
* @param \MailSo\Log\Logger $oLogger
*
* @return void
*
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
*/
public function SetLogger($oLogger)
{
if (!($oLogger instanceof \MailSo\Log\Logger))
{
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
}
$this->oLogger = $oLogger;
}
/**
* @return \MailSo\Log\Logger|null
*/
public function Logger()
{
return $this->oLogger;
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Pop3\Exceptions;
/**
* @category MailSo
* @package Pop3
* @subpackage Exceptions
*/
class Exception extends \MailSo\Base\Exceptions\Exception {}

View file

@ -0,0 +1,10 @@
<?php
namespace MailSo\Pop3\Exceptions;
/**
* @category MailSo
* @package Pop3
* @subpackage Exceptions
*/
class LoginBadCredentialsException extends \MailSo\Pop3\Exceptions\NegativeResponseException {}

Some files were not shown because too many files have changed in this diff Show more