| Current Path : /home/antonen/chenglong.lt/libraries/foxcontact/swiftmailer/classes/Swift/Signers/ |
| Current File : /home/antonen/chenglong.lt/libraries/foxcontact/swiftmailer/classes/Swift/Signers/DKIMSigner.php |
<?php defined('_JEXEC') or die;
/**
* @package Fox Contact for Joomla
* @copyright Copyright (c) Fox Labs, all rights reserved.
* @license Distributed under the terms of the GNU General Public License GNU/GPL v3 http://www.gnu.org/licenses/gpl-3.0.html
* @see Documentation: http://www.fox.ra.it/forum/2-documentation.html
*/
class Swift_Signers_DKIMSigner implements Swift_Signers_HeaderSigner
{
protected $_privateKey;
protected $_domainName;
protected $_selector;
protected $_hashAlgorithm = 'rsa-sha256';
protected $_bodyCanon = 'simple';
protected $_headerCanon = 'simple';
protected $_ignoredHeaders = array('return-path' => true);
protected $_signerIdentity;
protected $_bodyLen = 0;
protected $_maxLen = PHP_INT_MAX;
protected $_showLen = false;
protected $_signatureTimestamp = true;
protected $_signatureExpiration = false;
protected $_debugHeaders = false;
protected $_signedHeaders = array();
private $_debugHeadersData = '';
private $_bodyHash = '';
protected $_dkimHeader;
private $_bodyHashHandler;
private $_headerHash;
private $_headerCanonData = '';
private $_bodyCanonEmptyCounter = 0;
private $_bodyCanonIgnoreStart = 2;
private $_bodyCanonSpace = false;
private $_bodyCanonLastChar = null;
private $_bodyCanonLine = '';
private $_bound = array();
public function __construct($privateKey, $domainName, $selector)
{
$this->_privateKey = $privateKey;
$this->_domainName = $domainName;
$this->_signerIdentity = '@' . $domainName;
$this->_selector = $selector;
if (PHP_VERSION_ID < 50408)
{
$this->_hashAlgorithm = 'rsa-sha1';
}
}
public static function newInstance($privateKey, $domainName, $selector)
{
return new static($privateKey, $domainName, $selector);
}
public function reset()
{
$this->_headerHash = null;
$this->_signedHeaders = array();
$this->_bodyHash = null;
$this->_bodyHashHandler = null;
$this->_bodyCanonIgnoreStart = 2;
$this->_bodyCanonEmptyCounter = 0;
$this->_bodyCanonLastChar = null;
$this->_bodyCanonSpace = false;
}
public function write($bytes)
{
$this->_canonicalizeBody($bytes);
foreach ($this->_bound as $is)
{
$is->write($bytes);
}
}
public function commit()
{
return;
}
public function bind(Swift_InputByteStream $is)
{
$this->_bound[] = $is;
return;
}
public function unbind(Swift_InputByteStream $is)
{
foreach ($this->_bound as $k => $stream)
{
if ($stream === $is)
{
unset($this->_bound[$k]);
return;
}
}
}
public function flushBuffers()
{
$this->reset();
}
public function setHashAlgorithm($hash)
{
switch ($hash)
{
case 'rsa-sha1':
$this->_hashAlgorithm = 'rsa-sha1';
break;
case 'rsa-sha256':
$this->_hashAlgorithm = 'rsa-sha256';
if (!defined('OPENSSL_ALGO_SHA256'))
{
throw new Swift_SwiftException('Unable to set sha256 as it is not supported by OpenSSL.');
}
break;
default:
throw new Swift_SwiftException('Unable to set the hash algorithm, must be one of rsa-sha1 or rsa-sha256 (%s given).', $hash);
}
return $this;
}
public function setBodyCanon($canon)
{
if ($canon == 'relaxed')
{
$this->_bodyCanon = 'relaxed';
}
else
{
$this->_bodyCanon = 'simple';
}
return $this;
}
public function setHeaderCanon($canon)
{
if ($canon == 'relaxed')
{
$this->_headerCanon = 'relaxed';
}
else
{
$this->_headerCanon = 'simple';
}
return $this;
}
public function setSignerIdentity($identity)
{
$this->_signerIdentity = $identity;
return $this;
}
public function setBodySignedLen($len)
{
if ($len === true)
{
$this->_showLen = true;
$this->_maxLen = PHP_INT_MAX;
}
elseif ($len === false)
{
$this->_showLen = false;
$this->_maxLen = PHP_INT_MAX;
}
else
{
$this->_showLen = true;
$this->_maxLen = (int) $len;
}
return $this;
}
public function setSignatureTimestamp($time)
{
$this->_signatureTimestamp = $time;
return $this;
}
public function setSignatureExpiration($time)
{
$this->_signatureExpiration = $time;
return $this;
}
public function setDebugHeaders($debug)
{
$this->_debugHeaders = (bool) $debug;
return $this;
}
public function startBody()
{
switch ($this->_hashAlgorithm)
{
case 'rsa-sha256':
$this->_bodyHashHandler = hash_init('sha256');
break;
case 'rsa-sha1':
$this->_bodyHashHandler = hash_init('sha1');
break;
}
$this->_bodyCanonLine = '';
}
public function endBody()
{
$this->_endOfBody();
}
public function getAlteredHeaders()
{
if ($this->_debugHeaders)
{
return array('DKIM-Signature', 'X-DebugHash');
}
else
{
return array('DKIM-Signature');
}
}
public function ignoreHeader($header_name)
{
$this->_ignoredHeaders[strtolower($header_name)] = true;
return $this;
}
public function setHeaders(Swift_Mime_HeaderSet $headers)
{
$this->_headerCanonData = '';
$listHeaders = $headers->listAll();
foreach ($listHeaders as $hName)
{
if (!isset($this->_ignoredHeaders[strtolower($hName)]))
{
if ($headers->has($hName))
{
$tmp = $headers->getAll($hName);
foreach ($tmp as $header)
{
if ($header->getFieldBody() != '')
{
$this->_addHeader($header->toString());
$this->_signedHeaders[] = $header->getFieldName();
}
}
}
}
}
return $this;
}
public function addSignature(Swift_Mime_HeaderSet $headers)
{
$params = array('v' => '1', 'a' => $this->_hashAlgorithm, 'bh' => base64_encode($this->_bodyHash), 'd' => $this->_domainName, 'h' => implode(': ', $this->_signedHeaders), 'i' => $this->_signerIdentity, 's' => $this->_selector);
if ($this->_bodyCanon != 'simple')
{
$params['c'] = $this->_headerCanon . '/' . $this->_bodyCanon;
}
elseif ($this->_headerCanon != 'simple')
{
$params['c'] = $this->_headerCanon;
}
if ($this->_showLen)
{
$params['l'] = $this->_bodyLen;
}
if ($this->_signatureTimestamp === true)
{
$params['t'] = time();
if ($this->_signatureExpiration !== false)
{
$params['x'] = $params['t'] + $this->_signatureExpiration;
}
}
else
{
if ($this->_signatureTimestamp !== false)
{
$params['t'] = $this->_signatureTimestamp;
}
if ($this->_signatureExpiration !== false)
{
$params['x'] = $this->_signatureExpiration;
}
}
if ($this->_debugHeaders)
{
$params['z'] = implode('|', $this->_debugHeadersData);
}
$string = '';
foreach ($params as $k => $v)
{
$string .= $k . '=' . $v . '; ';
}
$string = trim($string);
$headers->addTextHeader('DKIM-Signature', $string);
$tmp = $headers->getAll('DKIM-Signature');
$this->_dkimHeader = end($tmp);
$this->_addHeader(trim($this->_dkimHeader->toString()) . "\r\n b=", true);
$this->_endOfHeaders();
if ($this->_debugHeaders)
{
$headers->addTextHeader('X-DebugHash', base64_encode($this->_headerHash));
}
$this->_dkimHeader->setValue($string . ' b=' . trim(chunk_split(base64_encode($this->_getEncryptedHash()), 73, ' ')));
return $this;
}
protected function _addHeader($header, $is_sig = false)
{
switch ($this->_headerCanon)
{
case 'relaxed':
$exploded = explode(':', $header, 2);
$name = strtolower(trim($exploded[0]));
$value = str_replace("\r\n", '', $exploded[1]);
$value = preg_replace("/[ \t][ \t]+/", ' ', $value);
$header = $name . ':' . trim($value) . ($is_sig ? '' : "\r\n");
case 'simple':
}
$this->_addToHeaderHash($header);
}
protected function _endOfHeaders()
{
}
protected function _canonicalizeBody($string)
{
$len = strlen($string);
$canon = '';
$method = $this->_bodyCanon == 'relaxed';
for ($i = 0; $i < $len; ++$i)
{
if ($this->_bodyCanonIgnoreStart > 0)
{
--$this->_bodyCanonIgnoreStart;
continue;
}
switch ($string[$i])
{
case "\r":
$this->_bodyCanonLastChar = "\r";
break;
case "\n":
if ($this->_bodyCanonLastChar == "\r")
{
if ($method)
{
$this->_bodyCanonSpace = false;
}
if ($this->_bodyCanonLine == '')
{
++$this->_bodyCanonEmptyCounter;
}
else
{
$this->_bodyCanonLine = '';
$canon .= "\r\n";
}
}
else
{
}
break;
case ' ':
case "\t":
if ($method)
{
$this->_bodyCanonSpace = true;
break;
}
default:
if ($this->_bodyCanonEmptyCounter > 0)
{
$canon .= str_repeat("\r\n", $this->_bodyCanonEmptyCounter);
$this->_bodyCanonEmptyCounter = 0;
}
if ($this->_bodyCanonSpace)
{
$this->_bodyCanonLine .= ' ';
$canon .= ' ';
$this->_bodyCanonSpace = false;
}
$this->_bodyCanonLine .= $string[$i];
$canon .= $string[$i];
}
}
$this->_addToBodyHash($canon);
}
protected function _endOfBody()
{
if (strlen($this->_bodyCanonLine) > 0)
{
$this->_addToBodyHash("\r\n");
}
$this->_bodyHash = hash_final($this->_bodyHashHandler, true);
}
private function _addToBodyHash($string)
{
$len = strlen($string);
if ($len > ($new_len = $this->_maxLen - $this->_bodyLen))
{
$string = substr($string, 0, $new_len);
$len = $new_len;
}
hash_update($this->_bodyHashHandler, $string);
$this->_bodyLen += $len;
}
private function _addToHeaderHash($header)
{
if ($this->_debugHeaders)
{
$this->_debugHeadersData[] = trim($header);
}
$this->_headerCanonData .= $header;
}
private function _getEncryptedHash()
{
$signature = '';
switch ($this->_hashAlgorithm)
{
case 'rsa-sha1':
$algorithm = OPENSSL_ALGO_SHA1;
break;
case 'rsa-sha256':
$algorithm = OPENSSL_ALGO_SHA256;
break;
}
$pkeyId = openssl_get_privatekey($this->_privateKey);
if (!$pkeyId)
{
throw new Swift_SwiftException('Unable to load DKIM Private Key [' . openssl_error_string() . ']');
}
if (openssl_sign($this->_headerCanonData, $signature, $pkeyId, $algorithm))
{
return $signature;
}
throw new Swift_SwiftException('Unable to sign DKIM Hash [' . openssl_error_string() . ']');
}
}