mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 05:58:34 +01:00
MDL-80207 core: Remove Horde library
This commit is contained in:
parent
a63d39b0ad
commit
6bddb8626f
@ -88,7 +88,6 @@ class core_component {
|
||||
protected static $filestomap = ['lib.php', 'settings.php'];
|
||||
/** @var array associative array of PSR-0 namespaces and corresponding paths. */
|
||||
protected static $psr0namespaces = [
|
||||
'Horde' => 'lib/horde/framework/Horde',
|
||||
'Mustache' => 'lib/mustache/src/Mustache',
|
||||
'CFPropertyList' => 'lib/plist/classes/CFPropertyList',
|
||||
];
|
||||
|
@ -1,147 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* The Horde_Array:: class provides various methods for array manipulation.
|
||||
*
|
||||
* Copyright 2003-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @author Marko Djukic <marko@oblo.com>
|
||||
* @author Jan Schneider <jan@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Util
|
||||
*/
|
||||
class Horde_Array
|
||||
{
|
||||
/**
|
||||
* Sorts an array on a specified key. If the key does not exist,
|
||||
* defaults to the first key of the array.
|
||||
*
|
||||
* @param array &$array The array to be sorted, passed by reference.
|
||||
* @param string $key The key by which to sort. If not specified then
|
||||
* the first key is used.
|
||||
* @param integer $dir Sort direction:
|
||||
* 0 = ascending (default)
|
||||
* 1 = descending
|
||||
* @param boolean $assoc Keep key value association?
|
||||
*/
|
||||
public static function arraySort(array &$array, $key = null, $dir = 0,
|
||||
$assoc = true)
|
||||
{
|
||||
/* Return if the array is empty. */
|
||||
if (empty($array)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If no key to sort by is specified, use the first key of the
|
||||
* first element. */
|
||||
if (is_null($key)) {
|
||||
$keys = array_keys(reset($array));
|
||||
$key = array_shift($keys);
|
||||
}
|
||||
|
||||
/* Call the appropriate sort function. */
|
||||
$helper = new Horde_Array_Sort_Helper();
|
||||
$helper->key = $key;
|
||||
$function = $dir ? 'reverseCompare' : 'compare';
|
||||
if ($assoc) {
|
||||
uasort($array, array($helper, $function));
|
||||
} else {
|
||||
usort($array, array($helper, $function));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an HTML type array field "example[key1][key2][key3]" breaks up
|
||||
* the keys so that they could be used to reference a regular PHP array.
|
||||
*
|
||||
* @param string $field The field name to be examined.
|
||||
* @param string &$base Will be set to the base element.
|
||||
* @param array &$keys Will be set to the list of keys.
|
||||
*
|
||||
* @return boolean True on sucess, false on error.
|
||||
*/
|
||||
public static function getArrayParts($field, &$base, &$keys)
|
||||
{
|
||||
if (!preg_match('|([^\[]*)((\[[^\[\]]*\])+)|', $field, $matches)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$base = $matches[1];
|
||||
$keys = explode('][', $matches[2]);
|
||||
$keys[0] = substr($keys[0], 1);
|
||||
$keys[count($keys) - 1] = substr($keys[count($keys) - 1], 0, strlen($keys[count($keys) - 1]) - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Using an array of keys iterate through the array following the
|
||||
* keys to find the final key value. If a value is passed then set
|
||||
* that value.
|
||||
*
|
||||
* @param array &$array The array to be used.
|
||||
* @param array &$keys The key path to follow as an array.
|
||||
* @param array $value If set the target element will have this value set
|
||||
* to it.
|
||||
*
|
||||
* @return mixed The final value of the key path.
|
||||
*/
|
||||
public static function getElement(&$array, array &$keys, $value = null)
|
||||
{
|
||||
if (count($keys)) {
|
||||
$key = array_shift($keys);
|
||||
return isset($array[$key])
|
||||
? self::getElement($array[$key], $keys, $value)
|
||||
: false;
|
||||
}
|
||||
|
||||
if (!is_null($value)) {
|
||||
$array = $value;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rectangle of a two-dimensional array.
|
||||
*
|
||||
* @param array $array The array to extract the rectangle from.
|
||||
* @param integer $row The start row of the rectangle.
|
||||
* @param integer $col The start column of the rectangle.
|
||||
* @param integer $height The height of the rectangle.
|
||||
* @param integer $width The width of the rectangle.
|
||||
*
|
||||
* @return array The extracted rectangle.
|
||||
*/
|
||||
public static function getRectangle(array $array, $row, $col, $height,
|
||||
$width)
|
||||
{
|
||||
$rec = array();
|
||||
for ($y = $row; $y < $row + $height; $y++) {
|
||||
$rec[] = array_slice($array[$y], $col, $width);
|
||||
}
|
||||
return $rec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array, returns an associative array with each element key
|
||||
* derived from its value.
|
||||
* For example:
|
||||
* array(0 => 'foo', 1 => 'bar')
|
||||
* would become:
|
||||
* array('foo' => 'foo', 'bar' => 'bar')
|
||||
*
|
||||
* @param array $array An array of values.
|
||||
*
|
||||
* @return array An array with keys the same as values.
|
||||
*/
|
||||
public static function valuesToKeys(array $array)
|
||||
{
|
||||
return $array
|
||||
? array_combine($array, $array)
|
||||
: array();
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Helper class for sorting arrays on arbitrary criteria for usort/uasort.
|
||||
*
|
||||
* Copyright 2003-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Marko Djukic <marko@oblo.com>
|
||||
* @author Jan Schneider <jan@horde.org>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Util
|
||||
*/
|
||||
class Horde_Array_Sort_Helper
|
||||
{
|
||||
/**
|
||||
* The array key to sort by.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $key;
|
||||
|
||||
/**
|
||||
* Compare two associative arrays by the array key defined in self::$key.
|
||||
*
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
*/
|
||||
public function compare($a, $b)
|
||||
{
|
||||
return strcoll(Horde_String::lower($a[$this->key], true, 'UTF-8'), Horde_String::lower($b[$this->key], true, 'UTF-8'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare, in reverse order, two associative arrays by the array key
|
||||
* defined in self::$key.
|
||||
*
|
||||
* @param scalar $a TODO
|
||||
* @param scalar $b TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
public function reverseCompare($a, $b)
|
||||
{
|
||||
return strcoll(Horde_String::lower($b[$this->key], true, 'UTF-8'), Horde_String::lower($a[$this->key], true, 'UTF-8'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare array keys case insensitively for uksort.
|
||||
*
|
||||
* @param scalar $a TODO
|
||||
* @param scalar $b TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
public function compareKeys($a, $b)
|
||||
{
|
||||
return strcoll(Horde_String::lower($a, true, 'UTF-8'), Horde_String::lower($b, true, 'UTF-8'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare, in reverse order, array keys case insensitively for uksort.
|
||||
*
|
||||
* @param scalar $a TODO
|
||||
* @param scalar $b TODO
|
||||
*
|
||||
* @return TODO
|
||||
*/
|
||||
public function reverseCompareKeys($a, $b)
|
||||
{
|
||||
return strcoll(Horde_String::lower($b, true, 'UTF-8'), Horde_String::lower($a, true, 'UTF-8'));
|
||||
}
|
||||
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2005-2008 Matthew Fonda <mfonda@php.net>
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides blowfish encryption/decryption, with or without a secret key,
|
||||
* for PHP strings.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2005-2008 Matthew Fonda
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*
|
||||
* @property string $cipher The cipher block mode ('ecb' or 'cbc').
|
||||
* @property string $key The encryption key in use.
|
||||
* @property mixed $iv The initialization vector (false if using 'ecb').
|
||||
*/
|
||||
class Horde_Crypt_Blowfish
|
||||
{
|
||||
// Constants for 'ignore' parameter of constructor.
|
||||
const IGNORE_OPENSSL = 1;
|
||||
const IGNORE_MCRYPT = 2;
|
||||
|
||||
// Block size for Blowfish
|
||||
const BLOCKSIZE = 8;
|
||||
|
||||
// Maximum key size for Blowfish
|
||||
const MAXKEYSIZE = 56;
|
||||
|
||||
// IV Length for CBC
|
||||
const IV_LENGTH = 8;
|
||||
|
||||
/**
|
||||
* Blowfish crypt driver.
|
||||
*
|
||||
* @var Horde_Crypt_Blowfish_Base
|
||||
*/
|
||||
protected $_crypt;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $key Encryption key.
|
||||
* @param array $opts Additional options:
|
||||
* - cipher: (string) Either 'ecb' or 'cbc'.
|
||||
* - ignore: (integer) A mask of drivers to ignore (IGNORE_* constants).
|
||||
* - iv: (string) IV to use.
|
||||
*/
|
||||
public function __construct($key, array $opts = array())
|
||||
{
|
||||
$opts = array_merge(array(
|
||||
'cipher' => 'ecb',
|
||||
'ignore' => 0,
|
||||
'iv' => null
|
||||
), $opts);
|
||||
|
||||
if (!($opts['ignore'] & self::IGNORE_OPENSSL) &&
|
||||
Horde_Crypt_Blowfish_Openssl::supported()) {
|
||||
$this->_crypt = new Horde_Crypt_Blowfish_Openssl($opts['cipher']);
|
||||
} elseif (!($opts['ignore'] & self::IGNORE_MCRYPT) &&
|
||||
Horde_Crypt_Blowfish_Mcrypt::supported()) {
|
||||
$this->_crypt = new Horde_Crypt_Blowfish_Mcrypt($opts['cipher']);
|
||||
} else {
|
||||
$this->_crypt = new Horde_Crypt_Blowfish_Php($opts['cipher']);
|
||||
}
|
||||
|
||||
$this->setKey($key, $opts['iv']);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'cipher':
|
||||
case 'key':
|
||||
case 'iv':
|
||||
return $this->_crypt->$name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a string.
|
||||
*
|
||||
* @param string $text The string to encrypt.
|
||||
*
|
||||
* @return string The ciphertext.
|
||||
* @throws Horde_Crypt_Blowfish_Exception
|
||||
*/
|
||||
public function encrypt($text)
|
||||
{
|
||||
if (!is_string($text)) {
|
||||
throw new Horde_Crypt_Blowfish_Exception('Data to encrypt must be a string.');
|
||||
}
|
||||
|
||||
return $this->_crypt->encrypt($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a string.
|
||||
*
|
||||
* @param string $text The string to decrypt.
|
||||
*
|
||||
* @return string The plaintext.
|
||||
* @throws Horde_Crypt_Blowfish_Exception
|
||||
*/
|
||||
public function decrypt($text)
|
||||
{
|
||||
if (!is_string($text)) {
|
||||
throw new Horde_Crypt_Blowfish_Exception('Data to decrypt must be a string.');
|
||||
}
|
||||
|
||||
return $this->_crypt->decrypt($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the secret key.
|
||||
*
|
||||
* The key must be non-zero, and less than or equal to MAXKEYSIZE
|
||||
* characters (bytes) in length.
|
||||
*
|
||||
* @param string $key Key must be non-empty and less than MAXKEYSIZE
|
||||
* bytes in length.
|
||||
* @param string $iv The initialization vector to use. Only needed for
|
||||
* 'cbc' cipher. If null, an IV is automatically
|
||||
* generated.
|
||||
*
|
||||
* @throws Horde_Crypt_Blowfish_Exception
|
||||
*/
|
||||
public function setKey($key, $iv = null)
|
||||
{
|
||||
if (!is_string($key)) {
|
||||
throw new Horde_Crypt_Blowfish_Exception('Encryption key must be a string.');
|
||||
}
|
||||
|
||||
$len = strlen($key);
|
||||
if (($len > self::MAXKEYSIZE) || ($len == 0)) {
|
||||
throw new Horde_Crypt_Blowfish_Exception(sprintf('Encryption key must be less than %d characters (bytes) and non-zero. Supplied key length: %d', self::MAXKEYSIZE, $len));
|
||||
}
|
||||
|
||||
$this->_crypt->key = $key;
|
||||
|
||||
switch ($this->_crypt->cipher) {
|
||||
case 'cbc':
|
||||
if (is_null($iv)) {
|
||||
if (is_null($this->iv)) {
|
||||
$this->_crypt->setIv();
|
||||
}
|
||||
} else {
|
||||
$iv = substr($iv, 0, self::IV_LENGTH);
|
||||
if (($len = strlen($iv)) < self::IV_LENGTH) {
|
||||
$iv .= str_repeat(chr(0), self::IV_LENGTH - $len);
|
||||
}
|
||||
$this->_crypt->setIv($iv);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'ecb':
|
||||
$this->iv = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract base driver class for blowfish encryption.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
abstract class Horde_Crypt_Blowfish_Base
|
||||
{
|
||||
/**
|
||||
* Cipher method.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $cipher;
|
||||
|
||||
/**
|
||||
* Initialization vector.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $iv = null;
|
||||
|
||||
/**
|
||||
* Encryption key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $key;
|
||||
|
||||
/**
|
||||
* Is this driver supported on this system?
|
||||
*
|
||||
* @return boolean True if supported.
|
||||
*/
|
||||
public static function supported()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $cipher Either 'ecb' or 'cbc'.
|
||||
*/
|
||||
public function __construct($cipher)
|
||||
{
|
||||
$this->cipher = $cipher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a string.
|
||||
*
|
||||
* @param string $text The string to encrypt.
|
||||
*
|
||||
* @return string The ciphertext.
|
||||
* @throws Horde_Crypt_Blowfish_Exception
|
||||
*/
|
||||
abstract public function encrypt($text);
|
||||
|
||||
/**
|
||||
* Decrypts a string.
|
||||
*
|
||||
* @param string $text The string to encrypt.
|
||||
*
|
||||
* @return string The ciphertext.
|
||||
* @throws Horde_Crypt_Blowfish_Exception
|
||||
*/
|
||||
abstract public function decrypt($text);
|
||||
|
||||
/**
|
||||
* Sets the initialization vector (required for CBC mode).
|
||||
*
|
||||
* @param string $iv Initialization vector.
|
||||
*/
|
||||
public function setIv($iv = null)
|
||||
{
|
||||
$this->iv = is_null($iv)
|
||||
? substr(new Horde_Support_Randomid(), 0, 8)
|
||||
: $iv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad text to match blocksize length.
|
||||
*
|
||||
* @param string $text Unpadded text.
|
||||
* @param boolean $ignore Don't pad if already at blocksize length.
|
||||
*
|
||||
* @return string Padded text.
|
||||
*/
|
||||
protected function _pad($text, $ignore = false)
|
||||
{
|
||||
$blocksize = Horde_Crypt_Blowfish::BLOCKSIZE;
|
||||
$padding = $blocksize - (strlen($text) % $blocksize);
|
||||
|
||||
return ($ignore && ($padding == $blocksize))
|
||||
? $text
|
||||
: $text . str_repeat(chr($padding), $padding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpad text from blocksize boundary.
|
||||
*
|
||||
* @param string $text Padded text.
|
||||
*
|
||||
* @return string Unpadded text.
|
||||
*/
|
||||
protected function _unpad($text)
|
||||
{
|
||||
return substr($text, 0, ord(substr($text, -1)) * -1);
|
||||
}
|
||||
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception object for the Horde_Crypt_Blowfish package.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
class Horde_Crypt_Blowfish_Exception extends Horde_Exception_Wrapped
|
||||
{
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2005-2008 Matthew Fonda <mfonda@php.net>
|
||||
* Copyright 2008 Philippe Jausions <jausions@php.net>
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Philippe Jausions <jausions@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
|
||||
/**
|
||||
* Mcrypt driver for blowfish encryption.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Philippe Jausions <jausions@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2005-2008 Matthew Fonda
|
||||
* @copyright 2008 Philippe Jausions
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
class Horde_Crypt_Blowfish_Mcrypt extends Horde_Crypt_Blowfish_Base
|
||||
{
|
||||
/**
|
||||
* Mcrypt resource.
|
||||
*
|
||||
* @var resource
|
||||
*/
|
||||
private $_mcrypt;
|
||||
|
||||
/**
|
||||
*/
|
||||
public static function supported()
|
||||
{
|
||||
return PHP_VERSION_ID < 70100 && extension_loaded('mcrypt');
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __construct($cipher)
|
||||
{
|
||||
parent::__construct($cipher);
|
||||
|
||||
$this->_mcrypt = mcrypt_module_open(MCRYPT_BLOWFISH, '', $cipher, '');
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function encrypt($text)
|
||||
{
|
||||
mcrypt_generic_init($this->_mcrypt, $this->key, empty($this->iv) ? str_repeat('0', Horde_Crypt_Blowfish::IV_LENGTH) : $this->iv);
|
||||
$out = mcrypt_generic($this->_mcrypt, $this->_pad($text));
|
||||
mcrypt_generic_deinit($this->_mcrypt);
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function decrypt($text)
|
||||
{
|
||||
mcrypt_generic_init($this->_mcrypt, $this->key, empty($this->iv) ? str_repeat('0', Horde_Crypt_Blowfish::IV_LENGTH) : $this->iv);
|
||||
$out = mdecrypt_generic($this->_mcrypt, $this->_pad($text, true));
|
||||
mcrypt_generic_deinit($this->_mcrypt);
|
||||
|
||||
return $this->_unpad($out);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function setIv($iv = null)
|
||||
{
|
||||
$this->iv = is_null($iv)
|
||||
? mcrypt_create_iv(Horde_Crypt_Blowfish::IV_LENGTH, MCRYPT_RAND)
|
||||
: $iv;
|
||||
}
|
||||
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
|
||||
/**
|
||||
* Openssl driver for blowfish encryption.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
class Horde_Crypt_Blowfish_Openssl extends Horde_Crypt_Blowfish_Base
|
||||
{
|
||||
/**
|
||||
*/
|
||||
public static function supported()
|
||||
{
|
||||
if (extension_loaded('openssl')) {
|
||||
$ciphers = openssl_get_cipher_methods();
|
||||
return in_array('bf-ecb', $ciphers) && in_array('bf-cbc', $ciphers);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function encrypt($text)
|
||||
{
|
||||
if (PHP_VERSION_ID <= 50302) {
|
||||
return @openssl_encrypt($text, 'bf-' . $this->cipher, $this->key, true);
|
||||
} elseif (PHP_VERSION_ID == 50303) {
|
||||
// Need to mask error output, since an invalid warning message was
|
||||
// issued prior to 5.3.4 for empty IVs in ECB mode.
|
||||
return @openssl_encrypt($text, 'bf-' . $this->cipher, $this->key, true, strval($this->iv));
|
||||
}
|
||||
|
||||
return openssl_encrypt($text, 'bf-' . $this->cipher, $this->key, true, strval($this->iv));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function decrypt($text)
|
||||
{
|
||||
return (PHP_VERSION_ID <= 50302)
|
||||
? openssl_decrypt($text, 'bf-' . $this->cipher, $this->key, true)
|
||||
: openssl_decrypt($text, 'bf-' . $this->cipher, $this->key, true, strval($this->iv));
|
||||
}
|
||||
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2015-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
|
||||
/**
|
||||
* PBKDF2 (Password-Based Key Derivation Function 2) implementation (RFC
|
||||
* 2898; PKCS #5 v2.0).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2015-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
* @link https://defuse.ca/php-pbkdf2.htm pbkdf2 code released to the
|
||||
* public domain.
|
||||
*/
|
||||
class Horde_Crypt_Blowfish_Pbkdf2
|
||||
{
|
||||
/**
|
||||
* Hash algorithm used to create key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $hashAlgo;
|
||||
|
||||
/**
|
||||
* Number of iterations to use.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $iterations;
|
||||
|
||||
/**
|
||||
* Salt.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $salt;
|
||||
|
||||
/**
|
||||
* The derived key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_key;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $pass The password.
|
||||
* @param string $key_length Length of the derived key (in bytes).
|
||||
* @param array $opts Additional options:
|
||||
* - algo: (string) Hash algorithm.
|
||||
* - i_count: (integer) Iteration count.
|
||||
* - salt: (string) The salt to use.
|
||||
*/
|
||||
public function __construct($pass, $key_length, array $opts = array())
|
||||
{
|
||||
$this->iterations = isset($opts['i_count'])
|
||||
? $opts['i_count']
|
||||
: 16384;
|
||||
|
||||
if (($key_length <= 0) || ($this->iterations <= 0)) {
|
||||
throw new InvalidArgumentException('Invalid arguments');
|
||||
}
|
||||
|
||||
$this->hashAlgo = isset($opts['algo'])
|
||||
? $opts['algo']
|
||||
: 'SHA256';
|
||||
|
||||
/* Nice to have, but salt does not need to be cryptographically
|
||||
* secure random value. */
|
||||
$this->salt = isset($opts['salt'])
|
||||
? $opts['salt']
|
||||
: (function_exists('openssl_random_pseudo_bytes')
|
||||
? openssl_random_pseudo_bytes($key_length)
|
||||
: substr(hash('sha512', new Horde_Support_Randomid(), true), 0, $key_length));
|
||||
|
||||
if (function_exists('hash_pbkdf2')) {
|
||||
$this->_key = hash_pbkdf2(
|
||||
$this->hashAlgo,
|
||||
$pass,
|
||||
$this->salt,
|
||||
$this->iterations,
|
||||
$key_length,
|
||||
true
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$hash_length = strlen(hash($this->hashAlgo, '', true));
|
||||
$block_count = ceil($key_length / $hash_length);
|
||||
|
||||
$hash = '';
|
||||
for ($i = 1; $i <= $block_count; ++$i) {
|
||||
// $i encoded as 4 bytes, big endian.
|
||||
$last = $this->salt . pack('N', $i);
|
||||
for ($j = 0; $j < $this->iterations; $j++) {
|
||||
$last = hash_hmac($this->hashAlgo, $last, $pass, true);
|
||||
if ($j) {
|
||||
$xorsum ^= $last;
|
||||
} else {
|
||||
$xorsum = $last;
|
||||
}
|
||||
}
|
||||
$hash .= $xorsum;
|
||||
}
|
||||
|
||||
$this->_key = substr($hash, 0, $key_length);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->_key;
|
||||
}
|
||||
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2005-2008 Matthew Fonda <mfonda@php.net>
|
||||
* Copyright 2008 Philippe Jausions <jausions@php.net>
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Philippe Jausions <jausions@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
|
||||
/**
|
||||
* Native PHP driver for blowfish encryption.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Philippe Jausions <jausions@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2005-2008 Matthew Fonda
|
||||
* @copyright 2008 Philippe Jausions
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
class Horde_Crypt_Blowfish_Php extends Horde_Crypt_Blowfish_Base
|
||||
{
|
||||
/**
|
||||
* Subclass object.
|
||||
*
|
||||
* @var Horde_Crypt_Blowfish_Php_Base
|
||||
*/
|
||||
protected $_ob;
|
||||
|
||||
/**
|
||||
*/
|
||||
public function encrypt($text)
|
||||
{
|
||||
$this->_init();
|
||||
return $this->_ob->encrypt($this->_pad($text), $this->iv);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function decrypt($text)
|
||||
{
|
||||
$this->_init();
|
||||
return $this->_unpad($this->_ob->decrypt($this->_pad($text, true), $this->iv));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the subclass.
|
||||
*/
|
||||
protected function _init()
|
||||
{
|
||||
if (!isset($this->_ob) ||
|
||||
($this->_ob->md5 != hash('md5', $this->key))) {
|
||||
switch ($this->cipher) {
|
||||
case 'cbc':
|
||||
$this->_ob = new Horde_Crypt_Blowfish_Php_Cbc($this->key);
|
||||
break;
|
||||
|
||||
case 'ecb':
|
||||
$this->_ob = new Horde_Crypt_Blowfish_Php_Ecb($this->key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,459 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2005-2008 Matthew Fonda <mfonda@php.net>
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base subclass for the PHP driver.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2005-2008 Matthew Fonda
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
abstract class Horde_Crypt_Blowfish_Php_Base
|
||||
{
|
||||
/**
|
||||
* MD5 sum of the key used.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $md5;
|
||||
|
||||
/**
|
||||
* P-Array contains 18 32-bit subkeys.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_P = array(
|
||||
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
|
||||
0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
|
||||
0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
|
||||
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
|
||||
0x9216D5D9, 0x8979FB1B
|
||||
);
|
||||
|
||||
/**
|
||||
* Array of four S-Blocks each containing 256 32-bit entries.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_S = array(
|
||||
array(
|
||||
0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
|
||||
0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
|
||||
0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
|
||||
0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
|
||||
0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
|
||||
0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
|
||||
0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
|
||||
0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
|
||||
0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
|
||||
0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
|
||||
0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
|
||||
0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
|
||||
0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
|
||||
0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
|
||||
0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
|
||||
0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
|
||||
0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
|
||||
0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
|
||||
0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
|
||||
0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
|
||||
0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
|
||||
0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
|
||||
0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
|
||||
0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
|
||||
0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
|
||||
0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
|
||||
0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
|
||||
0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
|
||||
0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
|
||||
0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
|
||||
0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
|
||||
0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
|
||||
0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
|
||||
0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
|
||||
0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
|
||||
0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
|
||||
0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
|
||||
0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
|
||||
0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
|
||||
0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
|
||||
0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
|
||||
0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
|
||||
0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
|
||||
0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
|
||||
0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
|
||||
0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
|
||||
0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
|
||||
0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
|
||||
0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
|
||||
0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
|
||||
0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
|
||||
0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
|
||||
0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
|
||||
0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
|
||||
0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
|
||||
0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
|
||||
0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
|
||||
0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
|
||||
0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
|
||||
0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
|
||||
0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
|
||||
0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
|
||||
0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
|
||||
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
|
||||
), array(
|
||||
0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
|
||||
0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
|
||||
0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
|
||||
0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
|
||||
0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
|
||||
0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
|
||||
0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
|
||||
0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
|
||||
0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
|
||||
0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
|
||||
0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
|
||||
0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
|
||||
0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
|
||||
0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
|
||||
0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
|
||||
0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
|
||||
0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
|
||||
0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
|
||||
0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
|
||||
0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
|
||||
0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
|
||||
0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
|
||||
0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
|
||||
0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
|
||||
0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
|
||||
0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
|
||||
0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
|
||||
0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
|
||||
0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
|
||||
0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
|
||||
0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
|
||||
0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
|
||||
0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
|
||||
0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
|
||||
0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
|
||||
0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
|
||||
0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
|
||||
0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
|
||||
0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
|
||||
0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
|
||||
0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
|
||||
0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
|
||||
0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
|
||||
0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
|
||||
0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
|
||||
0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
|
||||
0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
|
||||
0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
|
||||
0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
|
||||
0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
|
||||
0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
|
||||
0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
|
||||
0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
|
||||
0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
|
||||
0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
|
||||
0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
|
||||
0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
|
||||
0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
|
||||
0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
|
||||
0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
|
||||
0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
|
||||
0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
|
||||
0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
|
||||
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
|
||||
), array(
|
||||
0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
|
||||
0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
|
||||
0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
|
||||
0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
|
||||
0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
|
||||
0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
|
||||
0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
|
||||
0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
|
||||
0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
|
||||
0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
|
||||
0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
|
||||
0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
|
||||
0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
|
||||
0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
|
||||
0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
|
||||
0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
|
||||
0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
|
||||
0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
|
||||
0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
|
||||
0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
|
||||
0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
|
||||
0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
|
||||
0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
|
||||
0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
|
||||
0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
|
||||
0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
|
||||
0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
|
||||
0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
|
||||
0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
|
||||
0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
|
||||
0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
|
||||
0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
|
||||
0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
|
||||
0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
|
||||
0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
|
||||
0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
|
||||
0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
|
||||
0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
|
||||
0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
|
||||
0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
|
||||
0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
|
||||
0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
|
||||
0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
|
||||
0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
|
||||
0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
|
||||
0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
|
||||
0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
|
||||
0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
|
||||
0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
|
||||
0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
|
||||
0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
|
||||
0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
|
||||
0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
|
||||
0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
|
||||
0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
|
||||
0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
|
||||
0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
|
||||
0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
|
||||
0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
|
||||
0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
|
||||
0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
|
||||
0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
|
||||
0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
|
||||
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
|
||||
), array(
|
||||
0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
|
||||
0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
|
||||
0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
|
||||
0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
|
||||
0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
|
||||
0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
|
||||
0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
|
||||
0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
|
||||
0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
|
||||
0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
|
||||
0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
|
||||
0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
|
||||
0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
|
||||
0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
|
||||
0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
|
||||
0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
|
||||
0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
|
||||
0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
|
||||
0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
|
||||
0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
|
||||
0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
|
||||
0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
|
||||
0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
|
||||
0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
|
||||
0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
|
||||
0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
|
||||
0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
|
||||
0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
|
||||
0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
|
||||
0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
|
||||
0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
|
||||
0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
|
||||
0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
|
||||
0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
|
||||
0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
|
||||
0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
|
||||
0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
|
||||
0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
|
||||
0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
|
||||
0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
|
||||
0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
|
||||
0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
|
||||
0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
|
||||
0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
|
||||
0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
|
||||
0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
|
||||
0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
|
||||
0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
|
||||
0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
|
||||
0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
|
||||
0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
|
||||
0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
|
||||
0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
|
||||
0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
|
||||
0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
|
||||
0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
|
||||
0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
|
||||
0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
|
||||
0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
|
||||
0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
|
||||
0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
|
||||
0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
|
||||
0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
|
||||
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $key Encrpytion key.
|
||||
*/
|
||||
public function __construct($key)
|
||||
{
|
||||
$data = $datal = $datar = $k = 0;
|
||||
$len = strlen($key);
|
||||
|
||||
for ($i = 0; $i < 18; ++$i) {
|
||||
$data = 0;
|
||||
for ($j = 4; $j > 0; --$j) {
|
||||
$data = $data << 8 | ord($key[$k]);
|
||||
$k = ($k + 1) % $len;
|
||||
}
|
||||
$this->_P[$i] ^= $data;
|
||||
}
|
||||
|
||||
for ($i = 0; $i <= 16; $i += 2) {
|
||||
$this->_encipher($datal, $datar);
|
||||
$this->_P[$i] = $datal;
|
||||
$this->_P[$i+1] = $datar;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 256; $i += 2) {
|
||||
$this->_encipher($datal, $datar);
|
||||
$this->_S[0][$i] = $datal;
|
||||
$this->_S[0][$i+1] = $datar;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 256; $i += 2) {
|
||||
$this->_encipher($datal, $datar);
|
||||
$this->_S[1][$i] = $datal;
|
||||
$this->_S[1][$i+1] = $datar;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 256; $i += 2) {
|
||||
$this->_encipher($datal, $datar);
|
||||
$this->_S[2][$i] = $datal;
|
||||
$this->_S[2][$i+1] = $datar;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 256; $i += 2) {
|
||||
$this->_encipher($datal, $datar);
|
||||
$this->_S[3][$i] = $datal;
|
||||
$this->_S[3][$i+1] = $datar;
|
||||
}
|
||||
|
||||
$this->md5 = hash('md5', $key);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
abstract public function encrypt($text, $iv);
|
||||
|
||||
/**
|
||||
*/
|
||||
abstract public function decrypt($text, $iv);
|
||||
|
||||
/**
|
||||
* Workaround for XOR on certain systems.
|
||||
*
|
||||
* @param integer|float $l
|
||||
* @param integer|float $r
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function _binxor($l, $r)
|
||||
{
|
||||
$x = (($l < 0) ? (float)($l + 4294967296) : (float)$l)
|
||||
^ (($r < 0) ? (float)($r + 4294967296) : (float)$r);
|
||||
|
||||
return (float)(($x < 0) ? $x + 4294967296 : $x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enciphers a single 64-bit block.
|
||||
*
|
||||
* @param int &$Xl
|
||||
* @param int &$Xr
|
||||
*/
|
||||
protected function _encipher(&$Xl, &$Xr)
|
||||
{
|
||||
if ($Xl < 0) {
|
||||
$Xl += 4294967296;
|
||||
}
|
||||
|
||||
if ($Xr < 0) {
|
||||
$Xr += 4294967296;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 16; ++$i) {
|
||||
$temp = $Xl ^ $this->_P[$i];
|
||||
if ($temp < 0) {
|
||||
$temp += 4294967296;
|
||||
}
|
||||
|
||||
$Xl = fmod((fmod($this->_S[0][($temp >> 24) & 255]
|
||||
+ $this->_S[1][($temp >> 16) & 255], 4294967296)
|
||||
^ $this->_S[2][($temp >> 8) & 255])
|
||||
+ $this->_S[3][$temp & 255], 4294967296) ^ $Xr;
|
||||
$Xr = $temp;
|
||||
}
|
||||
|
||||
$Xr = $this->_binxor($Xl, $this->_P[16]);
|
||||
$Xl = $this->_binxor($temp, $this->_P[17]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deciphers a single 64-bit block.
|
||||
*
|
||||
* @param int &$Xl
|
||||
* @param int &$Xr
|
||||
*/
|
||||
protected function _decipher(&$Xl, &$Xr)
|
||||
{
|
||||
if ($Xl < 0) {
|
||||
$Xl += 4294967296;
|
||||
}
|
||||
if ($Xr < 0) {
|
||||
$Xr += 4294967296;
|
||||
}
|
||||
|
||||
for ($i = 17; $i > 1; --$i) {
|
||||
$temp = $Xl ^ $this->_P[$i];
|
||||
if ($temp < 0) {
|
||||
$temp += 4294967296;
|
||||
}
|
||||
|
||||
$Xl = fmod((fmod($this->_S[0][($temp >> 24) & 255]
|
||||
+ $this->_S[1][($temp >> 16) & 255], 4294967296)
|
||||
^ $this->_S[2][($temp >> 8) & 255])
|
||||
+ $this->_S[3][$temp & 255], 4294967296) ^ $Xr;
|
||||
$Xr = $temp;
|
||||
}
|
||||
|
||||
$Xr = $this->_binxor($Xl, $this->_P[1]);
|
||||
$Xl = $this->_binxor($temp, $this->_P[0]);
|
||||
}
|
||||
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2005-2008 Matthew Fonda <mfonda@php.net>
|
||||
* Copyright 2008 Philippe Jausions <jausions@php.net>
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Philippe Jausions <jausions@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
|
||||
/**
|
||||
* PHP implementation of the Blowfish algorithm in CBC mode.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Philippe Jausions <jausions@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2005-2008 Matthew Fonda
|
||||
* @copyright 2008 Philippe Jausions
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
class Horde_Crypt_Blowfish_Php_Cbc extends Horde_Crypt_Blowfish_Php_Base
|
||||
{
|
||||
/**
|
||||
*/
|
||||
public function encrypt($text, $iv)
|
||||
{
|
||||
$cipherText = '';
|
||||
$len = strlen($text);
|
||||
|
||||
list(, $Xl, $Xr) = unpack('N2', substr($text, 0, 8) ^ $iv);
|
||||
$this->_encipher($Xl, $Xr);
|
||||
$cipherText .= pack('N2', $Xl, $Xr);
|
||||
|
||||
for ($i = 8; $i < $len; $i += 8) {
|
||||
list(, $Xl, $Xr) = unpack('N2', substr($text, $i, 8) ^ substr($cipherText, $i - 8, 8));
|
||||
$this->_encipher($Xl, $Xr);
|
||||
$cipherText .= pack('N2', $Xl, $Xr);
|
||||
}
|
||||
|
||||
return $cipherText;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function decrypt($text, $iv)
|
||||
{
|
||||
$plainText = '';
|
||||
$len = strlen($text);
|
||||
|
||||
list(, $Xl, $Xr) = unpack('N2', substr($text, 0, 8));
|
||||
$this->_decipher($Xl, $Xr);
|
||||
$plainText .= (pack('N2', $Xl, $Xr) ^ $iv);
|
||||
|
||||
for ($i = 8; $i < $len; $i += 8) {
|
||||
list(, $Xl, $Xr) = unpack('N2', substr($text, $i, 8));
|
||||
$this->_decipher($Xl, $Xr);
|
||||
$plainText .= (pack('N2', $Xl, $Xr) ^ substr($text, $i - 8, 8));
|
||||
}
|
||||
|
||||
return $plainText;
|
||||
}
|
||||
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2005-2008 Matthew Fonda <mfonda@php.net>
|
||||
* Copyright 2008 Philippe Jausions <jausions@php.net>
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Philippe Jausions <jausions@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
|
||||
/**
|
||||
* PHP implementation of the Blowfish algorithm in ECB mode.
|
||||
*
|
||||
* @author Matthew Fonda <mfonda@php.net>
|
||||
* @author Philippe Jausions <jausions@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2005-2008 Matthew Fonda
|
||||
* @copyright 2008 Philippe Jausions
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Crypt_Blowfish
|
||||
*/
|
||||
class Horde_Crypt_Blowfish_Php_Ecb extends Horde_Crypt_Blowfish_Php_Base
|
||||
{
|
||||
/**
|
||||
*/
|
||||
public function encrypt($text, $iv)
|
||||
{
|
||||
$cipherText = '';
|
||||
$len = strlen($text);
|
||||
|
||||
for ($i = 0; $i < $len; $i += 8) {
|
||||
list(, $Xl, $Xr) = unpack('N2', substr($text, $i, 8));
|
||||
$this->_encipher($Xl, $Xr);
|
||||
$cipherText .= pack('N2', $Xl, $Xr);
|
||||
}
|
||||
|
||||
return $cipherText;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function decrypt($text, $iv)
|
||||
{
|
||||
$plainText = '';
|
||||
$len = strlen($text);
|
||||
|
||||
for ($i = 0; $i < $len; $i += 8) {
|
||||
list(, $Xl, $Xr) = unpack('N2', substr($text, $i, 8));
|
||||
$this->_decipher($Xl, $Xr);
|
||||
$plainText .= pack('N2', $Xl, $Xr);
|
||||
}
|
||||
|
||||
return $plainText;
|
||||
}
|
||||
|
||||
}
|
@ -1,341 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2010-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2010-2017 Horde LLC
|
||||
* @package Util
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parse DOM data from HTML strings.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2010-2017 Horde LLC
|
||||
* @package Util
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
*/
|
||||
class Horde_Domhtml implements Iterator
|
||||
{
|
||||
/**
|
||||
* DOM object.
|
||||
*
|
||||
* @var DOMDocument
|
||||
*/
|
||||
public $dom;
|
||||
|
||||
/**
|
||||
* Iterator status.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_iterator = null;
|
||||
|
||||
/**
|
||||
* Original charset of data.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_origCharset;
|
||||
|
||||
/**
|
||||
* Encoding tag added to beginning of output.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_xmlencoding = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $text The text of the HTML document.
|
||||
* @param string $charset The charset of the HTML document.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($text, $charset = null)
|
||||
{
|
||||
if (!extension_loaded('dom')) {
|
||||
throw new Exception('DOM extension is not available.');
|
||||
}
|
||||
|
||||
// Bug #9616: Make sure we have valid HTML input.
|
||||
if (!strlen($text)) {
|
||||
$text = '<html></html>';
|
||||
}
|
||||
|
||||
$old_error = libxml_use_internal_errors(true);
|
||||
$this->dom = new DOMDocument();
|
||||
|
||||
if (is_null($charset)) {
|
||||
/* If no charset given, charset is whatever libxml tells us the
|
||||
* encoding should be defaulting to 'iso-8859-1'. */
|
||||
$this->_loadHTML($text);
|
||||
$this->_origCharset = $this->dom->encoding
|
||||
? $this->dom->encoding
|
||||
: 'iso-8859-1';
|
||||
} else {
|
||||
/* Convert/try with UTF-8 first. */
|
||||
$this->_origCharset = Horde_String::lower($charset);
|
||||
$this->_xmlencoding = '<?xml encoding="UTF-8"?>';
|
||||
$this->_loadHTML(
|
||||
$this->_xmlencoding . Horde_String::convertCharset($text, $charset, 'UTF-8')
|
||||
);
|
||||
|
||||
if ($this->dom->encoding &&
|
||||
(Horde_String::lower($this->dom->encoding) != 'utf-8')) {
|
||||
/* Convert charset to what the HTML document says it SHOULD
|
||||
* be. */
|
||||
$this->_loadHTML(
|
||||
Horde_String::convertCharset($text, $charset, $this->dom->encoding)
|
||||
);
|
||||
$this->_xmlencoding = '';
|
||||
}
|
||||
}
|
||||
|
||||
if ($old_error) {
|
||||
libxml_use_internal_errors(false);
|
||||
}
|
||||
|
||||
/* Sanity checking: make sure we have the documentElement object. */
|
||||
if (!$this->dom->documentElement) {
|
||||
$this->dom->appendChild($this->dom->createElement('html'));
|
||||
}
|
||||
|
||||
/* Remove old charset information. */
|
||||
$xpath = new DOMXPath($this->dom);
|
||||
$domlist = $xpath->query('/html/head/meta[@http-equiv="content-type"]');
|
||||
for ($i = $domlist->length; $i > 0; --$i) {
|
||||
$meta = $domlist->item($i - 1);
|
||||
$meta->parentNode->removeChild($meta);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HEAD element, or creates one if it doesn't exist.
|
||||
*
|
||||
* @return DOMElement HEAD element.
|
||||
*/
|
||||
public function getHead()
|
||||
{
|
||||
$head = $this->dom->getElementsByTagName('head');
|
||||
if ($head->length) {
|
||||
return $head->item(0);
|
||||
}
|
||||
|
||||
$headelt = $this->dom->createElement('head');
|
||||
$this->dom->documentElement->insertBefore($headelt, $this->dom->documentElement->firstChild);
|
||||
|
||||
return $headelt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the BODY element, or creates one if it doesn't exist.
|
||||
*
|
||||
* @since 2.2.0
|
||||
*
|
||||
* @return DOMElement BODY element.
|
||||
*/
|
||||
public function getBody()
|
||||
{
|
||||
$body = $this->dom->getElementsByTagName('body');
|
||||
if ($body->length) {
|
||||
return $body->item(0);
|
||||
}
|
||||
|
||||
$bodyelt = $this->dom->createElement('body');
|
||||
$this->dom->documentElement->appendChild($bodyelt);
|
||||
|
||||
return $bodyelt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full HTML text in the original charset.
|
||||
*
|
||||
* @param array $opts Additional options: (since 2.1.0)
|
||||
* - charset: (string) Return using this charset. If set but empty, will
|
||||
* return as currently stored in the DOM object.
|
||||
* - metacharset: (boolean) If true, will add a META tag containing the
|
||||
* charset information.
|
||||
*
|
||||
* @return string HTML text.
|
||||
*/
|
||||
public function returnHtml(array $opts = array())
|
||||
{
|
||||
$curr_charset = $this->getCharset();
|
||||
if (strcasecmp($curr_charset, 'US-ASCII') === 0) {
|
||||
$curr_charset = 'UTF-8';
|
||||
}
|
||||
$charset = array_key_exists('charset', $opts)
|
||||
? (empty($opts['charset']) ? $curr_charset : $opts['charset'])
|
||||
: $this->_origCharset;
|
||||
|
||||
if (empty($opts['metacharset'])) {
|
||||
$text = $this->dom->saveHTML();
|
||||
} else {
|
||||
/* Add placeholder for META tag. Can't add charset yet because DOM
|
||||
* extension will alter output if it exists. */
|
||||
$meta = $this->dom->createElement('meta');
|
||||
$meta->setAttribute('http-equiv', 'content-type');
|
||||
$meta->setAttribute('horde_dom_html_charset', '');
|
||||
|
||||
$head = $this->getHead();
|
||||
$head->insertBefore($meta, $head->firstChild);
|
||||
|
||||
$text = str_replace(
|
||||
'horde_dom_html_charset=""',
|
||||
'content="text/html; charset=' . $charset . '"',
|
||||
$this->dom->saveHTML()
|
||||
);
|
||||
|
||||
$head->removeChild($meta);
|
||||
}
|
||||
|
||||
if (strcasecmp($curr_charset, $charset) !== 0) {
|
||||
$text = Horde_String::convertCharset($text, $curr_charset, $charset);
|
||||
}
|
||||
|
||||
if (!$this->_xmlencoding ||
|
||||
(($pos = strpos($text, $this->_xmlencoding)) === false)) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
return substr_replace($text, '', $pos, strlen($this->_xmlencoding));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the body text in the original charset.
|
||||
*
|
||||
* @return string HTML text.
|
||||
*/
|
||||
public function returnBody()
|
||||
{
|
||||
$body = $this->getBody();
|
||||
$text = '';
|
||||
|
||||
if ($body->hasChildNodes()) {
|
||||
foreach ($body->childNodes as $child) {
|
||||
$text .= $this->dom->saveXML($child);
|
||||
}
|
||||
}
|
||||
|
||||
return Horde_String::convertCharset($text, 'UTF-8', $this->_origCharset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the charset of the DOM data.
|
||||
*
|
||||
* @since 2.1.0
|
||||
*
|
||||
* @return string Charset of DOM data.
|
||||
*/
|
||||
public function getCharset()
|
||||
{
|
||||
return $this->dom->encoding
|
||||
? $this->dom->encoding
|
||||
: ($this->_xmlencoding ? 'UTF-8' : $this->_origCharset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the HTML data.
|
||||
*
|
||||
* @param string $html HTML data.
|
||||
*/
|
||||
protected function _loadHTML($html)
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.4', '>=')) {
|
||||
$mask = defined('LIBXML_PARSEHUGE')
|
||||
? LIBXML_PARSEHUGE
|
||||
: 0;
|
||||
$mask |= defined('LIBXML_COMPACT')
|
||||
? LIBXML_COMPACT
|
||||
: 0;
|
||||
$this->dom->loadHTML($html, $mask);
|
||||
} else {
|
||||
$this->dom->loadHTML($html);
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterator methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
if ($this->_iterator instanceof DOMDocument) {
|
||||
return $this->_iterator;
|
||||
}
|
||||
|
||||
$curr = end($this->_iterator);
|
||||
return $curr['list']->item($curr['i']);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function key()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function next()
|
||||
{
|
||||
/* Iterate in the reverse direction through the node list. This allows
|
||||
* alteration of the original list without breaking things (foreach()
|
||||
* w/removeChild() may exit iteration after removal is complete. */
|
||||
|
||||
if ($this->_iterator instanceof DOMDocument) {
|
||||
$this->_iterator = array();
|
||||
$curr = array();
|
||||
$node = $this->dom;
|
||||
} elseif (empty($this->_iterator)) {
|
||||
$this->_iterator = null;
|
||||
return;
|
||||
} else {
|
||||
$curr = &$this->_iterator[count($this->_iterator) - 1];
|
||||
$node = $curr['list']->item($curr['i']);
|
||||
}
|
||||
|
||||
if (empty($curr['child']) &&
|
||||
($node instanceof DOMNode) &&
|
||||
$node->hasChildNodes()) {
|
||||
$curr['child'] = true;
|
||||
$this->_iterator[] = array(
|
||||
'child' => false,
|
||||
'i' => $node->childNodes->length - 1,
|
||||
'list' => $node->childNodes
|
||||
);
|
||||
} elseif (--$curr['i'] < 0) {
|
||||
array_pop($this->_iterator);
|
||||
$this->next();
|
||||
} else {
|
||||
$curr['child'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function rewind()
|
||||
{
|
||||
$this->_iterator = $this->dom;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function valid()
|
||||
{
|
||||
return !is_null($this->_iterator);
|
||||
}
|
||||
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2008-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
|
||||
* @package Exception
|
||||
*/
|
||||
|
||||
/**
|
||||
* Horde base exception class.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @copyright 2008-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
|
||||
* @package Exception
|
||||
*/
|
||||
class Horde_Exception extends Exception
|
||||
{
|
||||
/**
|
||||
* Error details that should not be part of the main exception message,
|
||||
* e.g. any additional debugging information.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $details;
|
||||
|
||||
/**
|
||||
* Has this exception been logged?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $logged = false;
|
||||
|
||||
/**
|
||||
* The log level to use. A Horde_Log constant.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $_logLevel = 0;
|
||||
|
||||
/**
|
||||
* Get the log level.
|
||||
*
|
||||
* @return integer The Horde_Log constant for the log level.
|
||||
*/
|
||||
public function getLogLevel()
|
||||
{
|
||||
return $this->_logLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the log level.
|
||||
*
|
||||
* @param mixed $level The log level.
|
||||
*/
|
||||
public function setLogLevel($level = 0)
|
||||
{
|
||||
if (is_string($level)) {
|
||||
$level = defined('Horde_Log::' . $level)
|
||||
? constant('Horde_Log::' . $level)
|
||||
: 0;
|
||||
}
|
||||
|
||||
$this->_logLevel = $level;
|
||||
}
|
||||
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2008-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
|
||||
/**
|
||||
* Horde exception class that accepts output of error_get_last() as $code and
|
||||
* mask itself as that error.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @copyright 2008-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
class Horde_Exception_LastError extends Horde_Exception
|
||||
{
|
||||
/**
|
||||
* Exception constructor
|
||||
*
|
||||
* If $lasterror is passed the return value of error_get_last() (or a
|
||||
* matching format), the exception will be rewritten to have its file and
|
||||
* line parameters match that of the array, and any message in the array
|
||||
* will be appended to $message.
|
||||
*
|
||||
* @param mixed $message The exception message, a PEAR_Error
|
||||
* object, or an Exception object.
|
||||
* @param mixed $code_or_lasterror Either a numeric error code, or
|
||||
* an array from error_get_last().
|
||||
*/
|
||||
public function __construct($message = null, $code_or_lasterror = null)
|
||||
{
|
||||
if (is_array($code_or_lasterror)) {
|
||||
if ($message) {
|
||||
$message .= $code_or_lasterror['message'];
|
||||
} else {
|
||||
$message = $code_or_lasterror['message'];
|
||||
}
|
||||
parent::__construct($message, $code_or_lasterror['type']);
|
||||
$this->file = $code_or_lasterror['file'];
|
||||
$this->line = $code_or_lasterror['line'];
|
||||
} else {
|
||||
parent::__construct($message, $code_or_lasterror ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2010-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception thrown if an object wasn't found.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @copyright 2010-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
class Horde_Exception_NotFound extends Horde_Exception
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @see Horde_Exception::__construct()
|
||||
*
|
||||
* @param mixed $message The exception message, a PEAR_Error
|
||||
* object, or an Exception object.
|
||||
* @param integer $code A numeric error code.
|
||||
*/
|
||||
public function __construct($message = null, $code = null)
|
||||
{
|
||||
if (is_null($message)) {
|
||||
$message = Horde_Exception_Translation::t("Not Found");
|
||||
}
|
||||
parent::__construct($message, $code);
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2008-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
|
||||
/**
|
||||
* Horde exception class that converts PEAR errors to exceptions.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @copyright 2008-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
class Horde_Exception_Pear extends Horde_Exception
|
||||
{
|
||||
/**
|
||||
* The class name for generated exceptions.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $_class = __CLASS__;
|
||||
|
||||
/**
|
||||
* Exception constructor.
|
||||
*
|
||||
* @param PEAR_Error $error The PEAR error.
|
||||
*/
|
||||
public function __construct(PEAR_Error $error)
|
||||
{
|
||||
parent::__construct($error->getMessage(), $error->getCode());
|
||||
$this->details = $this->_getPearTrace($error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a trace for the PEAR error.
|
||||
*
|
||||
* @param PEAR_Error $error The PEAR error.
|
||||
*
|
||||
* @return string The backtrace as a string.
|
||||
*/
|
||||
private function _getPearTrace(PEAR_Error $error)
|
||||
{
|
||||
$pear_error = '';
|
||||
$backtrace = $error->getBacktrace();
|
||||
if (!empty($backtrace)) {
|
||||
$pear_error .= 'PEAR backtrace:' . "\n\n";
|
||||
foreach ($backtrace as $frame) {
|
||||
$pear_error .=
|
||||
(isset($frame['class']) ? $frame['class'] : '')
|
||||
. (isset($frame['type']) ? $frame['type'] : '')
|
||||
. (isset($frame['function']) ? $frame['function'] : 'unkown') . ' '
|
||||
. (isset($frame['file']) ? $frame['file'] : 'unkown') . ':'
|
||||
. (isset($frame['line']) ? $frame['line'] : 'unkown') . "\n";
|
||||
}
|
||||
}
|
||||
$userinfo = $error->getUserInfo();
|
||||
if (!empty($userinfo)) {
|
||||
$pear_error .= "\n" . 'PEAR user info:' . "\n\n";
|
||||
if (is_string($userinfo)) {
|
||||
$pear_error .= $userinfo;
|
||||
} else {
|
||||
$pear_error .= print_r($userinfo, true);
|
||||
}
|
||||
}
|
||||
return $pear_error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception handling.
|
||||
*
|
||||
* @param mixed $result The result to be checked for a PEAR_Error.
|
||||
*
|
||||
* @return mixed Returns the original result if it was no PEAR_Error.
|
||||
*
|
||||
* @throws Horde_Exception_Pear In case the result was a PEAR_Error.
|
||||
*/
|
||||
public static function catchError($result)
|
||||
{
|
||||
if ($result instanceof PEAR_Error) {
|
||||
throw new self::$_class($result);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2010-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception thrown if any access without sufficient permissions occured.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @copyright 2010-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
class Horde_Exception_PermissionDenied extends Horde_Exception
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @see Horde_Exception::__construct()
|
||||
*
|
||||
* @param string|Exception $message The exception message, a PEAR_Error
|
||||
* object, or an Exception object.
|
||||
* @param integer $code A numeric error code.
|
||||
*/
|
||||
public function __construct($message = null, $code = null)
|
||||
{
|
||||
if (is_null($message)) {
|
||||
$message = Horde_Exception_Translation::t("Permission Denied");
|
||||
}
|
||||
parent::__construct($message, $code);
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2010-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author Jan Schneider <jan@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
|
||||
/**
|
||||
* Horde_Exception_Translation is the translation wrapper class for Horde_Exception.
|
||||
*
|
||||
* @author Jan Schneider <jan@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2010-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
class Horde_Exception_Translation extends Horde_Translation_Autodetect
|
||||
{
|
||||
/**
|
||||
* The translation domain
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $_domain = 'Horde_Exception';
|
||||
|
||||
/**
|
||||
* The absolute PEAR path to the translations for the default gettext handler.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $_pearDirectory = '@data_dir@';
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2008-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
|
||||
/**
|
||||
* Horde exception class that can wrap and set its details from PEAR_Error,
|
||||
* Exception, and other objects with similar interfaces.
|
||||
*
|
||||
* @author
|
||||
* @category Horde
|
||||
* @copyright 2008-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL
|
||||
* @package Exception
|
||||
*/
|
||||
class Horde_Exception_Wrapped extends Horde_Exception
|
||||
{
|
||||
/**
|
||||
* Exception constructor.
|
||||
*
|
||||
* @param mixed $message The exception message, a PEAR_Error
|
||||
* object, or an Exception object.
|
||||
* @param int $code A numeric error code.
|
||||
*/
|
||||
public function __construct($message = null, $code = 0)
|
||||
{
|
||||
$previous = null;
|
||||
if (is_object($message) &&
|
||||
method_exists($message, 'getMessage')) {
|
||||
if (empty($code) &&
|
||||
method_exists($message, 'getCode')) {
|
||||
$code = (int)$message->getCode();
|
||||
}
|
||||
if ($message instanceof Exception) {
|
||||
$previous = $message;
|
||||
}
|
||||
if (method_exists($message, 'getUserinfo') &&
|
||||
$details = $message->getUserinfo()) {
|
||||
$this->details = $details;
|
||||
} elseif (!empty($message->details)) {
|
||||
$this->details = $message->details;
|
||||
}
|
||||
$message = (string)$message->getMessage();
|
||||
}
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (BSD). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/bsd.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/bsd BSD
|
||||
* @package Idna
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provide normalized encoding/decoding support for IDNA strings.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/bsd BSD
|
||||
* @package Idna
|
||||
*/
|
||||
class Horde_Idna
|
||||
{
|
||||
/**
|
||||
* The backend to use.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected static $_backend;
|
||||
|
||||
/**
|
||||
* @throws Horde_Idna_Exception
|
||||
*/
|
||||
public static function encode($data)
|
||||
{
|
||||
switch ($backend = static::_getBackend()) {
|
||||
case 'INTL':
|
||||
if ($data === null) {
|
||||
return false;
|
||||
}
|
||||
return idn_to_ascii($data);
|
||||
|
||||
case 'INTL_UTS46':
|
||||
if ($data === null) {
|
||||
return false;
|
||||
}
|
||||
$result = idn_to_ascii($data, 0, INTL_IDNA_VARIANT_UTS46, $info);
|
||||
self::_checkForError($info);
|
||||
return $result;
|
||||
|
||||
default:
|
||||
return $backend->encode($data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Horde_Idna_Exception
|
||||
*/
|
||||
public static function decode($data)
|
||||
{
|
||||
switch ($backend = static::_getBackend()) {
|
||||
case 'INTL':
|
||||
case 'INTL_UTS46':
|
||||
$parts = explode('.', $data);
|
||||
foreach ($parts as &$part) {
|
||||
if (strpos($part, 'xn--') === 0) {
|
||||
switch ($backend) {
|
||||
case 'INTL':
|
||||
$part = idn_to_utf8($part);
|
||||
break;
|
||||
|
||||
case 'INTL_UTS46':
|
||||
$part = idn_to_utf8($part, 0, INTL_IDNA_VARIANT_UTS46, $info);
|
||||
self::_checkForError($info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode('.', $parts);
|
||||
|
||||
default:
|
||||
return $backend->decode($data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the $idna_info parameter of idn_to_ascii() or idn_to_utf8()
|
||||
* contains errors.
|
||||
*
|
||||
* @param array $info Fourth parameter to idn_to_ascii() or idn_to_utf8().
|
||||
*
|
||||
* @throws Horde_Idna_Exception
|
||||
*/
|
||||
protected static function _checkForError($info)
|
||||
{
|
||||
if (!isset($info['errors'])) {
|
||||
return;
|
||||
}
|
||||
switch (true) {
|
||||
case $info['errors'] & IDNA_ERROR_EMPTY_LABEL:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Domain name is empty"
|
||||
));
|
||||
case $info['errors'] & IDNA_ERROR_LABEL_TOO_LONG:
|
||||
case $info['errors'] & IDNA_ERROR_DOMAIN_NAME_TOO_LONG:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Domain name is too long"
|
||||
));
|
||||
case $info['errors'] & IDNA_ERROR_LEADING_HYPHEN:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Starts with a hyphen"
|
||||
));
|
||||
case $info['errors'] & IDNA_ERROR_TRAILING_HYPHEN:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Ends with a hyphen"
|
||||
));
|
||||
case $info['errors'] & IDNA_ERROR_HYPHEN_3_4:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Contains hyphen in the third and fourth positions"
|
||||
));
|
||||
case $info['errors'] & IDNA_ERROR_LEADING_COMBINING_MARK:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Starts with a combining mark"
|
||||
));
|
||||
case $info['errors'] & IDNA_ERROR_DISALLOWED:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Contains disallowed characters"
|
||||
));
|
||||
case $info['errors'] & IDNA_ERROR_PUNYCODE:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Starts with \"xn--\" but does not contain valid Punycode"
|
||||
));
|
||||
case $info['errors'] & IDNA_ERROR_LABEL_HAS_DOT:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Contains a dot"
|
||||
));
|
||||
case $info['errors'] & IDNA_ERROR_INVALID_ACE_LABEL:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"ACE label does not contain a valid label string"
|
||||
));
|
||||
case $info['errors'] & IDNA_ERROR_BIDI:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Does not meet the IDNA BiDi requirements (for right-to-left characters)"
|
||||
));
|
||||
case $info['errors'] & IDNA_ERROR_CONTEXTJ:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Does not meet the IDNA CONTEXTJ requirements"
|
||||
));
|
||||
case $info['errors']:
|
||||
throw new Horde_Idna_Exception(Horde_Idna_Translation::t(
|
||||
"Unknown error"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the IDNA backend.
|
||||
*
|
||||
* @return mixed IDNA backend (false if none available).
|
||||
*/
|
||||
protected static function _getBackend()
|
||||
{
|
||||
if (!isset(self::$_backend)) {
|
||||
if (extension_loaded('intl')) {
|
||||
/* Only available in PHP > 5.4.0 */
|
||||
self::$_backend = defined('INTL_IDNA_VARIANT_UTS46')
|
||||
? 'INTL_UTS46'
|
||||
: 'INTL';
|
||||
} else {
|
||||
self::$_backend = new Horde_Idna_Punycode();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$_backend;
|
||||
}
|
||||
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (BSD). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/bsd.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/bsd BSD
|
||||
* @package Idna
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception class for the Horde_Idna package.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/bsd BSD
|
||||
* @package Idna
|
||||
*/
|
||||
class Horde_Idna_Exception extends Horde_Exception
|
||||
{}
|
@ -1,354 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014 TrueServer B.V.
|
||||
* Copyright 2015-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (BSD). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/bsd.
|
||||
*
|
||||
* @author Renan Gonçalves <renan.saddam@gmail.com>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/bsd BSD
|
||||
* @package Idna
|
||||
*/
|
||||
|
||||
/**
|
||||
* Punycode implementation as described in RFC 3492.
|
||||
*
|
||||
* Original code (v1.0.1; released under the MIT License):
|
||||
* https://github.com/true/php-punycode/
|
||||
*
|
||||
* @author Renan Gonçalves <renan.saddam@gmail.com>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014 TrueServer B.V.
|
||||
* @copyright 2015-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/bsd BSD
|
||||
* @package Idna
|
||||
* @link http://tools.ietf.org/html/rfc3492
|
||||
*/
|
||||
class Horde_Idna_Punycode
|
||||
{
|
||||
/**
|
||||
* Bootstring parameter values.
|
||||
*/
|
||||
const BASE = 36;
|
||||
const TMIN = 1;
|
||||
const TMAX = 26;
|
||||
const SKEW = 38;
|
||||
const DAMP = 700;
|
||||
const INITIAL_BIAS = 72;
|
||||
const INITIAL_N = 128;
|
||||
const PREFIX = 'xn--';
|
||||
const DELIMITER = '-';
|
||||
|
||||
/**
|
||||
* Encode table.
|
||||
*
|
||||
* @param array
|
||||
*/
|
||||
protected static $_encodeTable = array(
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
||||
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
|
||||
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
);
|
||||
|
||||
/**
|
||||
* Decode table.
|
||||
*
|
||||
* @param array
|
||||
*/
|
||||
protected static $_decodeTable = array(
|
||||
'a' => 0, 'b' => 1, 'c' => 2, 'd' => 3, 'e' => 4, 'f' => 5,
|
||||
'g' => 6, 'h' => 7, 'i' => 8, 'j' => 9, 'k' => 10, 'l' => 11,
|
||||
'm' => 12, 'n' => 13, 'o' => 14, 'p' => 15, 'q' => 16, 'r' => 17,
|
||||
's' => 18, 't' => 19, 'u' => 20, 'v' => 21, 'w' => 22, 'x' => 23,
|
||||
'y' => 24, 'z' => 25, '0' => 26, '1' => 27, '2' => 28, '3' => 29,
|
||||
'4' => 30, '5' => 31, '6' => 32, '7' => 33, '8' => 34, '9' => 35
|
||||
);
|
||||
|
||||
/**
|
||||
* Encode a domain to its Punycode version.
|
||||
*
|
||||
* @param string $input Domain name in Unicde to be encoded.
|
||||
*
|
||||
* @return string Punycode representation in ASCII.
|
||||
*/
|
||||
public function encode($input)
|
||||
{
|
||||
$parts = explode('.', $input);
|
||||
|
||||
foreach ($parts as &$part) {
|
||||
$part = $this->_encodePart($part);
|
||||
}
|
||||
|
||||
return implode('.', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a part of a domain name, such as tld, to its Punycode version.
|
||||
*
|
||||
* @param string $input Part of a domain name.
|
||||
*
|
||||
* @return string Punycode representation of a domain part.
|
||||
*/
|
||||
protected function _encodePart($input)
|
||||
{
|
||||
$codePoints = $this->_codePoints($input);
|
||||
|
||||
$n = static::INITIAL_N;
|
||||
$bias = static::INITIAL_BIAS;
|
||||
$delta = 0;
|
||||
$h = $b = count($codePoints['basic']);
|
||||
|
||||
$output = '';
|
||||
foreach ($codePoints['basic'] as $code) {
|
||||
$output .= $this->_codePointToChar($code);
|
||||
}
|
||||
if ($input === $output) {
|
||||
return $output;
|
||||
}
|
||||
if ($b > 0) {
|
||||
$output .= static::DELIMITER;
|
||||
}
|
||||
|
||||
$codePoints['nonBasic'] = array_unique($codePoints['nonBasic']);
|
||||
sort($codePoints['nonBasic']);
|
||||
|
||||
$i = 0;
|
||||
$length = Horde_String::length($input, 'UTF-8');
|
||||
|
||||
while ($h < $length) {
|
||||
$m = $codePoints['nonBasic'][$i++];
|
||||
$delta = $delta + ($m - $n) * ($h + 1);
|
||||
$n = $m;
|
||||
|
||||
foreach ($codePoints['all'] as $c) {
|
||||
if (($c < $n) || ($c < static::INITIAL_N)) {
|
||||
++$delta;
|
||||
}
|
||||
|
||||
if ($c === $n) {
|
||||
$q = $delta;
|
||||
for ($k = static::BASE; ; $k += static::BASE) {
|
||||
$t = $this->_calculateThreshold($k, $bias);
|
||||
if ($q < $t) {
|
||||
break;
|
||||
}
|
||||
|
||||
$code = $t + (($q - $t) % (static::BASE - $t));
|
||||
$output .= static::$_encodeTable[$code];
|
||||
|
||||
$q = ($q - $t) / (static::BASE - $t);
|
||||
}
|
||||
|
||||
$output .= static::$_encodeTable[$q];
|
||||
$bias = $this->_adapt($delta, $h + 1, ($h === $b));
|
||||
$delta = 0;
|
||||
++$h;
|
||||
}
|
||||
}
|
||||
|
||||
++$delta;
|
||||
++$n;
|
||||
}
|
||||
|
||||
return static::PREFIX . $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a Punycode domain name to its Unicode counterpart.
|
||||
*
|
||||
* @param string $input Domain name in Punycode
|
||||
*
|
||||
* @return string Unicode domain name.
|
||||
*/
|
||||
public function decode($input)
|
||||
{
|
||||
$parts = explode('.', $input);
|
||||
|
||||
foreach ($parts as &$part) {
|
||||
if (strpos($part, static::PREFIX) === 0) {
|
||||
$part = $this->_decodePart(
|
||||
substr($part, strlen(static::PREFIX))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return implode('.', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a part of domain name, such as tld.
|
||||
*
|
||||
* @param string $input Part of a domain name.
|
||||
*
|
||||
* @return string Unicode domain part.
|
||||
*/
|
||||
protected function _decodePart($input)
|
||||
{
|
||||
$n = static::INITIAL_N;
|
||||
$i = 0;
|
||||
$bias = static::INITIAL_BIAS;
|
||||
$output = '';
|
||||
|
||||
$pos = strrpos($input, static::DELIMITER);
|
||||
if ($pos !== false) {
|
||||
$output = substr($input, 0, $pos++);
|
||||
} else {
|
||||
$pos = 0;
|
||||
}
|
||||
|
||||
$outputLength = strlen($output);
|
||||
$inputLength = strlen($input);
|
||||
|
||||
/* Punycode lookup is case-insensitive. */
|
||||
$input = Horde_String::lower($input);
|
||||
|
||||
while ($pos < $inputLength) {
|
||||
$oldi = $i;
|
||||
$w = 1;
|
||||
|
||||
for ($k = static::BASE; ; $k += static::BASE) {
|
||||
$digit = static::$_decodeTable[$input[$pos++]];
|
||||
$i = $i + ($digit * $w);
|
||||
$t = $this->_calculateThreshold($k, $bias);
|
||||
|
||||
if ($digit < $t) {
|
||||
break;
|
||||
}
|
||||
|
||||
$w = $w * (static::BASE - $t);
|
||||
}
|
||||
|
||||
$bias = $this->_adapt($i - $oldi, ++$outputLength, ($oldi === 0));
|
||||
$n = $n + (int) ($i / $outputLength);
|
||||
$i = $i % ($outputLength);
|
||||
|
||||
$output = Horde_String::substr($output, 0, $i, 'UTF-8') .
|
||||
$this->_codePointToChar($n) .
|
||||
Horde_String::substr($output, $i, $outputLength - 1, 'UTF-8');
|
||||
|
||||
++$i;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the bias threshold to fall between TMIN and TMAX.
|
||||
*
|
||||
* @param integer $k
|
||||
* @param integer $bias
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
protected function _calculateThreshold($k, $bias)
|
||||
{
|
||||
if ($k <= ($bias + static::TMIN)) {
|
||||
return static::TMIN;
|
||||
} elseif ($k >= ($bias + static::TMAX)) {
|
||||
return static::TMAX;
|
||||
}
|
||||
return $k - $bias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bias adaptation.
|
||||
*
|
||||
* @param integer $delta
|
||||
* @param integer $numPoints
|
||||
* @param boolean $firstTime
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
protected function _adapt($delta, $numPoints, $firstTime)
|
||||
{
|
||||
$delta = (int) (
|
||||
($firstTime)
|
||||
? $delta / static::DAMP
|
||||
: $delta / 2
|
||||
);
|
||||
$delta += (int) ($delta / $numPoints);
|
||||
|
||||
$k = 0;
|
||||
while ($delta > ((static::BASE - static::TMIN) * static::TMAX) / 2) {
|
||||
$delta = (int) ($delta / (static::BASE - static::TMIN));
|
||||
$k = $k + static::BASE;
|
||||
}
|
||||
$k = $k + (int) (((static::BASE - static::TMIN + 1) * $delta) / ($delta + static::SKEW));
|
||||
|
||||
return $k;
|
||||
}
|
||||
|
||||
/**
|
||||
* List code points for a given input.
|
||||
*
|
||||
* @param string $input
|
||||
*
|
||||
* @return array Multi-dimension array with basic, non-basic and
|
||||
* aggregated code points.
|
||||
*/
|
||||
protected function _codePoints($input)
|
||||
{
|
||||
$codePoints = array(
|
||||
'all' => array(),
|
||||
'basic' => array(),
|
||||
'nonBasic' => array()
|
||||
);
|
||||
|
||||
$len = Horde_String::length($input, 'UTF-8');
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
$char = Horde_String::substr($input, $i, 1, 'UTF-8');
|
||||
$code = $this->_charToCodePoint($char);
|
||||
if ($code < 128) {
|
||||
$codePoints['all'][] = $codePoints['basic'][] = $code;
|
||||
} else {
|
||||
$codePoints['all'][] = $codePoints['nonBasic'][] = $code;
|
||||
}
|
||||
}
|
||||
|
||||
return $codePoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a single or multi-byte character to its code point.
|
||||
*
|
||||
* @param string $char
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
protected function _charToCodePoint($char)
|
||||
{
|
||||
$code = ord($char[0]);
|
||||
if ($code < 128) {
|
||||
return $code;
|
||||
} elseif ($code < 224) {
|
||||
return (($code - 192) * 64) + (ord($char[1]) - 128);
|
||||
} elseif ($code < 240) {
|
||||
return (($code - 224) * 4096) + ((ord($char[1]) - 128) * 64) + (ord($char[2]) - 128);
|
||||
}
|
||||
return (($code - 240) * 262144) + ((ord($char[1]) - 128) * 4096) + ((ord($char[2]) - 128) * 64) + (ord($char[3]) - 128);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a code point to its single or multi-byte character
|
||||
*
|
||||
* @param integer $code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _codePointToChar($code)
|
||||
{
|
||||
if ($code <= 0x7F) {
|
||||
return chr($code);
|
||||
} elseif ($code <= 0x7FF) {
|
||||
return chr(($code >> 6) + 192) . chr(($code & 63) + 128);
|
||||
} elseif ($code <= 0xFFFF) {
|
||||
return chr(($code >> 12) + 224) . chr((($code >> 6) & 63) + 128) . chr(($code & 63) + 128);
|
||||
}
|
||||
return chr(($code >> 18) + 240) . chr((($code >> 12) & 63) + 128) . chr((($code >> 6) & 63) + 128) . chr(($code & 63) + 128);
|
||||
}
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (BSD). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/bsd.
|
||||
*
|
||||
* @author Jan Schneider <jan@horde.org>
|
||||
* @category Horde
|
||||
* @license http://www.horde.org/licenses/bsd BSD
|
||||
* @package Idna
|
||||
*/
|
||||
|
||||
/**
|
||||
* Horde_Idna_Translation is the translation wrapper class for
|
||||
* Horde_Idna.
|
||||
*
|
||||
* @author Jan Schneider <jan@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/bsd BSD
|
||||
* @package Idna
|
||||
* @since Horde_Idna 1.1.0
|
||||
*/
|
||||
class Horde_Idna_Translation extends Horde_Translation_Autodetect
|
||||
{
|
||||
/**
|
||||
* The translation domain
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $_domain = 'Horde_Idna';
|
||||
|
||||
/**
|
||||
* The absolute PEAR path to the translations for the default gettext handler.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $_pearDirectory = '@data_dir@';
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2008-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2008-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base class for Horde_Imap_Client package. Defines common constants for use
|
||||
* in the package.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2008-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client
|
||||
{
|
||||
/* Constants for openMailbox() */
|
||||
const OPEN_READONLY = 1;
|
||||
const OPEN_READWRITE = 2;
|
||||
const OPEN_AUTO = 3;
|
||||
|
||||
/* Constants for listMailboxes() */
|
||||
const MBOX_SUBSCRIBED = 1;
|
||||
const MBOX_SUBSCRIBED_EXISTS = 2;
|
||||
const MBOX_UNSUBSCRIBED = 3;
|
||||
const MBOX_ALL = 4;
|
||||
/* @since 2.23.0 */
|
||||
const MBOX_ALL_SUBSCRIBED = 5;
|
||||
|
||||
/* Constants for status() */
|
||||
const STATUS_MESSAGES = 1;
|
||||
const STATUS_RECENT = 2;
|
||||
const STATUS_UIDNEXT = 4;
|
||||
const STATUS_UIDVALIDITY = 8;
|
||||
const STATUS_UNSEEN = 16;
|
||||
const STATUS_ALL = 32;
|
||||
const STATUS_FIRSTUNSEEN = 64;
|
||||
const STATUS_FLAGS = 128;
|
||||
const STATUS_PERMFLAGS = 256;
|
||||
const STATUS_HIGHESTMODSEQ = 512;
|
||||
const STATUS_SYNCMODSEQ = 1024;
|
||||
const STATUS_SYNCFLAGUIDS = 2048;
|
||||
const STATUS_UIDNOTSTICKY = 4096;
|
||||
const STATUS_UIDNEXT_FORCE = 8192;
|
||||
const STATUS_SYNCVANISHED = 16384;
|
||||
/* @since 2.12.0 */
|
||||
const STATUS_RECENT_TOTAL = 32768;
|
||||
/* @since 2.14.0 */
|
||||
const STATUS_FORCE_REFRESH = 65536;
|
||||
|
||||
/* Constants for search() */
|
||||
const SORT_ARRIVAL = 1;
|
||||
const SORT_CC = 2;
|
||||
const SORT_DATE = 3;
|
||||
const SORT_FROM = 4;
|
||||
const SORT_REVERSE = 5;
|
||||
const SORT_SIZE = 6;
|
||||
const SORT_SUBJECT = 7;
|
||||
const SORT_TO = 8;
|
||||
/* SORT_THREAD provided for completeness - it is not a valid sort criteria
|
||||
* for search() (use thread() instead). */
|
||||
const SORT_THREAD = 9;
|
||||
/* Sort criteria defined in RFC 5957 */
|
||||
const SORT_DISPLAYFROM = 10;
|
||||
const SORT_DISPLAYTO = 11;
|
||||
/* SORT_SEQUENCE does a simple numerical sort on the returned
|
||||
* UIDs/sequence numbers. */
|
||||
const SORT_SEQUENCE = 12;
|
||||
/* Fuzzy sort criteria defined in RFC 6203 */
|
||||
const SORT_RELEVANCY = 13;
|
||||
/* @since 2.4.0 */
|
||||
const SORT_DISPLAYFROM_FALLBACK = 14;
|
||||
/* @since 2.4.0 */
|
||||
const SORT_DISPLAYTO_FALLBACK = 15;
|
||||
|
||||
/* Search results constants */
|
||||
const SEARCH_RESULTS_COUNT = 1;
|
||||
const SEARCH_RESULTS_MATCH = 2;
|
||||
const SEARCH_RESULTS_MAX = 3;
|
||||
const SEARCH_RESULTS_MIN = 4;
|
||||
const SEARCH_RESULTS_SAVE = 5;
|
||||
/* Fuzzy sort criteria defined in RFC 6203 */
|
||||
const SEARCH_RESULTS_RELEVANCY = 6;
|
||||
|
||||
/* Constants for thread() */
|
||||
const THREAD_ORDEREDSUBJECT = 1;
|
||||
const THREAD_REFERENCES = 2;
|
||||
const THREAD_REFS = 3;
|
||||
|
||||
/* Fetch criteria constants. */
|
||||
const FETCH_STRUCTURE = 1;
|
||||
const FETCH_FULLMSG = 2;
|
||||
const FETCH_HEADERTEXT = 3;
|
||||
const FETCH_BODYTEXT = 4;
|
||||
const FETCH_MIMEHEADER = 5;
|
||||
const FETCH_BODYPART = 6;
|
||||
const FETCH_BODYPARTSIZE = 7;
|
||||
const FETCH_HEADERS = 8;
|
||||
const FETCH_ENVELOPE = 9;
|
||||
const FETCH_FLAGS = 10;
|
||||
const FETCH_IMAPDATE = 11;
|
||||
const FETCH_SIZE = 12;
|
||||
const FETCH_UID = 13;
|
||||
const FETCH_SEQ = 14;
|
||||
const FETCH_MODSEQ = 15;
|
||||
/* @since 2.11.0 */
|
||||
const FETCH_DOWNGRADED = 16;
|
||||
|
||||
/* Namespace constants. @deprecated */
|
||||
const NS_PERSONAL = 1;
|
||||
const NS_OTHER = 2;
|
||||
const NS_SHARED = 3;
|
||||
|
||||
/* ACL constants (RFC 4314 [2.1]). */
|
||||
const ACL_LOOKUP = 'l';
|
||||
const ACL_READ = 'r';
|
||||
const ACL_SEEN = 's';
|
||||
const ACL_WRITE = 'w';
|
||||
const ACL_INSERT = 'i';
|
||||
const ACL_POST = 'p';
|
||||
const ACL_CREATEMBOX = 'k';
|
||||
const ACL_DELETEMBOX = 'x';
|
||||
const ACL_DELETEMSGS = 't';
|
||||
const ACL_EXPUNGE = 'e';
|
||||
const ACL_ADMINISTER = 'a';
|
||||
// Old constants (RFC 2086 [3]; RFC 4314 [2.1.1])
|
||||
const ACL_CREATE = 'c';
|
||||
const ACL_DELETE = 'd';
|
||||
|
||||
/* System flags. */
|
||||
// RFC 3501 [2.3.2]
|
||||
const FLAG_ANSWERED = '\\answered';
|
||||
const FLAG_DELETED = '\\deleted';
|
||||
const FLAG_DRAFT = '\\draft';
|
||||
const FLAG_FLAGGED = '\\flagged';
|
||||
const FLAG_RECENT = '\\recent';
|
||||
const FLAG_SEEN = '\\seen';
|
||||
// RFC 3503 [3.3]
|
||||
const FLAG_MDNSENT = '$mdnsent';
|
||||
// RFC 5550 [2.8]
|
||||
const FLAG_FORWARDED = '$forwarded';
|
||||
// RFC 5788 registered keywords:
|
||||
// http://www.ietf.org/mail-archive/web/morg/current/msg00441.html
|
||||
const FLAG_JUNK = '$junk';
|
||||
const FLAG_NOTJUNK = '$notjunk';
|
||||
|
||||
/* Special-use mailbox attributes (RFC 6154 [2]). */
|
||||
const SPECIALUSE_ALL = '\\All';
|
||||
const SPECIALUSE_ARCHIVE = '\\Archive';
|
||||
const SPECIALUSE_DRAFTS = '\\Drafts';
|
||||
const SPECIALUSE_FLAGGED = '\\Flagged';
|
||||
const SPECIALUSE_JUNK = '\\Junk';
|
||||
const SPECIALUSE_SENT = '\\Sent';
|
||||
const SPECIALUSE_TRASH = '\\Trash';
|
||||
|
||||
/* Constants for sync(). */
|
||||
const SYNC_UIDVALIDITY = 0;
|
||||
const SYNC_FLAGS = 1;
|
||||
const SYNC_FLAGSUIDS = 2;
|
||||
const SYNC_NEWMSGS = 4;
|
||||
const SYNC_NEWMSGSUIDS = 8;
|
||||
const SYNC_VANISHED = 16;
|
||||
const SYNC_VANISHEDUIDS = 32;
|
||||
const SYNC_ALL = 64;
|
||||
|
||||
/**
|
||||
* Capability dependencies.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $capability_deps = array(
|
||||
// RFC 7162 [3.2]
|
||||
'QRESYNC' => array(
|
||||
// QRESYNC requires CONDSTORE, but the latter is implied and is
|
||||
// not required to be listed.
|
||||
'ENABLE'
|
||||
),
|
||||
// RFC 5182 [2.1]
|
||||
'SEARCHRES' => array(
|
||||
'ESEARCH'
|
||||
),
|
||||
// RFC 5255 [3.1]
|
||||
'LANGUAGE' => array(
|
||||
'NAMESPACE'
|
||||
),
|
||||
// RFC 5957 [1]
|
||||
'SORT=DISPLAY' => array(
|
||||
'SORT'
|
||||
)
|
||||
);
|
||||
|
||||
}
|
@ -1,189 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) 2002-2003 Richard Heyes
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* This code is based on the original code contained in the PEAR Auth_SASL
|
||||
* package (v0.5.1):
|
||||
* $Id: DigestMD5.php 294702 2010-02-07 16:03:55Z cweiske $
|
||||
*
|
||||
* That code is covered by the BSD 3-Clause license, as set forth below:
|
||||
* +-----------------------------------------------------------------------+
|
||||
* | Copyright (c) 2002-2003 Richard Heyes |
|
||||
* | All rights reserved. |
|
||||
* | |
|
||||
* | Redistribution and use in source and binary forms, with or without |
|
||||
* | modification, are permitted provided that the following conditions |
|
||||
* | are met: |
|
||||
* | |
|
||||
* | o Redistributions of source code must retain the above copyright |
|
||||
* | notice, this list of conditions and the following disclaimer. |
|
||||
* | o Redistributions in binary form must reproduce the above copyright |
|
||||
* | notice, this list of conditions and the following disclaimer in the |
|
||||
* | documentation and/or other materials provided with the distribution.|
|
||||
* | o The names of the authors may not be used to endorse or promote |
|
||||
* | products derived from this software without specific prior written |
|
||||
* | permission. |
|
||||
* | |
|
||||
* | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||
* | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
||||
* | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
||||
* | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
||||
* | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
||||
* | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
||||
* | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
||||
* | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
||||
* | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
||||
* | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
||||
* | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
||||
* +-----------------------------------------------------------------------+
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2002-2003 Richard Heyes
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides the code needed to authenticate via the DIGEST-MD5 SASL mechanism
|
||||
* (defined in RFC 2831). This method has been obsoleted by RFC 6331, but
|
||||
* still is in use on legacy servers.
|
||||
*
|
||||
* @author Richard Heyes <richard@php.net>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @copyright 2002-2003 Richard Heyes
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Auth_DigestMD5
|
||||
{
|
||||
/**
|
||||
* Digest response components.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_response;
|
||||
|
||||
/**
|
||||
* Generate the Digest-MD5 response.
|
||||
*
|
||||
* @param string $id Authentication id (username).
|
||||
* @param string $pass Password.
|
||||
* @param string $challenge The digest challenge sent by the server.
|
||||
* @param string $hostname The hostname of the machine connecting to.
|
||||
* @param string $service The service name (e.g. 'imap', 'pop3').
|
||||
*
|
||||
* @throws Horde_Imap_Client_Exception
|
||||
*/
|
||||
public function __construct($id, $pass, $challenge, $hostname, $service)
|
||||
{
|
||||
$challenge = $this->_parseChallenge($challenge);
|
||||
$cnonce = $this->_getCnonce();
|
||||
$digest_uri = sprintf('%s/%s', $service, $hostname);
|
||||
|
||||
/* Get response value. */
|
||||
$A1 = sprintf('%s:%s:%s', pack('H32', hash('md5', sprintf('%s:%s:%s', $id, $challenge['realm'], $pass))), $challenge['nonce'], $cnonce);
|
||||
$A2 = 'AUTHENTICATE:' . $digest_uri;
|
||||
$response_value = hash('md5', sprintf('%s:%s:00000001:%s:auth:%s', hash('md5', $A1), $challenge['nonce'], $cnonce, hash('md5', $A2)));
|
||||
|
||||
$this->_response = array(
|
||||
'cnonce' => '"' . $cnonce . '"',
|
||||
'digest-uri' => '"' . $digest_uri . '"',
|
||||
'maxbuf' => $challenge['maxbuf'],
|
||||
'nc' => '00000001',
|
||||
'nonce' => '"' . $challenge['nonce'] . '"',
|
||||
'qop' => 'auth',
|
||||
'response' => $response_value,
|
||||
'username' => '"' . $id . '"'
|
||||
);
|
||||
|
||||
if (strlen($challenge['realm'])) {
|
||||
$this->_response['realm'] = '"' . $challenge['realm'] . '"';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cooerce to string.
|
||||
*
|
||||
* @return string The digest response (not base64 encoded).
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$out = array();
|
||||
foreach ($this->_response as $key => $val) {
|
||||
$out[] = $key . '=' . $val;
|
||||
}
|
||||
return implode(',', $out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return specific digest response directive.
|
||||
*
|
||||
* @return mixed Requested directive, or null if it does not exist.
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return isset($this->_response[$name])
|
||||
? $this->_response[$name]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and verifies the digest challenge.
|
||||
*
|
||||
* @param string $challenge The digest challenge
|
||||
*
|
||||
* @return array The parsed challenge as an array with directives as keys.
|
||||
*
|
||||
* @throws Horde_Imap_Client_Exception
|
||||
*/
|
||||
protected function _parseChallenge($challenge)
|
||||
{
|
||||
$tokens = array(
|
||||
'maxbuf' => 65536,
|
||||
'realm' => ''
|
||||
);
|
||||
|
||||
preg_match_all('/([a-z-]+)=("[^"]+(?<!\\\)"|[^,]+)/i', $challenge, $matches, PREG_SET_ORDER);
|
||||
|
||||
foreach ($matches as $val) {
|
||||
$tokens[$val[1]] = trim($val[2], '"');
|
||||
}
|
||||
|
||||
// Required directives.
|
||||
if (!isset($tokens['nonce']) || !isset($tokens['algorithm'])) {
|
||||
throw new Horde_Imap_Client_Exception(
|
||||
Horde_Imap_Client_Translation::r("Authentication failure."),
|
||||
Horde_Imap_Client_Exception::SERVER_CONNECT
|
||||
);
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the client nonce for the response
|
||||
*
|
||||
* @return string The cnonce value.
|
||||
*/
|
||||
protected function _getCnonce()
|
||||
{
|
||||
if ((@is_readable('/dev/urandom') &&
|
||||
($fd = @fopen('/dev/urandom', 'r'))) ||
|
||||
(@is_readable('/dev/random') &&
|
||||
($fd = @fopen('/dev/random', 'r')))) {
|
||||
$str = fread($fd, 32);
|
||||
fclose($fd);
|
||||
} else {
|
||||
$str = '';
|
||||
for ($i = 0; $i < 32; ++$i) {
|
||||
$str .= chr(mt_rand(0, 255));
|
||||
}
|
||||
}
|
||||
|
||||
return base64_encode($str);
|
||||
}
|
||||
|
||||
}
|
@ -1,270 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2015-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2015-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides authentication via the SCRAM SASL mechanism (RFC 5802 [3]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2015-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.29.0
|
||||
*/
|
||||
class Horde_Imap_Client_Auth_Scram
|
||||
{
|
||||
/**
|
||||
* AuthMessage (RFC 5802 [3]).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_authmsg;
|
||||
|
||||
/**
|
||||
* Hash name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_hash;
|
||||
|
||||
/**
|
||||
* Number of Hi iterations (RFC 5802 [2]).
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $_iterations;
|
||||
|
||||
/**
|
||||
* Nonce.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_nonce;
|
||||
|
||||
/**
|
||||
* Password.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_pass;
|
||||
|
||||
/**
|
||||
* Server salt.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_salt;
|
||||
|
||||
/**
|
||||
* Calculated server signature value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_serversig;
|
||||
|
||||
/**
|
||||
* Username.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_user;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $user Username.
|
||||
* @param string $pass Password.
|
||||
* @param string $hash Hash name.
|
||||
*
|
||||
* @throws Horde_Imap_Client_Exception
|
||||
*/
|
||||
public function __construct($user, $pass, $hash = 'SHA1')
|
||||
{
|
||||
$error = false;
|
||||
|
||||
$this->_hash = $hash;
|
||||
|
||||
try {
|
||||
if (!class_exists('Horde_Stringprep') ||
|
||||
!class_exists('Horde_Crypt_Blowfish_Pbkdf2')) {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
Horde_Stringprep::autoload();
|
||||
$saslprep = new Znerol\Component\Stringprep\Profile\SASLprep();
|
||||
|
||||
$this->_user = $saslprep->apply(
|
||||
$user,
|
||||
'UTF-8',
|
||||
Znerol\Component\Stringprep\Profile::MODE_QUERY
|
||||
);
|
||||
$this->_pass = $saslprep->apply(
|
||||
$pass,
|
||||
'UTF-8',
|
||||
Znerol\Component\Stringprep\Profile::MODE_STORE
|
||||
);
|
||||
} catch (Znerol\Component\Stringprep\ProfileException $e) {
|
||||
$error = true;
|
||||
} catch (Exception $e) {
|
||||
$error = true;
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
throw new Horde_Imap_Client_Exception(
|
||||
Horde_Imap_Client_Translation::r("Authentication failure."),
|
||||
Horde_Imap_Client_Exception::LOGIN_AUTHORIZATIONFAILED
|
||||
);
|
||||
}
|
||||
|
||||
/* Generate nonce. (Done here so this can be overwritten for
|
||||
* testing purposes.) */
|
||||
$this->_nonce = strval(new Horde_Support_Randomid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the initial client message.
|
||||
*
|
||||
* @return string Initial client message.
|
||||
*/
|
||||
public function getClientFirstMessage()
|
||||
{
|
||||
/* n: client doesn't support channel binding,
|
||||
* <empty>,
|
||||
* n=<user>: SASLprepped username with "," and "=" escaped,
|
||||
* r=<nonce>: Random nonce */
|
||||
$this->_authmsg = 'n=' . str_replace(
|
||||
array(',', '='),
|
||||
array('=2C', '=3D'),
|
||||
$this->_user
|
||||
) . ',r=' . $this->_nonce;
|
||||
|
||||
return 'n,,' . $this->_authmsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the initial server message response.
|
||||
*
|
||||
* @param string $msg Initial server response.
|
||||
*
|
||||
* @return boolean False if authentication failed at this stage.
|
||||
*/
|
||||
public function parseServerFirstMessage($msg)
|
||||
{
|
||||
$i = $r = $s = false;
|
||||
|
||||
foreach (explode(',', $msg) as $val) {
|
||||
list($attr, $aval) = array_map('trim', explode('=', $val, 2));
|
||||
|
||||
switch ($attr) {
|
||||
case 'i':
|
||||
$this->_iterations = intval($aval);
|
||||
$i = true;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
/* Beginning of server-provided nonce MUST be the same as the
|
||||
* nonce we provided. */
|
||||
if (strpos($aval, $this->_nonce) !== 0) {
|
||||
return false;
|
||||
}
|
||||
$this->_nonce = $aval;
|
||||
$r = true;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
$this->_salt = base64_decode($aval);
|
||||
$s = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($i && $r && $s) {
|
||||
$this->_authmsg .= ',' . $msg;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the final client message.
|
||||
*
|
||||
* @return string Final client message.
|
||||
*/
|
||||
public function getClientFinalMessage()
|
||||
{
|
||||
$final_msg = 'c=biws,r=' . $this->_nonce;
|
||||
|
||||
/* Salted password. */
|
||||
$s_pass = strval(new Horde_Crypt_Blowfish_Pbkdf2(
|
||||
$this->_pass,
|
||||
strlen(hash($this->_hash, '', true)),
|
||||
array(
|
||||
'algo' => $this->_hash,
|
||||
'i_count' => $this->_iterations,
|
||||
'salt' => $this->_salt
|
||||
)
|
||||
));
|
||||
|
||||
/* Client key. */
|
||||
$c_key = hash_hmac($this->_hash, 'Client Key', $s_pass, true);
|
||||
|
||||
/* Stored key. */
|
||||
$s_key = hash($this->_hash, $c_key, true);
|
||||
|
||||
/* Client signature. */
|
||||
$auth_msg = $this->_authmsg . ',' . $final_msg;
|
||||
$c_sig = hash_hmac($this->_hash, $auth_msg, $s_key, true);
|
||||
|
||||
/* Proof. */
|
||||
$proof = $c_key ^ $c_sig;
|
||||
|
||||
/* Server signature. */
|
||||
$this->_serversig = hash_hmac(
|
||||
$this->_hash,
|
||||
$auth_msg,
|
||||
hash_hmac($this->_hash, 'Server Key', $s_pass, true),
|
||||
true
|
||||
);
|
||||
|
||||
/* c=biws: channel-binding ("biws" = base64('n,,')),
|
||||
* p=<proof>: base64 encoded ClientProof,
|
||||
* r=<nonce>: Nonce as returned from the server. */
|
||||
return $final_msg . ',p=' . base64_encode($proof);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the final server message response.
|
||||
*
|
||||
* @param string $msg Final server response.
|
||||
*
|
||||
* @return boolean False if authentication failed.
|
||||
*/
|
||||
public function parseServerFinalMessage($msg)
|
||||
{
|
||||
foreach (explode(',', $msg) as $val) {
|
||||
list($attr, $aval) = array_map('trim', explode('=', $val, 2));
|
||||
|
||||
switch ($attr) {
|
||||
case 'e':
|
||||
return false;
|
||||
|
||||
case 'v':
|
||||
return (base64_decode($aval) === $this->_serversig);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,105 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handle IMAP alerts sent from the server.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.24.0
|
||||
*/
|
||||
class Horde_Imap_Client_Base_Alerts
|
||||
implements SplSubject
|
||||
{
|
||||
/**
|
||||
* Alert data.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $_alert;
|
||||
|
||||
/**
|
||||
* Observers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_observers = array();
|
||||
|
||||
/**
|
||||
* Add an alert.
|
||||
*
|
||||
* @param string $alert The alert string.
|
||||
* @param string $type The alert type.
|
||||
*/
|
||||
public function add($alert, $type = null)
|
||||
{
|
||||
$this->_alert = new stdClass;
|
||||
$this->_alert->alert = $alert;
|
||||
if (!is_null($type)) {
|
||||
$this->_alert->type = $type;
|
||||
}
|
||||
|
||||
$this->notify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last alert received.
|
||||
*
|
||||
* @return object Alert information. Object with these properties:
|
||||
* <pre>
|
||||
* - alert: (string) Alert string.
|
||||
* - type: (string) [OPTIONAL] Alert type.
|
||||
* </pre>
|
||||
*/
|
||||
public function getLast()
|
||||
{
|
||||
return $this->_alert;
|
||||
}
|
||||
|
||||
/* SplSubject methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function attach(SplObserver $observer)
|
||||
{
|
||||
$this->detach($observer);
|
||||
$this->_observers[] = $observer;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function detach(SplObserver $observer)
|
||||
{
|
||||
if (($key = array_search($observer, $this->_observers, true)) !== false) {
|
||||
unset($this->_observers[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification is triggered internally whenever the object's internal
|
||||
* data storage is altered.
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function notify()
|
||||
{
|
||||
foreach ($this->_observers as $val) {
|
||||
$val->update($this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object allowing management of debugging output within a
|
||||
* Horde_Imap_Client_Base object.
|
||||
*
|
||||
* NOTE: This class is NOT intended to be accessed outside of a Base object.
|
||||
* There is NO guarantees that the API of this class will not change across
|
||||
* versions.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @internal
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Base_Debug
|
||||
{
|
||||
/** Time, in seconds, to be labeled a slow command. */
|
||||
const SLOW_CMD = 5;
|
||||
|
||||
/**
|
||||
* Is debugging active?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $debug = true;
|
||||
|
||||
/**
|
||||
* The debug stream.
|
||||
*
|
||||
* @var resource
|
||||
*/
|
||||
protected $_stream;
|
||||
|
||||
/**
|
||||
* Timestamp of last command.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $_time = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $debug The debug target.
|
||||
*/
|
||||
public function __construct($debug)
|
||||
{
|
||||
$this->_stream = is_resource($debug)
|
||||
? $debug
|
||||
: @fopen($debug, 'a');
|
||||
register_shutdown_function(array($this, 'shutdown'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown function.
|
||||
*/
|
||||
public function shutdown()
|
||||
{
|
||||
if (is_resource($this->_stream)) {
|
||||
fflush($this->_stream);
|
||||
fclose($this->_stream);
|
||||
$this->_stream = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write client output to debug log.
|
||||
*
|
||||
* @param string $msg Debug message.
|
||||
*/
|
||||
public function client($msg)
|
||||
{
|
||||
$this->_write($msg . "\n", 'C: ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Write informational message to debug log.
|
||||
*
|
||||
* @param string $msg Debug message.
|
||||
*/
|
||||
public function info($msg)
|
||||
{
|
||||
$this->_write($msg . "\n", '>> ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Write server output to debug log.
|
||||
*
|
||||
* @param string $msg Debug message.
|
||||
*/
|
||||
public function raw($msg)
|
||||
{
|
||||
$this->_write($msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write server output to debug log.
|
||||
*
|
||||
* @param string $msg Debug message.
|
||||
*/
|
||||
public function server($msg)
|
||||
{
|
||||
$this->_write($msg . "\n", 'S: ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Write debug information to the output stream.
|
||||
*
|
||||
* @param string $msg Debug data.
|
||||
*/
|
||||
protected function _write($msg, $pre = null)
|
||||
{
|
||||
if (!$this->debug || !$this->_stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_null($pre)) {
|
||||
$new_time = microtime(true);
|
||||
|
||||
if (is_null($this->_time)) {
|
||||
fwrite(
|
||||
$this->_stream,
|
||||
str_repeat('-', 30) . "\n" . '>> ' . date('r') . "\n"
|
||||
);
|
||||
} elseif (($diff = ($new_time - $this->_time)) > self::SLOW_CMD) {
|
||||
fwrite(
|
||||
$this->_stream,
|
||||
'>> Slow Command: ' . round($diff, 3) . " seconds\n"
|
||||
);
|
||||
}
|
||||
|
||||
$this->_time = $new_time;
|
||||
}
|
||||
|
||||
fwrite($this->_stream, $pre . $msg);
|
||||
}
|
||||
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class containing deprecated Horde_Imap_Client_Base methods that will be
|
||||
* removed in version 3.0.
|
||||
*
|
||||
* NOTE: This class is NOT intended to be accessed outside of a Base object.
|
||||
* There is NO guarantees that the API of this class will not change across
|
||||
* versions.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @internal
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Base_Deprecated
|
||||
{
|
||||
/**
|
||||
* Returns a unique identifier for the current mailbox status.
|
||||
*
|
||||
* @param Horde_Imap_Client_Base $base_ob The base driver object.
|
||||
* @param mixed $mailbox A mailbox. Either a
|
||||
* Horde_Imap_Client_Mailbox
|
||||
* object or a string (UTF-8).
|
||||
* @param boolean $condstore Is CONDSTORE enabled?
|
||||
* @param array $addl Additional cache info to add to
|
||||
* the cache ID string.
|
||||
*
|
||||
* @return string The cache ID string, which will change when the
|
||||
* composition of the mailbox changes. The uidvalidity
|
||||
* will always be the first element, and will be delimited
|
||||
* by the '|' character.
|
||||
*
|
||||
* @throws Horde_Imap_Client_Exception
|
||||
*/
|
||||
public static function getCacheId($base_ob, $mailbox, $condstore,
|
||||
array $addl = array())
|
||||
{
|
||||
$query = Horde_Imap_Client::STATUS_UIDVALIDITY | Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_UIDNEXT;
|
||||
|
||||
/* Use MODSEQ as cache ID if CONDSTORE extension is available. */
|
||||
if ($condstore) {
|
||||
$query |= Horde_Imap_Client::STATUS_HIGHESTMODSEQ;
|
||||
} else {
|
||||
$query |= Horde_Imap_Client::STATUS_UIDNEXT_FORCE;
|
||||
}
|
||||
|
||||
$status = $base_ob->status($mailbox, $query);
|
||||
|
||||
if (empty($status['highestmodseq'])) {
|
||||
$parts = array(
|
||||
'V' . $status['uidvalidity'],
|
||||
'U' . $status['uidnext'],
|
||||
'M' . $status['messages']
|
||||
);
|
||||
} else {
|
||||
$parts = array(
|
||||
'V' . $status['uidvalidity'],
|
||||
'H' . $status['highestmodseq']
|
||||
);
|
||||
}
|
||||
|
||||
return implode('|', array_merge($parts, $addl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a cacheID created by getCacheId().
|
||||
*
|
||||
* @param string $id The cache ID.
|
||||
*
|
||||
* @return array An array with the following information:
|
||||
* - highestmodseq: (integer)
|
||||
* - messages: (integer)
|
||||
* - uidnext: (integer)
|
||||
* - uidvalidity: (integer) Always present
|
||||
*/
|
||||
public static function parseCacheId($id)
|
||||
{
|
||||
$data = array(
|
||||
'H' => 'highestmodseq',
|
||||
'M' => 'messages',
|
||||
'U' => 'uidnext',
|
||||
'V' => 'uidvalidity'
|
||||
);
|
||||
$info = array();
|
||||
|
||||
foreach (explode('|', $id) as $part) {
|
||||
if (isset($data[$part[0]])) {
|
||||
$info[$data[$part[0]]] = intval(substr($part, 1));
|
||||
}
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
}
|
@ -1,187 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object allowing management of mailbox state within a
|
||||
* Horde_Imap_Client_Base object.
|
||||
*
|
||||
* NOTE: This class is NOT intended to be accessed outside of a Base object.
|
||||
* There is NO guarantees that the API of this class will not change across
|
||||
* versions.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @internal
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Base_Mailbox
|
||||
{
|
||||
/**
|
||||
* Mapping object.
|
||||
*
|
||||
* @var Horde_Imap_Client_Ids_Map
|
||||
*/
|
||||
public $map;
|
||||
|
||||
/**
|
||||
* Is mailbox opened?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $open;
|
||||
|
||||
/**
|
||||
* Is mailbox sync'd with remote server (via CONDSTORE/QRESYNC)?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $sync;
|
||||
|
||||
/**
|
||||
* Status information.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_status = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status information for the mailbox.
|
||||
*
|
||||
* @param integer $entry STATUS_* constant.
|
||||
*
|
||||
* @return mixed Status information.
|
||||
*/
|
||||
public function getStatus($entry)
|
||||
{
|
||||
if (isset($this->_status[$entry])) {
|
||||
return $this->_status[$entry];
|
||||
}
|
||||
|
||||
switch ($entry) {
|
||||
case Horde_Imap_Client::STATUS_FLAGS:
|
||||
case Horde_Imap_Client::STATUS_SYNCFLAGUIDS:
|
||||
case Horde_Imap_Client::STATUS_SYNCVANISHED:
|
||||
return array();
|
||||
|
||||
case Horde_Imap_Client::STATUS_FIRSTUNSEEN:
|
||||
/* If we know there are no messages in the current mailbox, we
|
||||
* know there are no unseen messages. */
|
||||
return empty($this->_status[Horde_Imap_Client::STATUS_MESSAGES])
|
||||
? false
|
||||
: null;
|
||||
|
||||
case Horde_Imap_Client::STATUS_RECENT_TOTAL:
|
||||
case Horde_Imap_Client::STATUS_SYNCMODSEQ:
|
||||
return 0;
|
||||
|
||||
case Horde_Imap_Client::STATUS_PERMFLAGS:
|
||||
/* If PERMFLAGS is not returned by server, must assume that all
|
||||
* flags can be changed permanently (RFC 3501 [6.3.1]). */
|
||||
$flags = isset($this->_status[Horde_Imap_Client::STATUS_FLAGS])
|
||||
? $this->_status[Horde_Imap_Client::STATUS_FLAGS]
|
||||
: array();
|
||||
$flags[] = "\\*";
|
||||
return $flags;
|
||||
|
||||
case Horde_Imap_Client::STATUS_UIDNOTSTICKY:
|
||||
/* In the absence of explicit uidnotsticky identification, assume
|
||||
* that UIDs are sticky. */
|
||||
return false;
|
||||
|
||||
case Horde_Imap_Client::STATUS_UNSEEN:
|
||||
/* If we know there are no messages in the current mailbox, we
|
||||
* know there are no unseen messages . */
|
||||
return empty($this->_status[Horde_Imap_Client::STATUS_MESSAGES])
|
||||
? 0
|
||||
: null;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set status information for the mailbox.
|
||||
*
|
||||
* @param integer $entry STATUS_* constant.
|
||||
* @param mixed $value Status information.
|
||||
*/
|
||||
public function setStatus($entry, $value)
|
||||
{
|
||||
switch ($entry) {
|
||||
case Horde_Imap_Client::STATUS_FIRSTUNSEEN:
|
||||
case Horde_Imap_Client::STATUS_HIGHESTMODSEQ:
|
||||
case Horde_Imap_Client::STATUS_MESSAGES:
|
||||
case Horde_Imap_Client::STATUS_UNSEEN:
|
||||
case Horde_Imap_Client::STATUS_UIDNEXT:
|
||||
case Horde_Imap_Client::STATUS_UIDVALIDITY:
|
||||
$value = intval($value);
|
||||
break;
|
||||
|
||||
case Horde_Imap_Client::STATUS_RECENT:
|
||||
/* Keep track of RECENT_TOTAL information. */
|
||||
$this->_status[Horde_Imap_Client::STATUS_RECENT_TOTAL] = isset($this->_status[Horde_Imap_Client::STATUS_RECENT_TOTAL])
|
||||
? ($this->_status[Horde_Imap_Client::STATUS_RECENT_TOTAL] + $value)
|
||||
: intval($value);
|
||||
break;
|
||||
|
||||
case Horde_Imap_Client::STATUS_SYNCMODSEQ:
|
||||
/* This is only set once per access. */
|
||||
if (isset($this->_status[$entry])) {
|
||||
return;
|
||||
}
|
||||
$value = intval($value);
|
||||
break;
|
||||
|
||||
case Horde_Imap_Client::STATUS_SYNCFLAGUIDS:
|
||||
case Horde_Imap_Client::STATUS_SYNCVANISHED:
|
||||
if (!isset($this->_status[$entry])) {
|
||||
$this->_status[$entry] = array();
|
||||
}
|
||||
$this->_status[$entry] = array_merge($this->_status[$entry], $value);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_status[$entry] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the mailbox information.
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$keep = array(
|
||||
Horde_Imap_Client::STATUS_SYNCFLAGUIDS,
|
||||
Horde_Imap_Client::STATUS_SYNCMODSEQ,
|
||||
Horde_Imap_Client::STATUS_SYNCVANISHED
|
||||
);
|
||||
|
||||
foreach (array_diff(array_keys($this->_status), $keep) as $val) {
|
||||
unset($this->_status[$val]);
|
||||
}
|
||||
|
||||
$this->map = new Horde_Imap_Client_Ids_Map();
|
||||
$this->open = $this->sync = false;
|
||||
}
|
||||
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2013-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface to allow dynamic generation of server password.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.14.0
|
||||
*/
|
||||
interface Horde_Imap_Client_Base_Password
|
||||
{
|
||||
/**
|
||||
* Return the password to use for the server connection.
|
||||
*
|
||||
* @return string The password.
|
||||
*/
|
||||
public function getPassword();
|
||||
|
||||
}
|
@ -1,263 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2005-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2005-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An interface to cache data retrieved from the IMAP server.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2005-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Cache
|
||||
{
|
||||
/**
|
||||
* Base client object.
|
||||
*
|
||||
* @var Horde_Imap_Client_Base
|
||||
*/
|
||||
protected $_baseob;
|
||||
|
||||
/**
|
||||
* Storage backend.
|
||||
*
|
||||
* @var Horde_Imap_Client_Cache_Backend
|
||||
*/
|
||||
protected $_backend;
|
||||
|
||||
/**
|
||||
* Debug output.
|
||||
*
|
||||
* @var Horde_Imap_Client_Base_Debug
|
||||
*/
|
||||
protected $_debug = false;
|
||||
|
||||
/**
|
||||
* The configuration params.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_params = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $params Configuration parameters:
|
||||
* <pre>
|
||||
* - REQUIRED Parameters:
|
||||
* - backend: (Horde_Imap_Client_Cache_Backend) The cache backend.
|
||||
* - baseob: (Horde_Imap_Client_Base) The base client object.
|
||||
*
|
||||
* - Optional Parameters:
|
||||
* - debug: (Horde_Imap_Client_Base_Debug) Debug object.
|
||||
* DEFAULT: No debug output
|
||||
* </pre>
|
||||
*/
|
||||
public function __construct(array $params = array())
|
||||
{
|
||||
$this->_backend = $params['backend'];
|
||||
$this->_baseob = $params['baseob'];
|
||||
|
||||
$this->_backend->setParams(array(
|
||||
'hostspec' => $this->_baseob->getParam('hostspec'),
|
||||
'port' => $this->_baseob->getParam('port'),
|
||||
'username' => $this->_baseob->getParam('username')
|
||||
));
|
||||
|
||||
if (isset($params['debug']) &&
|
||||
($params['debug'] instanceof Horde_Imap_Client_Base_Debug)) {
|
||||
$this->_debug = $params['debug'];
|
||||
$this->_debug->info(sprintf(
|
||||
'CACHE: Using the %s storage driver.',
|
||||
get_class($this->_backend)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information from the cache.
|
||||
*
|
||||
* @param string $mailbox An IMAP mailbox string.
|
||||
* @param array $uids The list of message UIDs to retrieve
|
||||
* information for. If empty, returns the list
|
||||
* of cached UIDs.
|
||||
* @param array $fields An array of fields to retrieve. If empty,
|
||||
* returns all cached fields.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
*
|
||||
* @return array An array of arrays with the UID of the message as the
|
||||
* key (if found) and the fields as values (will be
|
||||
* undefined if not found). If $uids is empty, returns the
|
||||
* full (unsorted) list of cached UIDs.
|
||||
*/
|
||||
public function get($mailbox, array $uids = array(), $fields = array(),
|
||||
$uidvalid = null)
|
||||
{
|
||||
$mailbox = strval($mailbox);
|
||||
|
||||
if (empty($uids)) {
|
||||
$ret = $this->_backend->getCachedUids($mailbox, $uidvalid);
|
||||
} else {
|
||||
$ret = $this->_backend->get($mailbox, $uids, $fields, $uidvalid);
|
||||
|
||||
if ($this->_debug && !empty($ret)) {
|
||||
$this->_debug->info(sprintf(
|
||||
'CACHE: Retrieved messages (%s [%s; %s])',
|
||||
empty($fields) ? 'ALL' : implode(',', $fields),
|
||||
$mailbox,
|
||||
$this->_baseob->getIdsOb(array_keys($ret))->tostring_sort
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store information in cache.
|
||||
*
|
||||
* @param string $mailbox An IMAP mailbox string.
|
||||
* @param array $data The list of data to save. The keys are the
|
||||
* UIDs, the values are an array of information
|
||||
* to save. If empty, do a check to make sure
|
||||
* the uidvalidity is still valid.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
*/
|
||||
public function set($mailbox, $data, $uidvalid)
|
||||
{
|
||||
$mailbox = strval($mailbox);
|
||||
|
||||
if (empty($data)) {
|
||||
$this->_backend->getMetaData($mailbox, $uidvalid, array('uidvalid'));
|
||||
} else {
|
||||
$this->_backend->set($mailbox, $data, $uidvalid);
|
||||
|
||||
if ($this->_debug) {
|
||||
$this->_debug->info(sprintf(
|
||||
'CACHE: Stored messages [%s; %s]',
|
||||
$mailbox,
|
||||
$this->_baseob->getIdsOb(array_keys($data))->tostring_sort
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get metadata information for a mailbox.
|
||||
*
|
||||
* @param string $mailbox An IMAP mailbox string.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
* @param array $entries An array of entries to return. If empty,
|
||||
* returns all metadata.
|
||||
*
|
||||
* @return array The requested metadata. Requested entries that do not
|
||||
* exist will be undefined. The following entries are
|
||||
* defaults and always present:
|
||||
* - uidvalid: (integer) The UIDVALIDITY of the mailbox.
|
||||
*/
|
||||
public function getMetaData($mailbox, $uidvalid = null,
|
||||
array $entries = array())
|
||||
{
|
||||
return $this->_backend->getMetaData(strval($mailbox), $uidvalid, $entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set metadata information for a mailbox.
|
||||
*
|
||||
* @param string $mailbox An IMAP mailbox string.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
* @param array $data The list of data to save. The keys are the
|
||||
* metadata IDs, the values are the associated
|
||||
* data. The following labels are reserved:
|
||||
* 'uidvalid'.
|
||||
*/
|
||||
public function setMetaData($mailbox, $uidvalid, array $data = array())
|
||||
{
|
||||
unset($data['uidvalid']);
|
||||
|
||||
if (!empty($data)) {
|
||||
if (!empty($uidvalid)) {
|
||||
$data['uidvalid'] = $uidvalid;
|
||||
}
|
||||
$mailbox = strval($mailbox);
|
||||
|
||||
$this->_backend->setMetaData($mailbox, $data);
|
||||
|
||||
if ($this->_debug) {
|
||||
$this->_debug->info(sprintf(
|
||||
'CACHE: Stored metadata (%s [%s])',
|
||||
implode(',', array_keys($data)),
|
||||
$mailbox
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete messages in the cache.
|
||||
*
|
||||
* @param string $mailbox An IMAP mailbox string.
|
||||
* @param array $uids The list of message UIDs to delete.
|
||||
*/
|
||||
public function deleteMsgs($mailbox, $uids)
|
||||
{
|
||||
if (empty($uids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mailbox = strval($mailbox);
|
||||
|
||||
$this->_backend->deleteMsgs($mailbox, $uids);
|
||||
|
||||
if ($this->_debug) {
|
||||
$this->_debug->info(sprintf(
|
||||
'CACHE: Deleted messages [%s; %s]',
|
||||
$mailbox,
|
||||
$this->_baseob->getIdsOb($uids)->tostring_sort
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a mailbox from the cache.
|
||||
*
|
||||
* @param string $mbox The mailbox to delete.
|
||||
*/
|
||||
public function deleteMailbox($mbox)
|
||||
{
|
||||
$mbox = strval($mbox);
|
||||
$this->_backend->deleteMailbox($mbox);
|
||||
|
||||
if ($this->_debug) {
|
||||
$this->_debug->info(sprintf(
|
||||
'CACHE: Deleted mailbox [%s]',
|
||||
$mbox
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cache.
|
||||
*
|
||||
* @since 2.9.0
|
||||
*
|
||||
* @param integer $lifetime Only delete entries older than this (in
|
||||
* seconds). If null, deletes all entries.
|
||||
*/
|
||||
public function clear($lifetime = null)
|
||||
{
|
||||
$this->_backend->clear($lifetime);
|
||||
}
|
||||
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2013-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* The abstract backend class for storing IMAP cached data.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
abstract class Horde_Imap_Client_Cache_Backend implements Serializable
|
||||
{
|
||||
/**
|
||||
* Configuration paramters.
|
||||
* Values set by the base Cache object: hostspec, port, username
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_params = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $params Configuration parameters.
|
||||
*/
|
||||
public function __construct(array $params = array())
|
||||
{
|
||||
$this->setParams($params);
|
||||
$this->_initOb();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization tasks.
|
||||
*/
|
||||
protected function _initOb()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Add configuration parameters.
|
||||
*
|
||||
* @param array $params Configuration parameters.
|
||||
*/
|
||||
public function setParams(array $params = array())
|
||||
{
|
||||
$this->_params = array_merge($this->_params, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information from the cache for a set of UIDs.
|
||||
*
|
||||
* @param string $mailbox An IMAP mailbox string.
|
||||
* @param array $uids The list of message UIDs to retrieve
|
||||
* information for.
|
||||
* @param array $fields An array of fields to retrieve. If empty,
|
||||
* returns all cached fields.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
*
|
||||
* @return array An array of arrays with the UID of the message as the
|
||||
* key (if found) and the fields as values (will be
|
||||
* undefined if not found).
|
||||
*/
|
||||
abstract public function get($mailbox, $uids, $fields, $uidvalid);
|
||||
|
||||
/**
|
||||
* Get the list of cached UIDs.
|
||||
*
|
||||
* @param string $mailbox An IMAP mailbox string.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
*
|
||||
* @return array The (unsorted) list of cached UIDs.
|
||||
*/
|
||||
abstract public function getCachedUids($mailbox, $uidvalid);
|
||||
|
||||
/**
|
||||
* Store data in cache.
|
||||
*
|
||||
* @param string $mailbox An IMAP mailbox string.
|
||||
* @param array $data The list of data to save. The keys are the
|
||||
* UIDs, the values are an array of information
|
||||
* to save.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
*/
|
||||
abstract public function set($mailbox, $data, $uidvalid);
|
||||
|
||||
/**
|
||||
* Get metadata information for a mailbox.
|
||||
*
|
||||
* @param string $mailbox An IMAP mailbox string.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
* @param array $entries An array of entries to return. If empty,
|
||||
* returns all metadata.
|
||||
*
|
||||
* @return array The requested metadata. Requested entries that do not
|
||||
* exist will be undefined. The following entries are
|
||||
* defaults and always present:
|
||||
* - uidvalid: (integer) The UIDVALIDITY of the mailbox.
|
||||
*/
|
||||
abstract public function getMetaData($mailbox, $uidvalid, $entries);
|
||||
|
||||
/**
|
||||
* Set metadata information for a mailbox.
|
||||
*
|
||||
* @param string $mailbox An IMAP mailbox string.
|
||||
* @param array $data The list of data to save. The keys are the
|
||||
* metadata IDs, the values are the associated
|
||||
* data. (If present, uidvalidity appears as
|
||||
* the 'uidvalid' key in $data.)
|
||||
*/
|
||||
abstract public function setMetaData($mailbox, $data);
|
||||
|
||||
/**
|
||||
* Delete messages in the cache.
|
||||
*
|
||||
* @param string $mailbox An IMAP mailbox string.
|
||||
* @param array $uids The list of message UIDs to delete.
|
||||
*/
|
||||
abstract public function deleteMsgs($mailbox, $uids);
|
||||
|
||||
/**
|
||||
* Delete a mailbox from the cache.
|
||||
*
|
||||
* @param string $mailbox The mailbox to delete.
|
||||
*/
|
||||
abstract public function deleteMailbox($mailbox);
|
||||
|
||||
/**
|
||||
* Clear the cache.
|
||||
*
|
||||
* @param integer $lifetime Only delete entries older than this (in
|
||||
* seconds). If null, deletes all entries.
|
||||
*/
|
||||
abstract public function clear($lifetime);
|
||||
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function unserialize($data)
|
||||
{
|
||||
$this->__unserialize(unserialize($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return $this->_params;
|
||||
}
|
||||
|
||||
public function __unserialize(array $data)
|
||||
{
|
||||
$this->_params = $data;
|
||||
}
|
||||
|
||||
}
|
@ -1,514 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2005-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2005-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Horde_Cache implementation for caching IMAP/POP data.
|
||||
* Requires the Horde_Cache package.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2005-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Cache_Backend_Cache
|
||||
extends Horde_Imap_Client_Cache_Backend
|
||||
{
|
||||
/** Cache structure version. */
|
||||
const VERSION = 3;
|
||||
|
||||
/**
|
||||
* The cache object.
|
||||
*
|
||||
* @var Horde_Cache
|
||||
*/
|
||||
protected $_cache;
|
||||
|
||||
/**
|
||||
* The working data for the current pageload. All changes take place to
|
||||
* this data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_data = array();
|
||||
|
||||
/**
|
||||
* The list of cache slices loaded.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_loaded = array();
|
||||
|
||||
/**
|
||||
* The mapping of UIDs to slices.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_slicemap = array();
|
||||
|
||||
/**
|
||||
* The list of items to update:
|
||||
* - add: (array) List of IDs that were added.
|
||||
* - slice: (array) List of slices that were modified.
|
||||
* - slicemap: (boolean) Was slicemap info changed?
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_update = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $params Configuration parameters:
|
||||
* <pre>
|
||||
* - REQUIRED Parameters:
|
||||
* - cacheob: (Horde_Cache) The cache object to use.
|
||||
*
|
||||
* - Optional Parameters:
|
||||
* - lifetime: (integer) The lifetime of the cache data (in seconds).
|
||||
* DEFAULT: 1 week (604800 seconds)
|
||||
* - slicesize: (integer) The slicesize to use.
|
||||
* DEFAULT: 50
|
||||
* </pre>
|
||||
*/
|
||||
public function __construct(array $params = array())
|
||||
{
|
||||
// Default parameters.
|
||||
$params = array_merge(array(
|
||||
'lifetime' => 604800,
|
||||
'slicesize' => 50
|
||||
), array_filter($params));
|
||||
|
||||
if (!isset($params['cacheob'])) {
|
||||
throw new InvalidArgumentException('Missing cacheob parameter.');
|
||||
}
|
||||
|
||||
foreach (array('lifetime', 'slicesize') as $val) {
|
||||
$params[$val] = intval($params[$val]);
|
||||
}
|
||||
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization tasks.
|
||||
*/
|
||||
protected function _initOb()
|
||||
{
|
||||
$this->_cache = $this->_params['cacheob'];
|
||||
register_shutdown_function(array($this, 'save'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the cache.
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$lifetime = $this->_params['lifetime'];
|
||||
|
||||
foreach ($this->_update as $mbox => $val) {
|
||||
$s = &$this->_slicemap[$mbox];
|
||||
|
||||
try {
|
||||
if (!empty($val['add'])) {
|
||||
if ($s['c'] <= $this->_params['slicesize']) {
|
||||
$val['slice'][] = $s['i'];
|
||||
$this->_loadSlice($mbox, $s['i']);
|
||||
}
|
||||
$val['slicemap'] = true;
|
||||
|
||||
foreach (array_keys(array_flip($val['add'])) as $uid) {
|
||||
if ($s['c']++ > $this->_params['slicesize']) {
|
||||
$s['c'] = 0;
|
||||
$val['slice'][] = ++$s['i'];
|
||||
$this->_loadSlice($mbox, $s['i']);
|
||||
}
|
||||
$s['s'][$uid] = $s['i'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($val['slice'])) {
|
||||
$d = &$this->_data[$mbox];
|
||||
$val['slicemap'] = true;
|
||||
|
||||
foreach (array_keys(array_flip($val['slice'])) as $slice) {
|
||||
$data = array();
|
||||
foreach (moodle_array_keys_filter($s['s'], $slice) as $uid) {
|
||||
$data[$uid] = is_array($d[$uid])
|
||||
? serialize($d[$uid])
|
||||
: $d[$uid];
|
||||
}
|
||||
$this->_cache->set($this->_getCid($mbox, $slice), serialize($data), $lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($val['slicemap'])) {
|
||||
$this->_cache->set($this->_getCid($mbox, 'slicemap'), serialize($s), $lifetime);
|
||||
}
|
||||
} catch (Horde_Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
$this->_update = array();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function get($mailbox, $uids, $fields, $uidvalid)
|
||||
{
|
||||
$ret = array();
|
||||
$this->_loadUids($mailbox, $uids, $uidvalid);
|
||||
|
||||
if (empty($this->_data[$mailbox])) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if (!empty($fields)) {
|
||||
$fields = array_flip($fields);
|
||||
}
|
||||
$ptr = &$this->_data[$mailbox];
|
||||
|
||||
foreach (array_intersect($uids, array_keys($ptr)) as $val) {
|
||||
if (is_string($ptr[$val])) {
|
||||
try {
|
||||
$ptr[$val] = @unserialize($ptr[$val]);
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
|
||||
$ret[$val] = (empty($fields) || empty($ptr[$val]))
|
||||
? $ptr[$val]
|
||||
: array_intersect_key($ptr[$val], $fields);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getCachedUids($mailbox, $uidvalid)
|
||||
{
|
||||
$this->_loadSliceMap($mailbox, $uidvalid);
|
||||
return array_unique(array_merge(
|
||||
array_keys($this->_slicemap[$mailbox]['s']),
|
||||
(isset($this->_update[$mailbox]) ? $this->_update[$mailbox]['add'] : array())
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function set($mailbox, $data, $uidvalid)
|
||||
{
|
||||
$update = array_keys($data);
|
||||
|
||||
try {
|
||||
$this->_loadUids($mailbox, $update, $uidvalid);
|
||||
} catch (Horde_Imap_Client_Exception $e) {
|
||||
// Ignore invalidity - just start building the new cache
|
||||
}
|
||||
|
||||
$d = &$this->_data[$mailbox];
|
||||
$s = &$this->_slicemap[$mailbox]['s'];
|
||||
$add = $updated = array();
|
||||
|
||||
foreach ($data as $k => $v) {
|
||||
if (isset($d[$k])) {
|
||||
if (is_string($d[$k])) {
|
||||
try {
|
||||
$d[$k] = @unserialize($d[$k]);
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
$d[$k] = is_array($d[$k])
|
||||
? array_merge($d[$k], $v)
|
||||
: $v;
|
||||
if (isset($s[$k])) {
|
||||
$updated[$s[$k]] = true;
|
||||
}
|
||||
} else {
|
||||
$d[$k] = $v;
|
||||
$add[] = $k;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_toUpdate($mailbox, 'add', $add);
|
||||
$this->_toUpdate($mailbox, 'slice', array_keys($updated));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getMetaData($mailbox, $uidvalid, $entries)
|
||||
{
|
||||
$this->_loadSliceMap($mailbox, $uidvalid);
|
||||
|
||||
return empty($entries)
|
||||
? $this->_slicemap[$mailbox]['d']
|
||||
: array_intersect_key($this->_slicemap[$mailbox]['d'], array_flip($entries));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function setMetaData($mailbox, $data)
|
||||
{
|
||||
$this->_loadSliceMap($mailbox, isset($data['uidvalid']) ? $data['uidvalid'] : null);
|
||||
$this->_slicemap[$mailbox]['d'] = array_merge($this->_slicemap[$mailbox]['d'], $data);
|
||||
$this->_toUpdate($mailbox, 'slicemap', true);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function deleteMsgs($mailbox, $uids)
|
||||
{
|
||||
if (empty($uids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_loadSliceMap($mailbox);
|
||||
|
||||
$slicemap = &$this->_slicemap[$mailbox];
|
||||
$deleted = array_intersect_key($slicemap['s'], array_flip($uids));
|
||||
|
||||
if (isset($this->_update[$mailbox])) {
|
||||
$this->_update[$mailbox]['add'] = array_diff(
|
||||
$this->_update[$mailbox]['add'],
|
||||
$uids
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($deleted)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_loadUids($mailbox, array_keys($deleted));
|
||||
$d = &$this->_data[$mailbox];
|
||||
|
||||
foreach (array_keys($deleted) as $id) {
|
||||
unset($d[$id], $slicemap['s'][$id]);
|
||||
}
|
||||
|
||||
foreach (array_unique($deleted) as $slice) {
|
||||
/* Get rid of slice if less than 10% of capacity. */
|
||||
if (($slice != $slicemap['i']) &&
|
||||
($slice_uids = moodle_array_keys_filter($slicemap['s'], $slice)) &&
|
||||
($this->_params['slicesize'] * 0.1) > count($slice_uids)) {
|
||||
$this->_toUpdate($mailbox, 'add', $slice_uids);
|
||||
$this->_cache->expire($this->_getCid($mailbox, $slice));
|
||||
foreach ($slice_uids as $val) {
|
||||
unset($slicemap['s'][$val]);
|
||||
}
|
||||
} else {
|
||||
$this->_toUpdate($mailbox, 'slice', array($slice));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function deleteMailbox($mailbox)
|
||||
{
|
||||
$this->_loadSliceMap($mailbox);
|
||||
$this->_deleteMailbox($mailbox);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function clear($lifetime)
|
||||
{
|
||||
$this->_cache->clear();
|
||||
$this->_data = $this->_loaded = $this->_slicemap = $this->_update = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the unique ID used to store the data in the cache.
|
||||
*
|
||||
* @param string $mailbox The mailbox to cache.
|
||||
* @param string $slice The cache slice.
|
||||
*
|
||||
* @return string The cache ID.
|
||||
*/
|
||||
protected function _getCid($mailbox, $slice)
|
||||
{
|
||||
return implode('|', array(
|
||||
'horde_imap_client',
|
||||
$this->_params['username'],
|
||||
$mailbox,
|
||||
$this->_params['hostspec'],
|
||||
$this->_params['port'],
|
||||
$slice,
|
||||
self::VERSION
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a mailbox from the cache.
|
||||
*
|
||||
* @param string $mbox The mailbox to delete.
|
||||
*/
|
||||
protected function _deleteMailbox($mbox)
|
||||
{
|
||||
foreach (array_merge(array_keys(array_flip($this->_slicemap[$mbox]['s'])), array('slicemap')) as $slice) {
|
||||
$cid = $this->_getCid($mbox, $slice);
|
||||
$this->_cache->expire($cid);
|
||||
unset($this->_loaded[$cid]);
|
||||
}
|
||||
|
||||
unset(
|
||||
$this->_data[$mbox],
|
||||
$this->_slicemap[$mbox],
|
||||
$this->_update[$mbox]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load UIDs by regenerating from the cache.
|
||||
*
|
||||
* @param string $mailbox The mailbox to load.
|
||||
* @param array $uids The UIDs to load.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
*/
|
||||
protected function _loadUids($mailbox, $uids, $uidvalid = null)
|
||||
{
|
||||
if (!isset($this->_data[$mailbox])) {
|
||||
$this->_data[$mailbox] = array();
|
||||
}
|
||||
|
||||
$this->_loadSliceMap($mailbox, $uidvalid);
|
||||
|
||||
if (!empty($uids)) {
|
||||
foreach (array_unique(array_intersect_key($this->_slicemap[$mailbox]['s'], array_flip($uids))) as $slice) {
|
||||
$this->_loadSlice($mailbox, $slice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load UIDs from a cache slice.
|
||||
*
|
||||
* @param string $mailbox The mailbox to load.
|
||||
* @param integer $slice The slice to load.
|
||||
*/
|
||||
protected function _loadSlice($mailbox, $slice)
|
||||
{
|
||||
$cache_id = $this->_getCid($mailbox, $slice);
|
||||
|
||||
if (!empty($this->_loaded[$cache_id])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (($data = $this->_cache->get($cache_id, 0)) !== false) {
|
||||
try {
|
||||
$data = @unserialize($data);
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
|
||||
if (($data !== false) && is_array($data)) {
|
||||
$this->_data[$mailbox] += $data;
|
||||
$this->_loaded[$cache_id] = true;
|
||||
} else {
|
||||
$ptr = &$this->_slicemap[$mailbox];
|
||||
|
||||
// Slice data is corrupt; remove from slicemap.
|
||||
foreach (moodle_array_keys_filter($ptr['s'], $slice) as $val) {
|
||||
unset($ptr['s'][$val]);
|
||||
}
|
||||
|
||||
if ($slice == $ptr['i']) {
|
||||
$ptr['c'] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the slicemap for a given mailbox. The slicemap contains
|
||||
* the uidvalidity information, the UIDs->slice lookup table, and any
|
||||
* metadata that needs to be saved for the mailbox.
|
||||
*
|
||||
* @param string $mailbox The mailbox.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
*/
|
||||
protected function _loadSliceMap($mailbox, $uidvalid = null)
|
||||
{
|
||||
if (!isset($this->_slicemap[$mailbox]) &&
|
||||
(($data = $this->_cache->get($this->_getCid($mailbox, 'slicemap'), 0)) !== false)) {
|
||||
try {
|
||||
if (($slice = @unserialize($data)) &&
|
||||
is_array($slice)) {
|
||||
$this->_slicemap[$mailbox] = $slice;
|
||||
}
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
|
||||
if (isset($this->_slicemap[$mailbox])) {
|
||||
$ptr = &$this->_slicemap[$mailbox];
|
||||
if (is_null($ptr['d']['uidvalid'])) {
|
||||
$ptr['d']['uidvalid'] = $uidvalid;
|
||||
return;
|
||||
} elseif (!is_null($uidvalid) &&
|
||||
($ptr['d']['uidvalid'] != $uidvalid)) {
|
||||
$this->_deleteMailbox($mailbox);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_slicemap[$mailbox] = array(
|
||||
// Tracking count for purposes of determining slices
|
||||
'c' => 0,
|
||||
// Metadata storage
|
||||
// By default includes UIDVALIDITY of mailbox.
|
||||
'd' => array('uidvalid' => $uidvalid),
|
||||
// The ID of the last slice.
|
||||
'i' => 0,
|
||||
// The slice list.
|
||||
's' => array()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add update entry for a mailbox.
|
||||
*
|
||||
* @param string $mailbox The mailbox.
|
||||
* @param string $type 'add', 'slice', or 'slicemap'.
|
||||
* @param mixed $data The data to update.
|
||||
*/
|
||||
protected function _toUpdate($mailbox, $type, $data)
|
||||
{
|
||||
if (!isset($this->_update[$mailbox])) {
|
||||
$this->_update[$mailbox] = array(
|
||||
'add' => array(),
|
||||
'slice' => array()
|
||||
);
|
||||
}
|
||||
|
||||
$this->_update[$mailbox][$type] = ($type == 'slicemap')
|
||||
? $data
|
||||
: array_merge($this->_update[$mailbox][$type], $data);
|
||||
}
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return $this->__serialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
$this->save();
|
||||
return parent::__serialize();
|
||||
}
|
||||
|
||||
}
|
@ -1,407 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2013-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* A SQL database implementation for caching IMAP/POP data.
|
||||
* Requires the Horde_Db package.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Cache_Backend_Db
|
||||
extends Horde_Imap_Client_Cache_Backend
|
||||
{
|
||||
/** SQL table names. */
|
||||
const BASE_TABLE = 'horde_imap_client_data';
|
||||
const MD_TABLE = 'horde_imap_client_metadata';
|
||||
const MSG_TABLE = 'horde_imap_client_message';
|
||||
|
||||
/**
|
||||
* Handle for the database connection.
|
||||
*
|
||||
* @var Horde_Db_Adapter
|
||||
*/
|
||||
protected $_db;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $params Configuration parameters:
|
||||
* <pre>
|
||||
* - REQUIRED Parameters:
|
||||
* - db: (Horde_Db_Adapter) DB object.
|
||||
* </pre>
|
||||
*/
|
||||
public function __construct(array $params = array())
|
||||
{
|
||||
if (!isset($params['db'])) {
|
||||
throw new InvalidArgumentException('Missing db parameter.');
|
||||
}
|
||||
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
protected function _initOb()
|
||||
{
|
||||
$this->_db = $this->_params['db'];
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function get($mailbox, $uids, $fields, $uidvalid)
|
||||
{
|
||||
$this->getMetaData($mailbox, $uidvalid, array('uidvalid'));
|
||||
|
||||
$query = $this->_baseSql($mailbox, self::MSG_TABLE);
|
||||
$query[0] = 'SELECT t.data, t.msguid ' . $query[0];
|
||||
|
||||
$uid_query = array();
|
||||
foreach ($uids as $val) {
|
||||
$uid_query[] = 't.msguid = ?';
|
||||
$query[1][] = strval($val);
|
||||
}
|
||||
$query[0] .= ' AND (' . implode(' OR ', $uid_query) . ')';
|
||||
|
||||
$compress = new Horde_Compress_Fast();
|
||||
$out = array();
|
||||
|
||||
try {
|
||||
$columns = $this->_db->columns(self::MSG_TABLE);
|
||||
$res = $this->_db->select($query[0], $query[1]);
|
||||
|
||||
foreach ($res as $row) {
|
||||
try {
|
||||
$out[$row['msguid']] = @unserialize($compress->decompress(
|
||||
$columns['data']->binaryToString($row['data'])
|
||||
));
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
} catch (Horde_Db_Exception $e) {}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getCachedUids($mailbox, $uidvalid)
|
||||
{
|
||||
$this->getMetaData($mailbox, $uidvalid, array('uidvalid'));
|
||||
|
||||
$query = $this->_baseSql($mailbox, self::MSG_TABLE);
|
||||
$query[0] = 'SELECT DISTINCT t.msguid ' . $query[0];
|
||||
|
||||
try {
|
||||
return $this->_db->selectValues($query[0], $query[1]);
|
||||
} catch (Horde_Db_Exception $e) {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function set($mailbox, $data, $uidvalid)
|
||||
{
|
||||
if ($uid = $this->_getUid($mailbox)) {
|
||||
$res = $this->get($mailbox, array_keys($data), array(), $uidvalid);
|
||||
} else {
|
||||
$res = array();
|
||||
$uid = $this->_createUid($mailbox);
|
||||
}
|
||||
|
||||
$compress = new Horde_Compress_Fast();
|
||||
|
||||
foreach ($data as $key => $val) {
|
||||
if (isset($res[$key])) {
|
||||
try {
|
||||
/* Update */
|
||||
$this->_db->updateBlob(
|
||||
self::MSG_TABLE,
|
||||
array('data' => new Horde_Db_Value_Binary($compress->compress(serialize(array_merge($res[$key], $val))))),
|
||||
array(
|
||||
'messageid = ? AND msguid = ?',
|
||||
array($uid, strval($key))
|
||||
)
|
||||
);
|
||||
} catch (Horde_Db_Exception $e) {}
|
||||
} else {
|
||||
/* Insert */
|
||||
try {
|
||||
$this->_db->insertBlob(
|
||||
self::MSG_TABLE,
|
||||
array(
|
||||
'data' => new Horde_Db_Value_Binary($compress->compress(serialize($val))),
|
||||
'msguid' => strval($key),
|
||||
'messageid' => $uid
|
||||
)
|
||||
);
|
||||
} catch (Horde_Db_Exception $e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update modified time. */
|
||||
try {
|
||||
$this->_db->update(
|
||||
sprintf(
|
||||
'UPDATE %s SET modified = ? WHERE messageid = ?',
|
||||
self::BASE_TABLE
|
||||
),
|
||||
array(time(), $uid)
|
||||
);
|
||||
} catch (Horde_Db_Exception $e) {}
|
||||
|
||||
/* Update uidvalidity. */
|
||||
$this->setMetaData($mailbox, array('uidvalid' => $uidvalid));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getMetaData($mailbox, $uidvalid, $entries)
|
||||
{
|
||||
$query = $this->_baseSql($mailbox, self::MD_TABLE);
|
||||
$query[0] = 'SELECT t.field, t.data ' . $query[0];
|
||||
|
||||
if (!empty($entries)) {
|
||||
$entries[] = 'uidvalid';
|
||||
$entry_query = array();
|
||||
|
||||
foreach (array_unique($entries) as $val) {
|
||||
$entry_query[] = 't.field = ?';
|
||||
$query[1][] = $val;
|
||||
}
|
||||
$query[0] .= ' AND (' . implode(' OR ', $entry_query) . ')';
|
||||
}
|
||||
|
||||
try {
|
||||
if ($res = $this->_db->selectAssoc($query[0], $query[1])) {
|
||||
$columns = $this->_db->columns(self::MD_TABLE);
|
||||
foreach ($res as $key => $val) {
|
||||
switch ($key) {
|
||||
case 'uidvalid':
|
||||
$res[$key] = $columns['data']->binaryToString($val);
|
||||
break;
|
||||
|
||||
default:
|
||||
try {
|
||||
$res[$key] = @unserialize(
|
||||
$columns['data']->binaryToString($val)
|
||||
);
|
||||
} catch (Exception $e) {}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null($uidvalid) ||
|
||||
!isset($res['uidvalid']) ||
|
||||
($res['uidvalid'] == $uidvalid)) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
$this->deleteMailbox($mailbox);
|
||||
}
|
||||
} catch (Horde_Db_Exception $e) {}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function setMetaData($mailbox, $data)
|
||||
{
|
||||
if (!($uid = $this->_getUid($mailbox))) {
|
||||
$uid = $this->_createUid($mailbox);
|
||||
}
|
||||
|
||||
$query = sprintf('SELECT field FROM %s where messageid = ?', self::MD_TABLE);
|
||||
$values = array($uid);
|
||||
|
||||
try {
|
||||
$fields = $this->_db->selectValues($query, $values);
|
||||
} catch (Horde_Db_Exception $e) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($data as $key => $val) {
|
||||
$val = new Horde_Db_Value_Binary(($key == 'uidvalid') ? $val : serialize($val));
|
||||
|
||||
if (in_array($key, $fields)) {
|
||||
/* Update */
|
||||
try {
|
||||
$this->_db->updateBlob(
|
||||
self::MD_TABLE,
|
||||
array('data' => $val),
|
||||
array('field = ? AND messageid = ?', array($key, $uid))
|
||||
);
|
||||
} catch (Horde_Db_Exception $e) {}
|
||||
} else {
|
||||
/* Insert */
|
||||
try {
|
||||
$this->_db->insertBlob(
|
||||
self::MD_TABLE,
|
||||
array('data' => $val, 'field' => $key, 'messageid' => $uid)
|
||||
);
|
||||
} catch (Horde_Db_Exception $e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function deleteMsgs($mailbox, $uids)
|
||||
{
|
||||
if (empty($uids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$query = $this->_baseSql($mailbox);
|
||||
$query[0] = sprintf(
|
||||
'DELETE FROM %s WHERE messageid IN (SELECT messageid ' . $query[0] . ')',
|
||||
self::MSG_TABLE
|
||||
);
|
||||
|
||||
$uid_query = array();
|
||||
foreach ($uids as $val) {
|
||||
$uid_query[] = 'msguid = ?';
|
||||
$query[1][] = strval($val);
|
||||
}
|
||||
$query[0] .= ' AND (' . implode(' OR ', $uid_query) . ')';
|
||||
|
||||
try {
|
||||
$this->_db->delete($query[0], $query[1]);
|
||||
} catch (Horde_Db_Exception $e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function deleteMailbox($mailbox)
|
||||
{
|
||||
if (is_null($uid = $this->_getUid($mailbox))) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (array(self::BASE_TABLE, self::MD_TABLE, self::MSG_TABLE) as $val) {
|
||||
try {
|
||||
$this->_db->delete(
|
||||
sprintf('DELETE FROM %s WHERE messageid = ?', $val),
|
||||
array($uid)
|
||||
);
|
||||
} catch (Horde_Db_Exception $e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function clear($lifetime)
|
||||
{
|
||||
if (is_null($lifetime)) {
|
||||
try {
|
||||
$this->_db->delete(sprintf('DELETE FROM %s', self::BASE_TABLE));
|
||||
$this->_db->delete(sprintf('DELETE FROM %s', self::MD_TABLE));
|
||||
$this->_db->delete(sprintf('DELETE FROM %s', self::MSG_TABLE));
|
||||
} catch (Horde_Db_Exception $e) {}
|
||||
return;
|
||||
}
|
||||
|
||||
$purge = time() - $lifetime;
|
||||
$sql = 'DELETE FROM %s WHERE messageid IN (SELECT messageid FROM %s WHERE modified < ?)';
|
||||
|
||||
foreach (array(self::MD_TABLE, self::MSG_TABLE) as $val) {
|
||||
try {
|
||||
$this->_db->delete(
|
||||
sprintf($sql, $val, self::BASE_TABLE),
|
||||
array($purge)
|
||||
);
|
||||
} catch (Horde_Db_Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$this->_db->delete(
|
||||
sprintf('DELETE FROM %s WHERE modified < ?', self::BASE_TABLE),
|
||||
array($purge)
|
||||
);
|
||||
} catch (Horde_Db_Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the base SQL query.
|
||||
*
|
||||
* @param string $mailbox The mailbox.
|
||||
* @param string $join The table to join with the base table.
|
||||
*
|
||||
* @return array SQL query and bound parameters.
|
||||
*/
|
||||
protected function _baseSql($mailbox, $join = null)
|
||||
{
|
||||
$sql = sprintf('FROM %s d', self::BASE_TABLE);
|
||||
|
||||
if (!is_null($join)) {
|
||||
$sql .= sprintf(' INNER JOIN %s t ON d.messageid = t.messageid', $join);
|
||||
}
|
||||
|
||||
return array(
|
||||
$sql . ' WHERE d.hostspec = ? AND d.port = ? AND d.username = ? AND d.mailbox = ?',
|
||||
array(
|
||||
$this->_params['hostspec'],
|
||||
$this->_params['port'],
|
||||
$this->_params['username'],
|
||||
$mailbox
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mailbox
|
||||
*
|
||||
* @return string UID from base table.
|
||||
*/
|
||||
protected function _getUid($mailbox)
|
||||
{
|
||||
$query = $this->_baseSql($mailbox);
|
||||
$query[0] = 'SELECT d.messageid ' . $query[0];
|
||||
|
||||
try {
|
||||
return $this->_db->selectValue($query[0], $query[1]);
|
||||
} catch (Horde_Db_Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mailbox
|
||||
*
|
||||
* @return string UID from base table.
|
||||
*/
|
||||
protected function _createUid($mailbox)
|
||||
{
|
||||
return $this->_db->insert(
|
||||
sprintf(
|
||||
'INSERT INTO %s (hostspec, mailbox, port, username) ' .
|
||||
'VALUES (?, ?, ?, ?)',
|
||||
self::BASE_TABLE
|
||||
),
|
||||
array(
|
||||
$this->_params['hostspec'],
|
||||
$mailbox,
|
||||
$this->_params['port'],
|
||||
$this->_params['username']
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,421 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2013-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Horde_HashTable implementation for caching IMAP/POP data.
|
||||
* Requires the Horde_HashTable and Horde_Pack packages.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.17.0
|
||||
*/
|
||||
class Horde_Imap_Client_Cache_Backend_Hashtable
|
||||
extends Horde_Imap_Client_Cache_Backend
|
||||
{
|
||||
/** Separator for CID between mailbox and UID. */
|
||||
const CID_SEPARATOR = '|';
|
||||
|
||||
/**
|
||||
* The working data for the current pageload. All changes take place to
|
||||
* this data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_data = array();
|
||||
|
||||
/**
|
||||
* HashTable object.
|
||||
*
|
||||
* @var Horde_HashTable
|
||||
*/
|
||||
protected $_hash;
|
||||
|
||||
/**
|
||||
* Mailbox level data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_mbox = array();
|
||||
|
||||
/**
|
||||
* Horde_Pack singleton object.
|
||||
*
|
||||
* @var Horde_Pack
|
||||
*/
|
||||
protected $_pack;
|
||||
|
||||
/**
|
||||
* List of mailbox/UIDs to update.
|
||||
* Keys are mailboxes. Values are arrays with three possible keys:
|
||||
* <pre>
|
||||
* - d: UIDs to delete
|
||||
* - m: Was metadata updated?
|
||||
* - u: UIDs to update
|
||||
* </pre>
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_update = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $params Configuration parameters:
|
||||
* <pre>
|
||||
* - REQUIRED parameters:
|
||||
* - hashtable: (Horde_HashTable) A HashTable object.
|
||||
*
|
||||
* - Optional Parameters:
|
||||
* - lifetime: (integer) The lifetime of the cache data (in seconds).
|
||||
* DEFAULT: 604800 seconds (1 week) [@since 2.19.0]
|
||||
* </pre>
|
||||
*/
|
||||
public function __construct(array $params = array())
|
||||
{
|
||||
if (!isset($params['hashtable'])) {
|
||||
throw new InvalidArgumentException('Missing hashtable parameter.');
|
||||
}
|
||||
|
||||
parent::__construct(array_merge(array(
|
||||
'lifetime' => 604800
|
||||
), $params));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
protected function _initOb()
|
||||
{
|
||||
$this->_hash = $this->_params['hashtable'];
|
||||
$this->_pack = new Horde_Pack();
|
||||
register_shutdown_function(array($this, 'save'));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function get($mailbox, $uids, $fields, $uidvalid)
|
||||
{
|
||||
$ret = array();
|
||||
|
||||
if (empty($uids)) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$this->_loadUids($mailbox, $uids, $uidvalid);
|
||||
|
||||
if (empty($this->_data[$mailbox])) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if (!empty($fields)) {
|
||||
$fields = array_flip($fields);
|
||||
}
|
||||
$ptr = &$this->_data[$mailbox];
|
||||
$to_delete = array();
|
||||
|
||||
foreach ($uids as $val) {
|
||||
if (isset($ptr[$val])) {
|
||||
if (is_string($ptr[$val])) {
|
||||
try {
|
||||
$ptr[$val] = $this->_pack->unpack($ptr[$val]);
|
||||
} catch (Horde_Pack_Exception $e) {
|
||||
$to_delete[] = $val;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$ret[$val] = (empty($fields) || empty($ptr[$val]))
|
||||
? $ptr[$val]
|
||||
: array_intersect_key($ptr[$val], $fields);
|
||||
} else {
|
||||
$to_delete[] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
$this->deleteMsgs($mailbox, $to_delete);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getCachedUids($mailbox, $uidvalid)
|
||||
{
|
||||
$this->_loadMailbox($mailbox, $uidvalid);
|
||||
return $this->_mbox[$mailbox]['u']->ids;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function set($mailbox, $data, $uidvalid)
|
||||
{
|
||||
$this->_loadUids($mailbox, array_keys($data), $uidvalid);
|
||||
|
||||
$d = &$this->_data[$mailbox];
|
||||
$to_add = array();
|
||||
|
||||
foreach ($data as $k => $v) {
|
||||
if (isset($d[$k]) && is_string($d[$k])) {
|
||||
try {
|
||||
$d[$k] = $this->_pack->unpack($d[$k]);
|
||||
} catch (Horde_Pack_Exception $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$d[$k] = (isset($d[$k]) && is_array($d[$k]))
|
||||
? array_merge($d[$k], $v)
|
||||
: $v;
|
||||
$this->_update[$mailbox]['u'][$k] = true;
|
||||
unset($this->_update[$mailbox]['d'][$k]);
|
||||
$to_add[] = $k;
|
||||
}
|
||||
|
||||
if (!empty($to_add)) {
|
||||
$this->_mbox[$mailbox]['u']->add($to_add);
|
||||
$this->_update[$mailbox]['m'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getMetaData($mailbox, $uidvalid, $entries)
|
||||
{
|
||||
$this->_loadMailbox($mailbox, $uidvalid);
|
||||
|
||||
return empty($entries)
|
||||
? $this->_mbox[$mailbox]['d']
|
||||
: array_intersect_key($this->_mbox[$mailbox]['d'], array_flip($entries));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function setMetaData($mailbox, $data)
|
||||
{
|
||||
$this->_loadMailbox($mailbox, isset($data['uidvalid']) ? $data['uidvalid'] : null);
|
||||
|
||||
$this->_mbox[$mailbox]['d'] = array_merge(
|
||||
$this->_mbox[$mailbox]['d'],
|
||||
$data
|
||||
);
|
||||
$this->_update[$mailbox]['m'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function deleteMsgs($mailbox, $uids)
|
||||
{
|
||||
if (empty($uids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_loadMailbox($mailbox);
|
||||
|
||||
foreach ($uids as $val) {
|
||||
unset(
|
||||
$this->_data[$mailbox][$val],
|
||||
$this->_update[$mailbox]['u'][$val]
|
||||
);
|
||||
$this->_update[$mailbox]['d'][$val] = true;
|
||||
}
|
||||
|
||||
$this->_mbox[$mailbox]['u']->remove($uids);
|
||||
$this->_update[$mailbox]['m'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function deleteMailbox($mailbox)
|
||||
{
|
||||
/* Do this action immediately, instead of at shutdown. Makes coding
|
||||
* simpler. */
|
||||
$this->_loadMailbox($mailbox);
|
||||
|
||||
$this->_hash->delete(array_merge(
|
||||
array($this->_getCid($mailbox)),
|
||||
array_values($this->_getMsgCids($mailbox, $this->_mbox[$mailbox]['u']))
|
||||
));
|
||||
|
||||
unset(
|
||||
$this->_data[$mailbox],
|
||||
$this->_mbox[$mailbox],
|
||||
$this->_update[$mailbox]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function clear($lifetime)
|
||||
{
|
||||
/* Only can clear mailboxes we know about. */
|
||||
foreach (array_keys($this->_mbox) as $val) {
|
||||
$this->deleteMailbox($val);
|
||||
}
|
||||
|
||||
$this->_data = $this->_mbox = $this->_update = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the cache.
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
foreach ($this->_update as $mbox => $val) {
|
||||
try {
|
||||
if (!empty($val['u'])) {
|
||||
$ptr = &$this->_data[$mbox];
|
||||
foreach ($this->_getMsgCids($mbox, array_keys($val['u'])) as $k2 => $v2) {
|
||||
try {
|
||||
$this->_hash->set(
|
||||
$v2,
|
||||
$this->_pack->pack($ptr[$k2]),
|
||||
array('expire' => $this->_params['lifetime'])
|
||||
);
|
||||
} catch (Horde_Pack_Exception $e) {
|
||||
$this->deleteMsgs($mbox, array($v2));
|
||||
$val['d'][] = $v2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($val['d'])) {
|
||||
$this->_hash->delete(array_values(
|
||||
$this->_getMsgCids($mbox, $val['d'])
|
||||
));
|
||||
}
|
||||
|
||||
if (!empty($val['m'])) {
|
||||
try {
|
||||
$this->_hash->set(
|
||||
$this->_getCid($mbox),
|
||||
$this->_pack->pack($this->_mbox[$mbox]),
|
||||
array('expire' => $this->_params['lifetime'])
|
||||
);
|
||||
} catch (Horde_Pack_Exception $e) {}
|
||||
}
|
||||
} catch (Horde_Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
$this->_update = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads basic mailbox information.
|
||||
*
|
||||
* @param string $mailbox The mailbox to load.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
*/
|
||||
protected function _loadMailbox($mailbox, $uidvalid = null)
|
||||
{
|
||||
if (!isset($this->_mbox[$mailbox]) &&
|
||||
($ob = $this->_hash->get($this->_getCid($mailbox)))) {
|
||||
try {
|
||||
$this->_mbox[$mailbox] = $this->_pack->unpack($ob);
|
||||
} catch (Horde_Pack_Exception $e) {}
|
||||
}
|
||||
|
||||
if (isset($this->_mbox[$mailbox])) {
|
||||
if (is_null($uidvalid) ||
|
||||
($uidvalid == $this->_mbox[$mailbox]['d']['uidvalid'])) {
|
||||
return;
|
||||
}
|
||||
$this->deleteMailbox($mailbox);
|
||||
}
|
||||
|
||||
$this->_mbox[$mailbox] = array(
|
||||
// Metadata storage
|
||||
// By default includes UIDVALIDITY of mailbox.
|
||||
'd' => array('uidvalid' => $uidvalid),
|
||||
// List of UIDs
|
||||
'u' => new Horde_Imap_Client_Ids()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load UIDs by regenerating from the cache.
|
||||
*
|
||||
* @param string $mailbox The mailbox to load.
|
||||
* @param array $uids The UIDs to load.
|
||||
* @param integer $uidvalid The IMAP uidvalidity value of the mailbox.
|
||||
*/
|
||||
protected function _loadUids($mailbox, $uids, $uidvalid = null)
|
||||
{
|
||||
if (!isset($this->_data[$mailbox])) {
|
||||
$this->_data[$mailbox] = array();
|
||||
}
|
||||
|
||||
$this->_loadMailbox($mailbox, $uidvalid);
|
||||
|
||||
if (empty($uids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ptr = &$this->_data[$mailbox];
|
||||
|
||||
$load = array_flip(
|
||||
array_diff_key(
|
||||
$this->_getMsgCids(
|
||||
$mailbox,
|
||||
array_unique(array_intersect($this->_mbox[$mailbox]['u']->ids, $uids))
|
||||
),
|
||||
$this->_data[$mailbox]
|
||||
)
|
||||
);
|
||||
|
||||
foreach (array_filter($this->_hash->get(array_keys($load))) as $key => $val) {
|
||||
$ptr[$load[$key]] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the unique ID used to store the mailbox data in the cache.
|
||||
*
|
||||
* @param string $mailbox The mailbox to cache.
|
||||
*
|
||||
* @return string The cache ID.
|
||||
*/
|
||||
protected function _getCid($mailbox)
|
||||
{
|
||||
return implode(self::CID_SEPARATOR, array(
|
||||
'horde_imap_client',
|
||||
$this->_params['username'],
|
||||
$mailbox,
|
||||
$this->_params['hostspec'],
|
||||
$this->_params['port']
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of cache IDs for mailbox/UID pairs.
|
||||
*
|
||||
* @param string $mailbox The mailbox to cache.
|
||||
* @param array $ids The UID list.
|
||||
*
|
||||
* @return array List of UIDs => cache IDs.
|
||||
*/
|
||||
protected function _getMsgCids($mailbox, $ids)
|
||||
{
|
||||
$cid = $this->_getCid($mailbox);
|
||||
$out = array();
|
||||
|
||||
foreach ($ids as $val) {
|
||||
$out[$val] = $cid . self::CID_SEPARATOR . $val;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
@ -1,440 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2013-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* A MongoDB database implementation for caching IMAP/POP data.
|
||||
*
|
||||
* Requires the Horde_Mongo class.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Cache_Backend_Mongo
|
||||
extends Horde_Imap_Client_Cache_Backend
|
||||
implements Horde_Mongo_Collection_Index
|
||||
{
|
||||
/** Mongo collection names. */
|
||||
const BASE = 'horde_imap_client_cache_data';
|
||||
const MD = 'horde_imap_client_cache_metadata';
|
||||
const MSG = 'horde_imap_client_cache_message';
|
||||
|
||||
/** Mongo field names: BASE collection. */
|
||||
const BASE_HOSTSPEC = 'hostspec';
|
||||
const BASE_MAILBOX = 'mailbox';
|
||||
const BASE_MODIFIED = 'modified';
|
||||
const BASE_PORT = 'port';
|
||||
const BASE_UID = 'data';
|
||||
const BASE_USERNAME = 'username';
|
||||
|
||||
/** Mongo field names: MD collection. */
|
||||
const MD_DATA = 'data';
|
||||
const MD_FIELD = 'field';
|
||||
const MD_UID = 'uid';
|
||||
|
||||
/** Mongo field names: MSG collection. */
|
||||
const MSG_DATA = 'data';
|
||||
const MSG_MSGUID = 'msguid';
|
||||
const MSG_UID = 'uid';
|
||||
|
||||
/**
|
||||
* The MongoDB object for the cache data.
|
||||
*
|
||||
* @var MongoDB
|
||||
*/
|
||||
protected $_db;
|
||||
|
||||
/**
|
||||
* The list of indices.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_indices = array(
|
||||
self::BASE => array(
|
||||
'base_index_1' => array(
|
||||
self::BASE_HOSTSPEC => 1,
|
||||
self::BASE_MAILBOX => 1,
|
||||
self::BASE_PORT => 1,
|
||||
self::BASE_USERNAME => 1,
|
||||
)
|
||||
),
|
||||
self::MSG => array(
|
||||
'msg_index_1' => array(
|
||||
self::MSG_MSGUID => 1,
|
||||
self::MSG_UID => 1
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $params Configuration parameters:
|
||||
* <pre>
|
||||
* - REQUIRED parameters:
|
||||
* - mongo_db: (Horde_Mongo_Client) A MongoDB client object.
|
||||
* </pre>
|
||||
*/
|
||||
public function __construct(array $params = array())
|
||||
{
|
||||
if (!isset($params['mongo_db'])) {
|
||||
throw new InvalidArgumentException('Missing mongo_db parameter.');
|
||||
}
|
||||
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
protected function _initOb()
|
||||
{
|
||||
$this->_db = $this->_params['mongo_db']->selectDB(null);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function get($mailbox, $uids, $fields, $uidvalid)
|
||||
{
|
||||
$this->getMetaData($mailbox, $uidvalid, array('uidvalid'));
|
||||
|
||||
if (!($uid = $this->_getUid($mailbox))) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$out = array();
|
||||
$query = array(
|
||||
self::MSG_MSGUID => array('$in' => array_map('strval', $uids)),
|
||||
self::MSG_UID => $uid
|
||||
);
|
||||
|
||||
try {
|
||||
$cursor = $this->_db->selectCollection(self::MSG)->find(
|
||||
$query,
|
||||
array(self::MSG_DATA => true, self::MSG_MSGUID => true)
|
||||
);
|
||||
foreach ($cursor as $val) {
|
||||
try {
|
||||
$out[$val[self::MSG_MSGUID]] = $this->_value($val[self::MSG_DATA]);
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
} catch (MongoException $e) {}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getCachedUids($mailbox, $uidvalid)
|
||||
{
|
||||
$this->getMetaData($mailbox, $uidvalid, array('uidvalid'));
|
||||
|
||||
if (!($uid = $this->_getUid($mailbox))) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$out = array();
|
||||
$query = array(
|
||||
self::MSG_UID => $uid
|
||||
);
|
||||
|
||||
try {
|
||||
$cursor = $this->_db->selectCollection(self::MSG)->find(
|
||||
$query, array(self::MSG_MSGUID => true)
|
||||
);
|
||||
foreach ($cursor as $val) {
|
||||
$out[] = $val[self::MSG_MSGUID];
|
||||
}
|
||||
} catch (MongoException $e) {}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function set($mailbox, $data, $uidvalid)
|
||||
{
|
||||
if ($uid = $this->_getUid($mailbox)) {
|
||||
$res = $this->get($mailbox, array_keys($data), array(), $uidvalid);
|
||||
} else {
|
||||
$res = array();
|
||||
$uid = $this->_createUid($mailbox);
|
||||
}
|
||||
|
||||
$coll = $this->_db->selectCollection(self::MSG);
|
||||
|
||||
foreach ($data as $key => $val) {
|
||||
try {
|
||||
if (isset($res[$key])) {
|
||||
$coll->update(array(
|
||||
self::MSG_MSGUID => strval($key),
|
||||
self::MSG_UID => $uid
|
||||
), array(
|
||||
self::MSG_DATA => $this->_value(array_merge($res[$key], $val)),
|
||||
self::MSG_MSGUID => strval($key),
|
||||
self::MSG_UID => $uid
|
||||
));
|
||||
} else {
|
||||
$doc = array(
|
||||
self::MSG_DATA => $this->_value($val),
|
||||
self::MSG_MSGUID => strval($key),
|
||||
self::MSG_UID => $uid
|
||||
);
|
||||
$coll->insert($doc);
|
||||
}
|
||||
} catch (MongoException $e) {}
|
||||
}
|
||||
|
||||
/* Update modified time. */
|
||||
try {
|
||||
$this->_db->selectCollection(self::BASE)->update(
|
||||
array(self::BASE_UID => $uid),
|
||||
array(self::BASE_MODIFIED => time())
|
||||
);
|
||||
} catch (MongoException $e) {}
|
||||
|
||||
/* Update uidvalidity. */
|
||||
$this->setMetaData($mailbox, array('uidvalid' => $uidvalid));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getMetaData($mailbox, $uidvalid, $entries)
|
||||
{
|
||||
if (!($uid = $this->_getUid($mailbox))) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$out = array();
|
||||
$query = array(
|
||||
self::MD_UID => $uid
|
||||
);
|
||||
|
||||
if (!empty($entries)) {
|
||||
$entries[] = 'uidvalid';
|
||||
$query[self::MD_FIELD] = array(
|
||||
'$in' => array_unique($entries)
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
$cursor = $this->_db->selectCollection(self::MD)->find(
|
||||
$query,
|
||||
array(self::MD_DATA => true, self::MD_FIELD => true)
|
||||
);
|
||||
foreach ($cursor as $val) {
|
||||
try {
|
||||
$out[$val[self::MD_FIELD]] = $this->_value($val[self::MD_DATA]);
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
|
||||
if (is_null($uidvalid) ||
|
||||
!isset($out['uidvalid']) ||
|
||||
($out['uidvalid'] == $uidvalid)) {
|
||||
return $out;
|
||||
}
|
||||
|
||||
$this->deleteMailbox($mailbox);
|
||||
} catch (MongoException $e) {}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function setMetaData($mailbox, $data)
|
||||
{
|
||||
if (!($uid = $this->_getUid($mailbox))) {
|
||||
$uid = $this->_createUid($mailbox);
|
||||
}
|
||||
|
||||
$coll = $this->_db->selectCollection(self::MD);
|
||||
|
||||
foreach ($data as $key => $val) {
|
||||
try {
|
||||
$coll->update(
|
||||
array(
|
||||
self::MD_FIELD => $key,
|
||||
self::MD_UID => $uid
|
||||
),
|
||||
array(
|
||||
self::MD_DATA => $this->_value($val),
|
||||
self::MD_FIELD => $key,
|
||||
self::MD_UID => $uid
|
||||
),
|
||||
array('upsert' => true)
|
||||
);
|
||||
} catch (MongoException $e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function deleteMsgs($mailbox, $uids)
|
||||
{
|
||||
if (!empty($uids) && ($uid = $this->_getUid($mailbox))) {
|
||||
try {
|
||||
$this->_db->selectCollection(self::MSG)->remove(array(
|
||||
self::MSG_MSGUID => array(
|
||||
'$in' => array_map('strval', $uids)
|
||||
),
|
||||
self::MSG_UID => $uid
|
||||
));
|
||||
} catch (MongoException $e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function deleteMailbox($mailbox)
|
||||
{
|
||||
if (!($uid = $this->_getUid($mailbox))) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (array(self::BASE, self::MD, self::MSG) as $val) {
|
||||
try {
|
||||
$this->_db->selectCollection($val)
|
||||
->remove(array('uid' => $uid));
|
||||
} catch (MongoException $e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function clear($lifetime)
|
||||
{
|
||||
if (is_null($lifetime)) {
|
||||
foreach (array(self::BASE, self::MD, self::MSG) as $val) {
|
||||
$this->_db->selectCollection($val)->drop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$query = array(
|
||||
self::BASE_MODIFIED => array('$lt' => (time() - $lifetime))
|
||||
);
|
||||
$uids = array();
|
||||
|
||||
try {
|
||||
$cursor = $this->_db->selectCollection(self::BASE)->find($query);
|
||||
foreach ($cursor as $val) {
|
||||
$uids[] = strval($val['_id']);
|
||||
}
|
||||
} catch (MongoException $e) {}
|
||||
|
||||
if (empty($uids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (array(self::BASE, self::MD, self::MSG) as $val) {
|
||||
try {
|
||||
$this->_db->selectCollection($val)
|
||||
->remove(array('uid' => array('$in' => $uids)));
|
||||
} catch (MongoException $e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the UID for a mailbox/user/server combo.
|
||||
*
|
||||
* @param string $mailbox Mailbox name.
|
||||
*
|
||||
* @return string UID from base table.
|
||||
*/
|
||||
protected function _getUid($mailbox)
|
||||
{
|
||||
$query = array(
|
||||
self::BASE_HOSTSPEC => $this->_params['hostspec'],
|
||||
self::BASE_MAILBOX => $mailbox,
|
||||
self::BASE_PORT => $this->_params['port'],
|
||||
self::BASE_USERNAME => $this->_params['username']
|
||||
);
|
||||
|
||||
try {
|
||||
if ($result = $this->_db->selectCollection(self::BASE)->findOne($query)) {
|
||||
return strval($result['_id']);
|
||||
}
|
||||
} catch (MongoException $e) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return the UID for a mailbox/user/server combo.
|
||||
*
|
||||
* @param string $mailbox Mailbox name.
|
||||
*
|
||||
* @return string UID from base table.
|
||||
*/
|
||||
protected function _createUid($mailbox)
|
||||
{
|
||||
$doc = array(
|
||||
self::BASE_HOSTSPEC => $this->_params['hostspec'],
|
||||
self::BASE_MAILBOX => $mailbox,
|
||||
self::BASE_PORT => $this->_params['port'],
|
||||
self::BASE_USERNAME => $this->_params['username']
|
||||
);
|
||||
$this->_db->selectCollection(self::BASE)->insert($doc);
|
||||
|
||||
return $this->_getUid($mailbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert data from/to storage format.
|
||||
*
|
||||
* @param mixed|MongoBinData $data The data object.
|
||||
*
|
||||
* @return mixed|MongoBinData The converted data.
|
||||
*/
|
||||
protected function _value($data)
|
||||
{
|
||||
static $compress;
|
||||
|
||||
if (!isset($compress)) {
|
||||
$compress = new Horde_Compress_Fast();
|
||||
}
|
||||
|
||||
return ($data instanceof MongoBinData)
|
||||
? @unserialize($compress->decompress($data->bin))
|
||||
: new MongoBinData(
|
||||
$compress->compress(serialize($data)), MongoBinData::BYTE_ARRAY
|
||||
);
|
||||
}
|
||||
|
||||
/* Horde_Mongo_Collection_Index methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function checkMongoIndices()
|
||||
{
|
||||
foreach ($this->_indices as $key => $val) {
|
||||
if (!$this->_params['mongo_db']->checkIndices($key, $val)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function createMongoIndices()
|
||||
{
|
||||
foreach ($this->_indices as $key => $val) {
|
||||
$this->_params['mongo_db']->createIndices($key, $val);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2013-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* A null backend class for storing cached IMAP/POP data.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Cache_Backend_Null
|
||||
extends Horde_Imap_Client_Cache_Backend
|
||||
{
|
||||
/**
|
||||
*/
|
||||
public function get($mailbox, $uids, $fields, $uidvalid)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getCachedUids($mailbox, $uidvalid)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function set($mailbox, $data, $uidvalid)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getMetaData($mailbox, $uidvalid, $entries)
|
||||
{
|
||||
return array(
|
||||
'uidvalid' => 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function setMetaData($mailbox, $data)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function deleteMsgs($mailbox, $uids)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function deleteMailbox($mailbox)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function clear($lifetime)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
@ -1,188 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* ACL rights for a mailbox (see RFC 2086/4314).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Acl extends Horde_Imap_Client_Data_AclCommon implements ArrayAccess, IteratorAggregate, Serializable
|
||||
{
|
||||
/**
|
||||
* ACL rights.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_rights;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $rights The rights (see RFC 4314 [2.1]).
|
||||
*/
|
||||
public function __construct($rights = '')
|
||||
{
|
||||
$this->_rights = str_split($rights);
|
||||
$this->_normalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of the ACL.
|
||||
*
|
||||
* @return string String representation (RFC 4314 compliant).
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return implode('', $this->_rights);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference to another rights string.
|
||||
* Virtual rights are ignored.
|
||||
*
|
||||
* @param string $rights The rights to compute against.
|
||||
*
|
||||
* @return array Two element array: added and removed.
|
||||
*/
|
||||
public function diff($rights)
|
||||
{
|
||||
$rlist = array_diff(str_split($rights), array_keys($this->_virtual));
|
||||
|
||||
return array(
|
||||
'added' => implode('', array_diff($rlist, $this->_rights)),
|
||||
'removed' => implode('', array_diff($this->_rights, $rlist))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize virtual rights (see RFC 4314 [2.1.1]).
|
||||
*/
|
||||
protected function _normalize()
|
||||
{
|
||||
/* Clients conforming to RFC 4314 MUST ignore the virtual ACL_CREATE
|
||||
* and ACL_DELETE rights. See RFC 4314 [2.1]. However, we still need
|
||||
* to handle these rights when dealing with RFC 2086 servers since
|
||||
* we are abstracting out use of ACL_CREATE/ACL_DELETE to their
|
||||
* component RFC 4314 rights. */
|
||||
foreach ($this->_virtual as $key => $val) {
|
||||
foreach ($val as $right) {
|
||||
if ($this[$right]) {
|
||||
foreach (array_keys($this->_virtual) as $virtual) {
|
||||
unset($this[$virtual]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($this->_virtual as $key => $val) {
|
||||
if ($this[$key]) {
|
||||
unset($this[$key]);
|
||||
$this->_rights = array_unique(array_merge($this->_rights, $val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ArrayAccess methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return $this[$offset];
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return in_array($offset, $this->_rights);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if ($value) {
|
||||
if (!$this[$offset]) {
|
||||
$this->_rights[] = $offset;
|
||||
$this->_normalize();
|
||||
}
|
||||
} elseif ($this[$offset]) {
|
||||
if (isset($this->_virtual[$offset])) {
|
||||
foreach ($this->_virtual[$offset] as $val) {
|
||||
unset($this[$val]);
|
||||
}
|
||||
}
|
||||
unset($this[$offset]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
$this->_rights = array_values(array_diff($this->_rights, array($offset)));
|
||||
}
|
||||
|
||||
/* IteratorAggregate method. */
|
||||
|
||||
#[ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->_rights);
|
||||
}
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function unserialize($data)
|
||||
{
|
||||
$data = @unserialize($data);
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Cache version changed.');
|
||||
}
|
||||
$this->__unserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return array(
|
||||
'rights' => $this->_rights
|
||||
);
|
||||
}
|
||||
|
||||
public function __unserialize(array $data)
|
||||
{
|
||||
$this->_rights = $data['rights'];
|
||||
}
|
||||
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides common methods shared in all ACL classes (see RFC 2086/4314).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_AclCommon
|
||||
{
|
||||
/** Constants for getString(). */
|
||||
const RFC_2086 = 1;
|
||||
const RFC_4314 = 2;
|
||||
|
||||
/**
|
||||
* List of virtual rights (RFC 4314 [2.1.1]).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_virtual = array(
|
||||
Horde_Imap_Client::ACL_CREATE => array(
|
||||
Horde_Imap_Client::ACL_CREATEMBOX,
|
||||
Horde_Imap_Client::ACL_DELETEMBOX
|
||||
),
|
||||
Horde_Imap_Client::ACL_DELETE => array(
|
||||
Horde_Imap_Client::ACL_DELETEMSGS,
|
||||
// Don't put this first - we do checks on the existence of the
|
||||
// first element in this array to determine the RFC type, and this
|
||||
// is duplicate of right contained in ACL_CREATE.
|
||||
Horde_Imap_Client::ACL_DELETEMBOX,
|
||||
Horde_Imap_Client::ACL_EXPUNGE
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the raw string to use in IMAP server calls.
|
||||
*
|
||||
* @param integer $type The RFC type to use (RFC_* constant).
|
||||
*
|
||||
* @return string The string representation of the ACL.
|
||||
*/
|
||||
public function getString($type = self::RFC_4314)
|
||||
{
|
||||
$acl = strval($this);
|
||||
|
||||
if ($type == self::RFC_2086) {
|
||||
foreach ($this->_virtual as $key => $val) {
|
||||
$acl = str_replace($val, '', $acl, $count);
|
||||
if ($count) {
|
||||
$acl .= $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $acl;
|
||||
}
|
||||
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* ACL *negative* rights for a mailbox (see RFC 2086/4314 [2]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_AclNegative extends Horde_Imap_Client_Data_Acl
|
||||
{
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Available ACL rights for a mailbox/identifier (see RFC 2086/4314).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_AclRights extends Horde_Imap_Client_Data_AclCommon implements ArrayAccess, Iterator, Serializable
|
||||
{
|
||||
/**
|
||||
* ACL optional rights.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_optional = array();
|
||||
|
||||
/**
|
||||
* ACL required rights.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_required = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $required The required rights (see RFC 4314 [2.1]).
|
||||
* @param array $optional The optional rights (see RFC 4314 [2.1]).
|
||||
*/
|
||||
public function __construct(array $required = array(),
|
||||
array $optional = array())
|
||||
{
|
||||
$this->_required = $required;
|
||||
|
||||
foreach ($optional as $val) {
|
||||
foreach (str_split($val) as $right) {
|
||||
$this->_optional[$right] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_normalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of the ACL.
|
||||
*
|
||||
* @return string String representation (RFC 4314 compliant).
|
||||
*
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return implode('', array_keys(array_flip(array_merge(array_values($this->_required), array_keys($this->_optional)))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize virtual rights (see RFC 4314 [2.1.1]).
|
||||
*/
|
||||
protected function _normalize()
|
||||
{
|
||||
/* Clients conforming to RFC 4314 MUST ignore the virtual ACL_CREATE
|
||||
* and ACL_DELETE rights. See RFC 4314 [2.1]. However, we still need
|
||||
* to handle these rights when dealing with RFC 2086 servers since
|
||||
* we are abstracting out use of ACL_CREATE/ACL_DELETE to their
|
||||
* component RFC 4314 rights. */
|
||||
foreach ($this->_virtual as $key => $val) {
|
||||
if (isset($this->_optional[$key])) {
|
||||
unset($this->_optional[$key]);
|
||||
foreach ($val as $val2) {
|
||||
$this->_optional[$val2] = implode('', $val);
|
||||
}
|
||||
} elseif (($pos = array_search($key, $this->_required)) !== false) {
|
||||
unset($this->_required[$pos]);
|
||||
$this->_required = array_unique(array_merge($this->_required, $val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ArrayAccess methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return (bool)$this[$offset];
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if (isset($this->_optional[$offset])) {
|
||||
return $this->_optional[$offset];
|
||||
}
|
||||
|
||||
$pos = array_search($offset, $this->_required);
|
||||
|
||||
return ($pos === false)
|
||||
? null
|
||||
: $this->_required[$pos];
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->_optional[$offset] = $value;
|
||||
$this->_normalize();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->_optional[$offset]);
|
||||
$this->_required = array_values(array_diff($this->_required, array($offset)));
|
||||
|
||||
if (isset($this->_virtual[$offset])) {
|
||||
foreach ($this->_virtual[$offset] as $val) {
|
||||
unset($this[$val]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterator methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
$val = current($this->_required);
|
||||
return is_null($val)
|
||||
? current($this->_optional)
|
||||
: $val;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function key()
|
||||
{
|
||||
$key = key($this->_required);
|
||||
return is_null($key)
|
||||
? key($this->_optional)
|
||||
: $key;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function next()
|
||||
{
|
||||
if (key($this->_required) === null) {
|
||||
next($this->_optional);
|
||||
} else {
|
||||
next($this->_required);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function rewind()
|
||||
{
|
||||
reset($this->_required);
|
||||
reset($this->_optional);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function valid()
|
||||
{
|
||||
return ((key($this->_required) !== null) ||
|
||||
(key($this->_optional) !== null));
|
||||
|
||||
}
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function unserialize($data)
|
||||
{
|
||||
$data = @unserialize($data);
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Cache version changed.');
|
||||
}
|
||||
$this->__unserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return [$this->_required, $this->_optional];
|
||||
}
|
||||
|
||||
public function __unserialize(array $data)
|
||||
{
|
||||
list($this->_required, $this->_optional) = $data;
|
||||
}
|
||||
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2008-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* getBaseSubject() code adapted from imap-base-subject.c (Dovecot 1.2)
|
||||
* Original code released under the LGPL-2.1
|
||||
* Copyright (c) 2002-2008 Timo Sirainen <tss@iki.fi>
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2002-2008 Timo Sirainen
|
||||
* @copyright 2008-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determines the "base subject" of a string (RFC 5256 [2.1]).
|
||||
*
|
||||
* @author Timo Sirainen <tss@iki.fi>
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2002-2008 Timo Sirainen
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_BaseSubject
|
||||
{
|
||||
/**
|
||||
* The base subject.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_subject;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $str The subject string.
|
||||
* @param array $opts Additional options:
|
||||
* - keepblob: (boolean) Don't remove any "blob" information (i.e. text
|
||||
* leading text between square brackets) from string.
|
||||
*
|
||||
* @return string The cleaned up subject string.
|
||||
*/
|
||||
public function __construct($str, array $opts = array())
|
||||
{
|
||||
// Rule 1a: MIME decode.
|
||||
$str = Horde_Mime::decode($str);
|
||||
|
||||
// Rule 1b: Remove superfluous whitespace.
|
||||
$str = preg_replace("/[\t\r\n ]+/", ' ', $str);
|
||||
|
||||
do {
|
||||
/* (2) Remove all trailing text of the subject that matches the
|
||||
* the subj-trailer ABNF, repeat until no more matches are
|
||||
* possible. */
|
||||
$str = preg_replace("/(?:\s*\(fwd\)\s*)+$/i", '', $str);
|
||||
|
||||
do {
|
||||
/* (3) Remove all prefix text of the subject that matches the
|
||||
* subj-leader ABNF. */
|
||||
$found = $this->_removeSubjLeader($str, !empty($opts['keepblob']));
|
||||
|
||||
/* (4) If there is prefix text of the subject that matches
|
||||
* the subj-blob ABNF, and removing that prefix leaves a
|
||||
* non-empty subj-base, then remove the prefix text. */
|
||||
$found = (empty($opts['keepblob']) && $this->_removeBlobWhenNonempty($str)) || $found;
|
||||
|
||||
/* (5) Repeat (3) and (4) until no matches remain. */
|
||||
} while ($found);
|
||||
|
||||
/* (6) If the resulting text begins with the subj-fwd-hdr ABNF and
|
||||
* ends with the subj-fwd-trl ABNF, remove the subj-fwd-hdr and
|
||||
* subj-fwd-trl and repeat from step (2). */
|
||||
} while ($this->_removeSubjFwdHdr($str));
|
||||
|
||||
$this->_subject = strval($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the "base subject" defined in RFC 5256 [2.1].
|
||||
*
|
||||
* @return string The base subject.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->_subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all prefix text of the subject that matches the subj-leader
|
||||
* ABNF.
|
||||
*
|
||||
* @param string &$str The subject string.
|
||||
* @param boolean $keepblob Remove blob information?
|
||||
*
|
||||
* @return boolean True if string was altered.
|
||||
*/
|
||||
protected function _removeSubjLeader(&$str, $keepblob = false)
|
||||
{
|
||||
$ret = false;
|
||||
|
||||
if (!strlen($str)) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($len = strspn($str, " \t")) {
|
||||
$str = substr($str, $len);
|
||||
$ret = true;
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
|
||||
if (!$keepblob) {
|
||||
while (isset($str[$i]) && ($str[$i] === '[')) {
|
||||
if (($i = $this->_removeBlob($str, $i)) === false) {
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stripos($str, 're', $i) === 0) {
|
||||
$i += 2;
|
||||
} elseif (stripos($str, 'fw', $i) === 0) {
|
||||
$i += (stripos($str, 'fwd', $i) === 0) ? 3 : 2;
|
||||
} else {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$i += strspn($str, " \t", $i);
|
||||
|
||||
if (!$keepblob) {
|
||||
while (isset($str[$i]) && ($str[$i] === '[')) {
|
||||
if (($i = $this->_removeBlob($str, $i)) === false) {
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($str[$i]) || ($str[$i] !== ':')) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$str = substr($str, ++$i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove "[...]" text.
|
||||
*
|
||||
* @param string $str The subject string.
|
||||
* @param integer $i Current position.
|
||||
*
|
||||
* @return boolean|integer False if blob was not found, otherwise the
|
||||
* string position of the first non-blob char.
|
||||
*/
|
||||
protected function _removeBlob($str, $i)
|
||||
{
|
||||
if ($str[$i] !== '[') {
|
||||
return false;
|
||||
}
|
||||
|
||||
++$i;
|
||||
|
||||
for ($cnt = strlen($str); $i < $cnt; ++$i) {
|
||||
if ($str[$i] === ']') {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($str[$i] === '[') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($i === ($cnt - 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
++$i;
|
||||
|
||||
if ($str[$i] === ' ') {
|
||||
++$i;
|
||||
}
|
||||
|
||||
return $i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove "[...]" text if it doesn't result in the subject becoming
|
||||
* empty.
|
||||
*
|
||||
* @param string &$str The subject string.
|
||||
*
|
||||
* @return boolean True if string was altered.
|
||||
*/
|
||||
protected function _removeBlobWhenNonempty(&$str)
|
||||
{
|
||||
if ($str &&
|
||||
($str[0] === '[') &&
|
||||
(($i = $this->_removeBlob($str, 0)) !== false) &&
|
||||
($i !== strlen($str))) {
|
||||
$str = substr($str, $i);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a "[fwd: ... ]" string.
|
||||
*
|
||||
* @param string &$str The subject string.
|
||||
*
|
||||
* @return boolean True if string was altered.
|
||||
*/
|
||||
protected function _removeSubjFwdHdr(&$str)
|
||||
{
|
||||
if ((stripos($str, '[fwd:') !== 0) || (substr($str, -1) !== ']')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$str = substr($str, 5, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,234 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Query the capabilities of a server.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.24.0
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Capability
|
||||
implements Serializable, SplSubject
|
||||
{
|
||||
/**
|
||||
* Capability data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_data = array();
|
||||
|
||||
/**
|
||||
* Observers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_observers = array();
|
||||
|
||||
/**
|
||||
* Add a capability (and optional parameters).
|
||||
*
|
||||
* @param string $capability The capability to add.
|
||||
* @param mixed $params A parameter (or array of parameters) to add.
|
||||
*/
|
||||
public function add($capability, $params = null)
|
||||
{
|
||||
$capability = Horde_String::upper($capability);
|
||||
|
||||
if (is_null($params)) {
|
||||
if (isset($this->_data[$capability])) {
|
||||
return;
|
||||
}
|
||||
$params = true;
|
||||
} else {
|
||||
if (!is_array($params)) {
|
||||
$params = array($params);
|
||||
}
|
||||
$params = array_map('Horde_String::upper', $params);
|
||||
|
||||
if (isset($this->_data[$capability]) &&
|
||||
is_array($this->_data[$capability])) {
|
||||
$params = array_merge($this->_data[$capability], $params);
|
||||
}
|
||||
}
|
||||
|
||||
$this->_data[$capability] = $params;
|
||||
$this->notify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a capability.
|
||||
*
|
||||
* @param string $capability The capability to remove.
|
||||
* @param string $params A parameter (or array of parameters) to
|
||||
* remove from the capability.
|
||||
*/
|
||||
public function remove($capability, $params = null)
|
||||
{
|
||||
$capability = Horde_String::upper($capability);
|
||||
|
||||
if (is_null($params)) {
|
||||
unset($this->_data[$capability]);
|
||||
} elseif (isset($this->_data[$capability])) {
|
||||
if (!is_array($params)) {
|
||||
$params = array($params);
|
||||
}
|
||||
$params = array_map('Horde_String::upper', $params);
|
||||
|
||||
$this->_data[$capability] = is_array($this->_data[$capability])
|
||||
? array_diff($this->_data[$capability], $params)
|
||||
: array();
|
||||
|
||||
if (empty($this->_data[$capability])) {
|
||||
unset($this->_data[$capability]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->notify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the server supports the given capability.
|
||||
*
|
||||
* @param string $capability The capability string to query.
|
||||
* @param string $parameter If set, require the parameter to exist.
|
||||
*
|
||||
* @return boolean True if the capability (and parameter) exist.
|
||||
*/
|
||||
public function query($capability, $parameter = null)
|
||||
{
|
||||
$capability = Horde_String::upper($capability);
|
||||
|
||||
if (!isset($this->_data[$capability])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_null($parameter) ?:
|
||||
(is_array($this->_data[$capability]) &&
|
||||
in_array(Horde_String::upper($parameter), $this->_data[$capability]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of parameters for an extension.
|
||||
*
|
||||
* @param string $capability The capability string to query.
|
||||
*
|
||||
* @return array An array of parameters if the extension exists and
|
||||
* supports parameters. Otherwise, an empty array.
|
||||
*/
|
||||
public function getParams($capability)
|
||||
{
|
||||
return ($this->query($capability) && is_array($out = $this->_data[Horde_String::upper($capability)]))
|
||||
? $out
|
||||
: array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the extension enabled?
|
||||
*
|
||||
* @param string $capability The extension (+ parameter) to query. If
|
||||
* null, returns all enabled extensions.
|
||||
*
|
||||
* @return mixed If $capability is null, return all enabled extensions.
|
||||
* Otherwise, true if the extension (+ parameter) is
|
||||
* enabled.
|
||||
*/
|
||||
public function isEnabled($capability = null)
|
||||
{
|
||||
return is_null($capability)
|
||||
? array()
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @return array Capability data.
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/* SplSubject methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function attach(SplObserver $observer)
|
||||
{
|
||||
$this->detach($observer);
|
||||
$this->_observers[] = $observer;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function detach(SplObserver $observer)
|
||||
{
|
||||
if (($key = array_search($observer, $this->_observers, true)) !== false) {
|
||||
unset($this->_observers[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification is triggered internally whenever the object's internal
|
||||
* data storage is altered.
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function notify()
|
||||
{
|
||||
foreach ($this->_observers as $val) {
|
||||
$val->update($this);
|
||||
}
|
||||
}
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function unserialize($data)
|
||||
{
|
||||
$data = @unserialize($data);
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Cache version change.');
|
||||
}
|
||||
$this->__unserialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
public function __unserialize(array $data)
|
||||
{
|
||||
$this->_data = $data;
|
||||
}
|
||||
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Query the capabilities of an IMAP server.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.24.0
|
||||
*
|
||||
* @property-read integer $cmdlength Allowable command length (in octets).
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Capability_Imap
|
||||
extends Horde_Imap_Client_Data_Capability
|
||||
{
|
||||
/**
|
||||
* The list of enabled extensions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_enabled = array();
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'cmdlength':
|
||||
/* RFC 2683 [3.2.1.5] originally recommended that lines should
|
||||
* be limited to "approximately 1000 octets". However, servers
|
||||
* should allow a command line of at least "8000 octets".
|
||||
* RFC 7162 [4] updates the recommendation to 8192 octets.
|
||||
* As a compromise, assume all modern IMAP servers handle
|
||||
* ~2000 octets and, if CONDSTORE/QRESYNC is supported, assume
|
||||
* they can handle ~8000 octets. (Don't need dependency support
|
||||
* checks here - the simple presence of CONDSTORE/QRESYNC is
|
||||
* enough to trigger.) */
|
||||
return (isset($this->_data['CONDSTORE']) || isset($this->_data['QRESYNC']))
|
||||
? 8000
|
||||
: 2000;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function query($capability, $parameter = null)
|
||||
{
|
||||
if (parent::query($capability, $parameter)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (Horde_String::upper($capability)) {
|
||||
case 'CONDSTORE':
|
||||
case 'ENABLE':
|
||||
/* RFC 7162 [3.2.3] - QRESYNC implies CONDSTORE and ENABLE. */
|
||||
return (is_null($parameter) && $this->query('QRESYNC'));
|
||||
|
||||
case 'UTF8':
|
||||
/* RFC 6855 [3] - UTF8=ONLY implies UTF8=ACCEPT. */
|
||||
return ((Horde_String::upper($parameter) === 'ACCEPT') &&
|
||||
$this->query('UTF8', 'ONLY'));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function isEnabled($capability = null)
|
||||
{
|
||||
return is_null($capability)
|
||||
? $this->_enabled
|
||||
: in_array(Horde_String::upper($capability), $this->_enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a capability as enabled/disabled.
|
||||
*
|
||||
* @param array $capability A capability (+ parameter).
|
||||
* @param boolean $enable If true, enables the capability.
|
||||
*/
|
||||
public function enable($capability, $enable = true)
|
||||
{
|
||||
$capability = Horde_String::upper($capability);
|
||||
$enabled = $this->isEnabled($capability);
|
||||
|
||||
if ($enable && !$enabled) {
|
||||
switch ($capability) {
|
||||
case 'QRESYNC':
|
||||
/* RFC 7162 [3.2.3] - Enabling QRESYNC also implies enabling
|
||||
* of CONDSTORE. */
|
||||
$this->enable('CONDSTORE');
|
||||
break;
|
||||
}
|
||||
|
||||
$this->_enabled[] = $capability;
|
||||
$this->notify();
|
||||
} elseif (!$enable && $enabled) {
|
||||
$this->_enabled = array_diff($this->_enabled, array($capability));
|
||||
$this->notify();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,238 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Envelope data as returned by the IMAP FETCH command (RFC 3501 [7.4.2]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*
|
||||
* @todo $date should return null if it doesn't exist.
|
||||
*
|
||||
* @property Horde_Mail_Rfc822_List $bcc Bcc address(es).
|
||||
* @property Horde_Mail_Rfc822_List $cc Cc address(es).
|
||||
* @property Horde_Imap_Client_DateTime $date Message date.
|
||||
* @property Horde_Mail_Rfc822_List $from From address(es).
|
||||
* @property string $in_reply_to Message-ID of the message replied to.
|
||||
* @property string $message_id Message-ID of the message.
|
||||
* @property Horde_Mail_Rfc822_List $reply_to Reply-to address(es).
|
||||
* @property Horde_Mail_Rfc822_List $sender Sender address.
|
||||
* @property string $subject Subject.
|
||||
* @property Horde_Mail_Rfc822_List $to To address(es).
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Envelope implements Serializable
|
||||
{
|
||||
/* Serializable version. */
|
||||
const VERSION = 3;
|
||||
|
||||
/**
|
||||
* Data object.
|
||||
*
|
||||
* @var Horde_Mime_Headers
|
||||
*/
|
||||
protected $_data;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @var array $data An array of property names (keys) and values to set
|
||||
* in this object.
|
||||
*/
|
||||
public function __construct(array $data = array())
|
||||
{
|
||||
$this->_data = new Horde_Mime_Headers();
|
||||
|
||||
foreach ($data as $key => $val) {
|
||||
$this->$key = $val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
$name = $this->_normalizeProperty($name);
|
||||
|
||||
switch ($name) {
|
||||
case 'bcc':
|
||||
case 'cc':
|
||||
case 'from':
|
||||
case 'reply-to':
|
||||
case 'sender':
|
||||
case 'to':
|
||||
if ($h = $this->_data[$name]) {
|
||||
return $h->getAddressList(true);
|
||||
}
|
||||
|
||||
if (in_array($name, array('sender', 'reply-to'))) {
|
||||
return $this->from;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'date':
|
||||
if ($val = $this->_data['date']) {
|
||||
return new Horde_Imap_Client_DateTime($val->value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'in-reply-to':
|
||||
case 'message-id':
|
||||
case 'subject':
|
||||
if ($val = $this->_data[$name]) {
|
||||
return $val->value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Default values.
|
||||
switch ($name) {
|
||||
case 'bcc':
|
||||
case 'cc':
|
||||
case 'from':
|
||||
case 'to':
|
||||
return new Horde_Mail_Rfc822_List();
|
||||
|
||||
case 'date':
|
||||
return new Horde_Imap_Client_DateTime();
|
||||
|
||||
case 'in-reply-to':
|
||||
case 'message-id':
|
||||
case 'subject':
|
||||
return '';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if (!strlen($value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$name = $this->_normalizeProperty($name);
|
||||
|
||||
switch ($name) {
|
||||
case 'bcc':
|
||||
case 'cc':
|
||||
case 'date':
|
||||
case 'from':
|
||||
case 'in-reply-to':
|
||||
case 'message-id':
|
||||
case 'reply-to':
|
||||
case 'sender':
|
||||
case 'subject':
|
||||
case 'to':
|
||||
switch ($name) {
|
||||
case 'from':
|
||||
if ($this->reply_to->match($value)) {
|
||||
unset($this->_data['reply-to']);
|
||||
}
|
||||
if ($this->sender->match($value)) {
|
||||
unset($this->_data['sender']);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'reply-to':
|
||||
case 'sender':
|
||||
if ($this->from->match($value)) {
|
||||
unset($this->_data[$name]);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$this->_data->addHeader($name, $value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
$name = $this->_normalizeProperty($name);
|
||||
|
||||
switch ($name) {
|
||||
case 'reply-to':
|
||||
case 'sender':
|
||||
if (isset($this->_data[$name])) {
|
||||
return true;
|
||||
}
|
||||
$name = 'from';
|
||||
break;
|
||||
}
|
||||
|
||||
return isset($this->_data[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
protected function _normalizeProperty($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'in_reply_to':
|
||||
return 'in-reply-to';
|
||||
|
||||
case 'message_id':
|
||||
return 'message-id';
|
||||
|
||||
case 'reply_to':
|
||||
return 'reply-to';
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function unserialize($data)
|
||||
{
|
||||
$this->__unserialize(@unserialize($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return array(
|
||||
'd' => $this->_data,
|
||||
'v' => self::VERSION,
|
||||
);
|
||||
}
|
||||
|
||||
public function __unserialize(array $data)
|
||||
{
|
||||
if (empty($data['v']) || $data['v'] != self::VERSION) {
|
||||
throw new Exception('Cache version change');
|
||||
}
|
||||
|
||||
$this->_data = $data['d'];
|
||||
}
|
||||
|
||||
}
|
@ -1,666 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object containing data returned by the Horde_Imap_Client_Base#fetch()
|
||||
* command.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Fetch
|
||||
{
|
||||
/** Header formatting constants. */
|
||||
const HEADER_PARSE = 1;
|
||||
const HEADER_STREAM = 2;
|
||||
|
||||
/**
|
||||
* Internal data array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_data = array();
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$this->_data = unserialize(serialize($this->_data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the full message property.
|
||||
*
|
||||
* @param mixed $msg The full message text, as either a string or stream
|
||||
* resource.
|
||||
*/
|
||||
public function setFullMsg($msg)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_FULLMSG] = $this->_setMixed($msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full message.
|
||||
*
|
||||
* @param boolean $stream Return as a stream?
|
||||
*
|
||||
* @return mixed The full text of the entire message.
|
||||
*/
|
||||
public function getFullMsg($stream = false)
|
||||
{
|
||||
return $this->_msgText(
|
||||
$stream,
|
||||
isset($this->_data[Horde_Imap_Client::FETCH_FULLMSG])
|
||||
? $this->_data[Horde_Imap_Client::FETCH_FULLMSG]
|
||||
: null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the message structure.
|
||||
*
|
||||
* @param Horde_Mime_Part $structure The base MIME part of the message.
|
||||
*/
|
||||
public function setStructure(Horde_Mime_Part $structure)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_STRUCTURE] = $structure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message structure.
|
||||
*
|
||||
* @return Horde_Mime_Part $structure The base MIME part of the message.
|
||||
*/
|
||||
public function getStructure()
|
||||
{
|
||||
return isset($this->_data[Horde_Imap_Client::FETCH_STRUCTURE])
|
||||
? clone $this->_data[Horde_Imap_Client::FETCH_STRUCTURE]
|
||||
: new Horde_Mime_Part();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a header entry.
|
||||
*
|
||||
* @param string $label The search label.
|
||||
* @param mixed $data Either a Horde_Mime_Headers object or the raw
|
||||
* header text.
|
||||
*/
|
||||
public function setHeaders($label, $data)
|
||||
{
|
||||
if ($data instanceof Horde_Stream) {
|
||||
$data = $data->stream;
|
||||
}
|
||||
$this->_data[Horde_Imap_Client::FETCH_HEADERS][$label] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a header entry.
|
||||
*
|
||||
* @param string $label The search label.
|
||||
* @param integer $format The return format. If self::HEADER_PARSE,
|
||||
* returns a Horde_Mime_Headers object. If
|
||||
* self::HEADER_STREAM, returns a stream.
|
||||
* Otherwise, returns header text.
|
||||
*
|
||||
* @return mixed See $format.
|
||||
*/
|
||||
public function getHeaders($label, $format = 0)
|
||||
{
|
||||
return $this->_getHeaders(
|
||||
$label,
|
||||
$format,
|
||||
Horde_Imap_Client::FETCH_HEADERS
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a header text entry.
|
||||
*
|
||||
* @param string $id The MIME ID.
|
||||
* @param mixed $text The header text, as either a string or stream
|
||||
* resource.
|
||||
*/
|
||||
public function setHeaderText($id, $text)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_HEADERTEXT][$id] = $this->_setMixed($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a header text entry.
|
||||
*
|
||||
* @param string $id The MIME ID.
|
||||
* @param integer $format The return format. If self::HEADER_PARSE,
|
||||
* returns a Horde_Mime_Headers object. If
|
||||
* self::HEADER_STREAM, returns a stream.
|
||||
* Otherwise, returns header text.
|
||||
*
|
||||
* @return mixed See $format.
|
||||
*/
|
||||
public function getHeaderText($id = 0, $format = 0)
|
||||
{
|
||||
return $this->_getHeaders(
|
||||
$id,
|
||||
$format,
|
||||
Horde_Imap_Client::FETCH_HEADERTEXT
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a MIME header entry.
|
||||
*
|
||||
* @param string $id The MIME ID.
|
||||
* @param mixed $text The header text, as either a string or stream
|
||||
* resource.
|
||||
*/
|
||||
public function setMimeHeader($id, $text)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_MIMEHEADER][$id] = $this->_setMixed($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a MIME header entry.
|
||||
*
|
||||
* @param string $id The MIME ID.
|
||||
* @param integer $format The return format. If self::HEADER_PARSE,
|
||||
* returns a Horde_Mime_Headers object. If
|
||||
* self::HEADER_STREAM, returns a stream.
|
||||
* Otherwise, returns header text.
|
||||
*
|
||||
* @return mixed See $format.
|
||||
*/
|
||||
public function getMimeHeader($id, $format = 0)
|
||||
{
|
||||
return $this->_getHeaders(
|
||||
$id,
|
||||
$format,
|
||||
Horde_Imap_Client::FETCH_MIMEHEADER
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a body part entry.
|
||||
*
|
||||
* @param string $id The MIME ID.
|
||||
* @param mixed $text The body part text, as either a string or stream
|
||||
* resource.
|
||||
* @param string $decode Either '8bit', 'binary', or null.
|
||||
*/
|
||||
public function setBodyPart($id, $text, $decode = null)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_BODYPART][$id] = array(
|
||||
'd' => $decode,
|
||||
't' => $this->_setMixed($text)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a body part entry.
|
||||
*
|
||||
* @param string $id The MIME ID.
|
||||
* @param boolean $stream Return as a stream?
|
||||
*
|
||||
* @return mixed The full text of the body part.
|
||||
*/
|
||||
public function getBodyPart($id, $stream = false)
|
||||
{
|
||||
return $this->_msgText(
|
||||
$stream,
|
||||
isset($this->_data[Horde_Imap_Client::FETCH_BODYPART][$id])
|
||||
? $this->_data[Horde_Imap_Client::FETCH_BODYPART][$id]['t']
|
||||
: null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if/how a body part was MIME decoded on the server.
|
||||
*
|
||||
* @param string $id The MIME ID.
|
||||
*
|
||||
* @return string Either '8bit', 'binary', or null.
|
||||
*/
|
||||
public function getBodyPartDecode($id)
|
||||
{
|
||||
return isset($this->_data[Horde_Imap_Client::FETCH_BODYPART][$id])
|
||||
? $this->_data[Horde_Imap_Client::FETCH_BODYPART][$id]['d']
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the body part size for a body part.
|
||||
*
|
||||
* @param string $id The MIME ID.
|
||||
* @param integer $size The size (in bytes).
|
||||
*/
|
||||
public function setBodyPartSize($id, $size)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id] = intval($size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the body part size, if returned by the server.
|
||||
*
|
||||
* @param string $id The MIME ID.
|
||||
*
|
||||
* @return integer The body part size, in bytes.
|
||||
*/
|
||||
public function getBodyPartSize($id)
|
||||
{
|
||||
return isset($this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id])
|
||||
? $this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a body text entry.
|
||||
*
|
||||
* @param string $id The MIME ID.
|
||||
* @param mixed $text The body part text, as either a string or stream
|
||||
* resource.
|
||||
*/
|
||||
public function setBodyText($id, $text)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id] = $this->_setMixed($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a body text entry.
|
||||
*
|
||||
* @param string $id The MIME ID.
|
||||
* @param boolean $stream Return as a stream?
|
||||
*
|
||||
* @return mixed The full text of the body text.
|
||||
*/
|
||||
public function getBodyText($id = 0, $stream = false)
|
||||
{
|
||||
return $this->_msgText(
|
||||
$stream,
|
||||
isset($this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id])
|
||||
? $this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id]
|
||||
: null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set envelope data.
|
||||
*
|
||||
* @param array $data The envelope data to pass to the Envelope object
|
||||
* constructor, or an Envelope object.
|
||||
*/
|
||||
public function setEnvelope($data)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_ENVELOPE] = is_array($data)
|
||||
? new Horde_Imap_Client_Data_Envelope($data)
|
||||
: $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get envelope data.
|
||||
*
|
||||
* @return Horde_Imap_Client_Data_Envelope An envelope object.
|
||||
*/
|
||||
public function getEnvelope()
|
||||
{
|
||||
return isset($this->_data[Horde_Imap_Client::FETCH_ENVELOPE])
|
||||
? clone $this->_data[Horde_Imap_Client::FETCH_ENVELOPE]
|
||||
: new Horde_Imap_Client_Data_Envelope();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set IMAP flags.
|
||||
*
|
||||
* @param array $flags An array of IMAP flags.
|
||||
*/
|
||||
public function setFlags(array $flags)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_FLAGS] = array_map(
|
||||
'Horde_String::lower',
|
||||
array_map('trim', $flags)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IMAP flags.
|
||||
*
|
||||
* @return array An array of IMAP flags (all flags in lowercase).
|
||||
*/
|
||||
public function getFlags()
|
||||
{
|
||||
return isset($this->_data[Horde_Imap_Client::FETCH_FLAGS])
|
||||
? $this->_data[Horde_Imap_Client::FETCH_FLAGS]
|
||||
: array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set IMAP internal date.
|
||||
*
|
||||
* @param mixed $date Either a Horde_Imap_Client_DateTime object or a
|
||||
* date string.
|
||||
*/
|
||||
public function setImapDate($date)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_IMAPDATE] = is_object($date)
|
||||
? $date
|
||||
: new Horde_Imap_Client_DateTime($date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get internal IMAP date.
|
||||
*
|
||||
* @return Horde_Imap_Client_DateTime A date object.
|
||||
*/
|
||||
public function getImapDate()
|
||||
{
|
||||
return isset($this->_data[Horde_Imap_Client::FETCH_IMAPDATE])
|
||||
? clone $this->_data[Horde_Imap_Client::FETCH_IMAPDATE]
|
||||
: new Horde_Imap_Client_DateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set message size.
|
||||
*
|
||||
* @param integer $size The size of the message, in bytes.
|
||||
*/
|
||||
public function setSize($size)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_SIZE] = intval($size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get message size.
|
||||
*
|
||||
* @return integer The size of the message, in bytes.
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
return isset($this->_data[Horde_Imap_Client::FETCH_SIZE])
|
||||
? $this->_data[Horde_Imap_Client::FETCH_SIZE]
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set UID.
|
||||
*
|
||||
* @param integer $uid The message UID.
|
||||
*/
|
||||
public function setUid($uid)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_UID] = intval($uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get UID.
|
||||
*
|
||||
* @return integer The message UID.
|
||||
*/
|
||||
public function getUid()
|
||||
{
|
||||
return isset($this->_data[Horde_Imap_Client::FETCH_UID])
|
||||
? $this->_data[Horde_Imap_Client::FETCH_UID]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set message sequence number.
|
||||
*
|
||||
* @param integer $seq The message sequence number.
|
||||
*/
|
||||
public function setSeq($seq)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_SEQ] = intval($seq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get message sequence number.
|
||||
*
|
||||
* @return integer The message sequence number.
|
||||
*/
|
||||
public function getSeq()
|
||||
{
|
||||
return isset($this->_data[Horde_Imap_Client::FETCH_SEQ])
|
||||
? $this->_data[Horde_Imap_Client::FETCH_SEQ]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the modified sequence value for the message.
|
||||
*
|
||||
* @param integer $modseq The modseq value.
|
||||
*/
|
||||
public function setModSeq($modseq)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_MODSEQ] = intval($modseq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the modified sequence value for the message.
|
||||
*
|
||||
* @return integer The modseq value.
|
||||
*/
|
||||
public function getModSeq()
|
||||
{
|
||||
return isset($this->_data[Horde_Imap_Client::FETCH_MODSEQ])
|
||||
? $this->_data[Horde_Imap_Client::FETCH_MODSEQ]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the internationalized downgraded status for the message.
|
||||
*
|
||||
* @since 2.11.0
|
||||
*
|
||||
* @param boolean $downgraded True if at least one message component has
|
||||
* been downgraded.
|
||||
*/
|
||||
public function setDowngraded($downgraded)
|
||||
{
|
||||
if ($downgraded) {
|
||||
$this->_data[Horde_Imap_Client::FETCH_DOWNGRADED] = true;
|
||||
} else {
|
||||
unset($this->_data[Horde_Imap_Client::FETCH_DOWNGRADED]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the message contain internationalized downgraded data (i.e. it
|
||||
* is a "surrogate" message)?
|
||||
*
|
||||
* @since 2.11.0
|
||||
*
|
||||
* @return boolean True if at least one message components has been
|
||||
* downgraded.
|
||||
*/
|
||||
public function isDowngraded()
|
||||
{
|
||||
return !empty($this->_data[Horde_Imap_Client::FETCH_DOWNGRADED]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the internal representation of the data.
|
||||
*
|
||||
* @return array The data array.
|
||||
*/
|
||||
public function getRawData()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge a fetch object into this one.
|
||||
*
|
||||
* @param Horde_Imap_Client_Data_Fetch $data A fetch object.
|
||||
*/
|
||||
public function merge(Horde_Imap_Client_Data_Fetch $data)
|
||||
{
|
||||
$this->_data = array_replace_recursive(
|
||||
$this->_data,
|
||||
$data->getRawData()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this object containing cacheable data of the given type?
|
||||
*
|
||||
* @param integer $type The type to query.
|
||||
*
|
||||
* @return boolean True if the type is cacheable.
|
||||
*/
|
||||
public function exists($type)
|
||||
{
|
||||
return isset($this->_data[$type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this object contain only default values for all fields?
|
||||
*
|
||||
* @return boolean True if object contains default data.
|
||||
*/
|
||||
public function isDefault()
|
||||
{
|
||||
return empty($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return text representation of a field.
|
||||
*
|
||||
* @param boolean $stream Return as a stream?
|
||||
* @param mixed $data The field data (string or resource) or null if
|
||||
* field does not exist.
|
||||
*
|
||||
* @return mixed Requested text representation.
|
||||
*/
|
||||
protected function _msgText($stream, $data)
|
||||
{
|
||||
if ($data instanceof Horde_Stream) {
|
||||
if ($stream) {
|
||||
$data->rewind();
|
||||
return $data->stream;
|
||||
}
|
||||
return strval($data);
|
||||
}
|
||||
|
||||
if (is_resource($data)) {
|
||||
rewind($data);
|
||||
return $stream
|
||||
? $data
|
||||
: stream_get_contents($data);
|
||||
}
|
||||
|
||||
if (!$stream) {
|
||||
return strval($data);
|
||||
}
|
||||
|
||||
$tmp = fopen('php://temp', 'w+');
|
||||
|
||||
if (!is_null($data)) {
|
||||
fwrite($tmp, $data);
|
||||
rewind($tmp);
|
||||
}
|
||||
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return representation of a header field.
|
||||
*
|
||||
* @param string $id The header id.
|
||||
* @param integer $format The return format. If self::HEADER_PARSE,
|
||||
* returns a Horde_Mime_Headers object. If
|
||||
* self::HEADER_STREAM, returns a stream.
|
||||
* Otherwise, returns header text.
|
||||
* @param integer $key The array key where the data is stored in the
|
||||
* internal array.
|
||||
*
|
||||
* @return mixed The data in the format specified by $format.
|
||||
*/
|
||||
protected function _getHeaders($id, $format, $key)
|
||||
{
|
||||
switch ($format) {
|
||||
case self::HEADER_STREAM:
|
||||
if (!isset($this->_data[$key][$id])) {
|
||||
$data = null;
|
||||
} elseif (is_object($this->_data[$key][$id])) {
|
||||
switch ($key) {
|
||||
case Horde_Imap_Client::FETCH_HEADERS:
|
||||
$data = $this->_getHeaders($id, 0, $key);
|
||||
break;
|
||||
|
||||
case Horde_Imap_Client::FETCH_HEADERTEXT:
|
||||
case Horde_Imap_Client::FETCH_MIMEHEADER:
|
||||
$data = $this->_data[$key][$id];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$data = $this->_data[$key][$id];
|
||||
}
|
||||
|
||||
return $this->_msgText(true, $data);
|
||||
|
||||
case self::HEADER_PARSE:
|
||||
if (!isset($this->_data[$key][$id])) {
|
||||
return new Horde_Mime_Headers();
|
||||
} elseif (is_object($this->_data[$key][$id])) {
|
||||
switch ($key) {
|
||||
case Horde_Imap_Client::FETCH_HEADERS:
|
||||
return clone $this->_data[$key][$id];
|
||||
|
||||
case Horde_Imap_Client::FETCH_HEADERTEXT:
|
||||
case Horde_Imap_Client::FETCH_MIMEHEADER:
|
||||
return Horde_Mime_Headers::parseHeaders($this->_data[$key][$id]);
|
||||
}
|
||||
} else {
|
||||
$hdrs = $this->_getHeaders($id, self::HEADER_STREAM, $key);
|
||||
$parsed = Horde_Mime_Headers::parseHeaders($hdrs);
|
||||
fclose($hdrs);
|
||||
return $parsed;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($this->_data[$key][$id])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (is_object($this->_data[$key][$id])) {
|
||||
switch ($key) {
|
||||
case Horde_Imap_Client::FETCH_HEADERS:
|
||||
return $this->_data[$key][$id]->toString(
|
||||
array('nowrap' => true)
|
||||
);
|
||||
|
||||
case Horde_Imap_Client::FETCH_HEADERTEXT:
|
||||
case Horde_Imap_Client::FETCH_MIMEHEADER:
|
||||
return strval($this->_data[$key][$id]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_msgText(false, $this->_data[$key][$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts mixed input (string or resource) to the correct internal
|
||||
* representation.
|
||||
*
|
||||
* @param mixed $data Mixed data (string, resource, Horde_Stream object).
|
||||
*
|
||||
* @return mixed The internal representation of that data.
|
||||
*/
|
||||
protected function _setMixed($data)
|
||||
{
|
||||
return is_resource($data)
|
||||
? new Horde_Stream_Existing(array('stream' => $data))
|
||||
: $data;
|
||||
}
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object containg POP3 fetch data.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Fetch_Pop3 extends Horde_Imap_Client_Data_Fetch
|
||||
{
|
||||
/**
|
||||
* Set UID.
|
||||
*
|
||||
* @param string $uid The message UID. Unlike IMAP, this UID does not
|
||||
* have to be an integer.
|
||||
*/
|
||||
public function setUid($uid)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_UID] = strval($uid);
|
||||
}
|
||||
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP data format (RFC 3501 [4]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format
|
||||
{
|
||||
/**
|
||||
* Data.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $_data;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $data Data.
|
||||
*/
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->_data = is_resource($data)
|
||||
? stream_get_contents($data, -1, 0)
|
||||
: $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string value of the raw data.
|
||||
*
|
||||
* @return string String value.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return strval($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data.
|
||||
*
|
||||
* @return mixed Raw data.
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data formatted for output to the IMAP server.
|
||||
*
|
||||
* @return string IMAP escaped string.
|
||||
*/
|
||||
public function escape()
|
||||
{
|
||||
return strval($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the data.
|
||||
*
|
||||
* @throws Horde_Imap_Client_Data_Format_Exception
|
||||
*/
|
||||
public function verify()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP astring (atom or string) (RFC 3501 [4.3]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Astring extends Horde_Imap_Client_Data_Format_String
|
||||
{
|
||||
/**
|
||||
*/
|
||||
public function quoted()
|
||||
{
|
||||
return $this->_filter->quoted || !$this->_data->length();
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Extend astring element to allow for non-ASCII characters.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.25.0
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Astring_Nonascii
|
||||
extends Horde_Imap_Client_Data_Format_Astring
|
||||
implements Horde_Imap_Client_Data_Format_String_Support_Nonascii
|
||||
{
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP atom (RFC 3501 [4.1]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Atom extends Horde_Imap_Client_Data_Format
|
||||
{
|
||||
/**
|
||||
*/
|
||||
public function escape()
|
||||
{
|
||||
return strlen($this->_data)
|
||||
? parent::escape()
|
||||
: '""';
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function verify()
|
||||
{
|
||||
if (strlen($this->_data) !== strlen($this->stripNonAtomCharacters())) {
|
||||
throw new Horde_Imap_Client_Data_Format_Exception('Illegal character in IMAP atom.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip out any characters that are not allowed in an IMAP atom.
|
||||
*
|
||||
* @return string The atom data disallowed characters removed.
|
||||
*/
|
||||
public function stripNonAtomCharacters()
|
||||
{
|
||||
return str_replace(
|
||||
array('(', ')', '{', ' ', '%', '*', '"', '\\', ']'),
|
||||
'',
|
||||
preg_replace('/[^\x20-\x7e]/', '', $this->_data)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP date string (RFC 3501 [9]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Date extends Horde_Imap_Client_Data_Format
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $data Either a DateTime object, or a date format that
|
||||
* can be converted to a DateTime object.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($data)
|
||||
{
|
||||
if (!($data instanceof DateTime)) {
|
||||
$data = new Horde_Imap_Client_DateTime($data);
|
||||
}
|
||||
|
||||
parent::__construct($data);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->_data->format('j-M-Y');
|
||||
}
|
||||
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP date-time string (RFC 3501 [9]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_DateTime extends Horde_Imap_Client_Data_Format_Date
|
||||
{
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->_data->format('j-M-Y H:i:s O');
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function escape()
|
||||
{
|
||||
return '"' . strval($this) . '"';
|
||||
}
|
||||
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception object for IMAP data format errors.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Exception extends Horde_Exception_Wrapped
|
||||
{
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stream filter to output a quoted IMAP string.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Filter_Quote extends php_user_filter
|
||||
{
|
||||
/**
|
||||
* Has the initial quote been prepended?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_prepend;
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function onCreate()
|
||||
{
|
||||
$this->_prepend = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see stream_filter_register()
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function filter($in, $out, &$consumed, $closing)
|
||||
{
|
||||
if (!$this->_prepend) {
|
||||
stream_bucket_append($out, stream_bucket_new($this->stream, '"'));
|
||||
$this->_prepend = true;
|
||||
}
|
||||
|
||||
while ($bucket = stream_bucket_make_writeable($in)) {
|
||||
$consumed += $bucket->datalen;
|
||||
$bucket->data = addcslashes($bucket->data, '"\\');
|
||||
stream_bucket_append($out, $bucket);
|
||||
}
|
||||
|
||||
/* feof() call needed due to:
|
||||
* http://news.php.net/php.internals/80363 */
|
||||
if ($closing || feof($this->stream)) {
|
||||
stream_bucket_append($out, stream_bucket_new($this->stream, '"'));
|
||||
}
|
||||
|
||||
return PSFS_PASS_ON;
|
||||
}
|
||||
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stream filter to analyze an IMAP string to determine how to send to the
|
||||
* server.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Filter_String extends php_user_filter
|
||||
{
|
||||
/**
|
||||
* Skip status.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_skip = false;
|
||||
|
||||
/**
|
||||
* @see stream_filter_register()
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function onCreate()
|
||||
{
|
||||
$this->params->binary = false;
|
||||
$this->params->literal = false;
|
||||
$this->params->nonascii = false;
|
||||
// no_quote_list is used below as a config option
|
||||
$this->params->quoted = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see stream_filter_register()
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function filter($in, $out, &$consumed, $closing)
|
||||
{
|
||||
$p = $this->params;
|
||||
|
||||
while ($bucket = stream_bucket_make_writeable($in)) {
|
||||
if (!$this->_skip) {
|
||||
$len = $bucket->datalen;
|
||||
$str = $bucket->data;
|
||||
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
$chr = ord($str[$i]);
|
||||
|
||||
switch ($chr) {
|
||||
case 0: // null
|
||||
$p->binary = true;
|
||||
$p->literal = true;
|
||||
|
||||
// No need to scan input anymore.
|
||||
$this->_skip = true;
|
||||
break 2;
|
||||
|
||||
case 10: // LF
|
||||
case 13: // CR
|
||||
$p->literal = true;
|
||||
break;
|
||||
|
||||
case 32: // SPACE
|
||||
case 34: // "
|
||||
case 40: // (
|
||||
case 41: // )
|
||||
case 92: // \
|
||||
case 123: // {
|
||||
case 127: // DEL
|
||||
// These are all invalid ATOM characters.
|
||||
$p->quoted = true;
|
||||
break;
|
||||
|
||||
case 37: // %
|
||||
case 42: // *
|
||||
// These are not quoted if being used as wildcards.
|
||||
if (empty($p->no_quote_list)) {
|
||||
$p->quoted = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if ($chr < 32) {
|
||||
// CTL characters must be, at a minimum, quoted.
|
||||
$p->quoted = true;
|
||||
} elseif ($chr > 127) {
|
||||
$p->nonascii = true;
|
||||
// 8-bit chars must be in a literal.
|
||||
$p->literal = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$consumed += $bucket->datalen;
|
||||
stream_bucket_append($out, $bucket);
|
||||
}
|
||||
|
||||
if ($p->literal) {
|
||||
$p->quoted = false;
|
||||
}
|
||||
|
||||
return PSFS_PASS_ON;
|
||||
}
|
||||
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP parenthesized list (RFC 3501 [4.4]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_List extends Horde_Imap_Client_Data_Format implements Countable, IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @see add()
|
||||
*/
|
||||
public function __construct($data = null)
|
||||
{
|
||||
parent::__construct(array());
|
||||
|
||||
if (!is_null($data)) {
|
||||
$this->add($data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an element to the list.
|
||||
*
|
||||
* @param mixed $data The data element(s) to add. Either a
|
||||
* Horde_Imap_Client_Data_Format object, a string
|
||||
* value that will be treated as an IMAP atom, or
|
||||
* an array (or iterable object) of objects to add.
|
||||
* @param boolean $merge Merge the contents of any container objects,
|
||||
* instead of adding the objects themselves?
|
||||
*
|
||||
* @return Horde_Imap_Client_Data_Format_List This object to allow for
|
||||
* chainable calls (since
|
||||
* 2.10.0).
|
||||
*/
|
||||
public function add($data, $merge = false)
|
||||
{
|
||||
if (is_array($data) || ($merge && ($data instanceof Traversable))) {
|
||||
foreach ($data as $val) {
|
||||
$this->add($val);
|
||||
}
|
||||
} elseif (is_object($data)) {
|
||||
$this->_data[] = $data;
|
||||
} elseif (!is_null($data)) {
|
||||
$this->_data[] = new Horde_Imap_Client_Data_Format_Atom($data);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$out = '';
|
||||
|
||||
foreach ($this as $val) {
|
||||
if ($val instanceof $this) {
|
||||
$out .= '(' . $val->escape() . ') ';
|
||||
} elseif (($val instanceof Horde_Imap_Client_Data_Format_String) &&
|
||||
$val->literal()) {
|
||||
/* ERROR: Requires literal output. */
|
||||
return '';
|
||||
} else {
|
||||
$out .= $val->escape() . ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return rtrim($out);
|
||||
}
|
||||
|
||||
/* Countable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return count($this->_data);
|
||||
}
|
||||
|
||||
/* IteratorAggregate method. */
|
||||
|
||||
/**
|
||||
* Iterator loops through the data elements contained in this list.
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->_data);
|
||||
}
|
||||
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP mailbox string used in a LIST command.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_ListMailbox
|
||||
extends Horde_Imap_Client_Data_Format_Mailbox
|
||||
{
|
||||
/**
|
||||
*/
|
||||
protected function _filterParams()
|
||||
{
|
||||
$ob = parent::_filterParams();
|
||||
|
||||
/* Don't quote % or * characters. */
|
||||
$ob->no_quote_list = true;
|
||||
|
||||
return $ob;
|
||||
}
|
||||
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP mailbox string used in a LIST command
|
||||
* when UTF8=ACCEPT is supported/enabled on the server (RFC 6855 [3]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_ListMailbox_Utf8
|
||||
extends Horde_Imap_Client_Data_Format_Mailbox_Utf8
|
||||
{
|
||||
/**
|
||||
*/
|
||||
protected function _filterParams()
|
||||
{
|
||||
$ob = parent::_filterParams();
|
||||
|
||||
/* Don't quote % or * characters. */
|
||||
$ob->no_quote_list = true;
|
||||
|
||||
return $ob;
|
||||
}
|
||||
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP mailbox string (RFC 3501 [9]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Mailbox
|
||||
extends Horde_Imap_Client_Data_Format_Astring
|
||||
{
|
||||
/**
|
||||
* Mailbox encoding.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_encoding = 'utf7imap';
|
||||
|
||||
/**
|
||||
* Mailbox object.
|
||||
*
|
||||
* @var Horde_Imap_Client_Mailbox
|
||||
*/
|
||||
protected $_mailbox;
|
||||
|
||||
/**
|
||||
* @param mixed $data Either a mailbox object or a UTF-8 mailbox name.
|
||||
*/
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->_mailbox = Horde_Imap_Client_Mailbox::get($data);
|
||||
|
||||
parent::__construct($this->_mailbox->{$this->_encoding});
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return strval($this->_mailbox);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->_mailbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Horde_Imap_Client_Exception
|
||||
*/
|
||||
public function binary()
|
||||
{
|
||||
if (parent::binary()) {
|
||||
// Mailbox data can NEVER be sent as binary.
|
||||
/* @todo: Disable until Horde_Imap_Client 3.0 */
|
||||
// throw new Horde_Imap_Client_Exception(
|
||||
// 'Client error: can not send mailbox to IMAP server as binary data.'
|
||||
// );
|
||||
|
||||
// Temporary fix: send a blank mailbox string.
|
||||
$this->_mailbox = Horde_Imap_Client_Mailbox::get('');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function length()
|
||||
{
|
||||
return strlen($this->_mailbox->{$this->_encoding});
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
$stream = new Horde_Stream_Temp();
|
||||
$stream->add($this->_mailbox->{$this->_encoding});
|
||||
return $stream;
|
||||
}
|
||||
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP mailbox string allowed when UTF8=ACCEPT
|
||||
* is supported/enabled on the server (RFC 6855 [3]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Mailbox_Utf8
|
||||
extends Horde_Imap_Client_Data_Format_Mailbox
|
||||
implements Horde_Imap_Client_Data_Format_String_Support_Nonascii
|
||||
{
|
||||
/**
|
||||
*/
|
||||
protected $_encoding = 'utf8';
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __construct($data)
|
||||
{
|
||||
parent::__construct($data);
|
||||
|
||||
/* RFC 3501 allows any US-ASCII character, except null (\0), in
|
||||
* mailbox data.
|
||||
* RFC 6855 [3] institutes additional limitations on valid mailbox
|
||||
* characters, to comply with RFC 5198 [2] (Net-Unicode Definition):
|
||||
* "MUST NOT contain control characters (U+0000-U+001F and
|
||||
* U+0080-U+009F), a delete character (U+007F), a line separator
|
||||
* (U+2028), or a paragraph separator (U+2029)." */
|
||||
if ($this->quoted() &&
|
||||
preg_match('/[\x00-\x1f\x7f\x80-\x9f\x{2028}\x{2029}]/u', strval($this))) {
|
||||
throw new Horde_Imap_Client_Data_Format_Exception(
|
||||
'Invalid character found in mailbox data.'
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->literal()) {
|
||||
$this->forceQuoted();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP NIL (RFC 3501 [4.5]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Nil extends Horde_Imap_Client_Data_Format
|
||||
{
|
||||
/**
|
||||
*/
|
||||
public function __construct($data = null)
|
||||
{
|
||||
// Don't store any data in object.
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function escape()
|
||||
{
|
||||
return 'NIL';
|
||||
}
|
||||
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP nstring (NIL or string) (RFC 3501 [4.5]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Nstring extends Horde_Imap_Client_Data_Format_String
|
||||
{
|
||||
/**
|
||||
*/
|
||||
public function __construct($data = null)
|
||||
{
|
||||
/* Data can be null (NIL) here. */
|
||||
if (is_null($data)) {
|
||||
$this->_data = null;
|
||||
} else {
|
||||
parent::__construct($data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return is_null($this->_data)
|
||||
? ''
|
||||
: parent::__toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function escape()
|
||||
{
|
||||
return is_null($this->_data)
|
||||
? 'NIL'
|
||||
: parent::escape();
|
||||
}
|
||||
|
||||
public function escapeStream()
|
||||
{
|
||||
if (is_null($this->_data)) {
|
||||
$stream = new Horde_Stream_Temp();
|
||||
$stream->add('NIL', true);
|
||||
return $stream->stream;
|
||||
}
|
||||
|
||||
return parent::escapeStream();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function quoted()
|
||||
{
|
||||
return is_null($this->_data)
|
||||
? false
|
||||
: parent::quoted();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function length()
|
||||
{
|
||||
return is_null($this->_data)
|
||||
? 0
|
||||
: parent::length();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
return is_null($this->_data)
|
||||
? new Horde_Stream_Temp()
|
||||
: parent::getStream();
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Extend nstring element to allow for non-ASCII characters.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.25.0
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Nstring_Nonascii
|
||||
extends Horde_Imap_Client_Data_Format_Nstring
|
||||
implements Horde_Imap_Client_Data_Format_String_Support_Nonascii
|
||||
{
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP number (RFC 3501 [4.2]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_Number extends Horde_Imap_Client_Data_Format
|
||||
{
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return strval(intval($this->_data));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function verify()
|
||||
{
|
||||
if (!is_numeric($this->_data)) {
|
||||
throw new Horde_Imap_Client_Data_Format_Exception('Illegal character in IMAP number.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,219 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representation of an IMAP string (RFC 3501 [4.3]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_String
|
||||
extends Horde_Imap_Client_Data_Format
|
||||
{
|
||||
/**
|
||||
* String filter parameters.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_filter;
|
||||
|
||||
/**
|
||||
* @param array $opts Additional options:
|
||||
* - eol: (boolean) If true, normalize EOLs in input. @since 2.2.0
|
||||
* - skipscan: (boolean) If true, don't scan input for
|
||||
* binary/literal/quoted data. @since 2.2.0
|
||||
*
|
||||
* @throws Horde_Imap_Client_Data_Format_Exception
|
||||
*/
|
||||
public function __construct($data, array $opts = array())
|
||||
{
|
||||
/* String data is stored in a stream. */
|
||||
$this->_data = new Horde_Stream_Temp();
|
||||
|
||||
if (empty($opts['skipscan'])) {
|
||||
$this->_filter = $this->_filterParams();
|
||||
stream_filter_register('horde_imap_client_string', 'Horde_Imap_Client_Data_Format_Filter_String');
|
||||
$res = stream_filter_append($this->_data->stream, 'horde_imap_client_string', STREAM_FILTER_WRITE, $this->_filter);
|
||||
} else {
|
||||
$res = null;
|
||||
}
|
||||
|
||||
if (empty($opts['eol'])) {
|
||||
$res2 = null;
|
||||
} else {
|
||||
stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol');
|
||||
$res2 = stream_filter_append($this->_data->stream, 'horde_eol', STREAM_FILTER_WRITE);
|
||||
}
|
||||
|
||||
$this->_data->add($data);
|
||||
|
||||
if (!is_null($res)) {
|
||||
stream_filter_remove($res);
|
||||
}
|
||||
if (!is_null($res2)) {
|
||||
stream_filter_remove($res2);
|
||||
}
|
||||
|
||||
if (isset($this->_filter) &&
|
||||
$this->_filter->nonascii &&
|
||||
!($this instanceof Horde_Imap_Client_Data_Format_String_Support_Nonascii)) {
|
||||
throw new Horde_Imap_Client_Data_Format_Exception(
|
||||
'String contains non-ASCII characters.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base string filter parameters.
|
||||
*
|
||||
* @return object Filter parameters.
|
||||
*/
|
||||
protected function _filterParams()
|
||||
{
|
||||
return new stdClass;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->_data->getString(0);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function escape()
|
||||
{
|
||||
if ($this->literal()) {
|
||||
throw new Horde_Imap_Client_Data_Format_Exception('String requires literal to output.');
|
||||
}
|
||||
|
||||
return $this->quoted()
|
||||
? stream_get_contents($this->escapeStream())
|
||||
: $this->_data->getString(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the escaped string as a stream.
|
||||
*
|
||||
* @return resource The IMAP escaped stream.
|
||||
*/
|
||||
public function escapeStream()
|
||||
{
|
||||
if ($this->literal()) {
|
||||
throw new Horde_Imap_Client_Data_Format_Exception('String requires literal to output.');
|
||||
}
|
||||
|
||||
rewind($this->_data->stream);
|
||||
|
||||
$stream = new Horde_Stream_Temp();
|
||||
$stream->add($this->_data, true);
|
||||
|
||||
stream_filter_register('horde_imap_client_string_quote', 'Horde_Imap_Client_Data_Format_Filter_Quote');
|
||||
stream_filter_append($stream->stream, 'horde_imap_client_string_quote', STREAM_FILTER_READ);
|
||||
|
||||
return $stream->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this data item require quoted string output?
|
||||
*
|
||||
* @return boolean True if quoted output is required.
|
||||
*/
|
||||
public function quoted()
|
||||
{
|
||||
/* IMAP strings MUST be quoted if they are not a literal. */
|
||||
return (!isset($this->_filter) || !$this->_filter->literal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force item to be output quoted.
|
||||
*/
|
||||
public function forceQuoted()
|
||||
{
|
||||
$this->_filter = $this->_filterParams();
|
||||
$this->_filter->binary = false;
|
||||
$this->_filter->literal = false;
|
||||
$this->_filter->quoted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this data item require literal string output?
|
||||
*
|
||||
* @return boolean True if literal output is required.
|
||||
*/
|
||||
public function literal()
|
||||
{
|
||||
return (isset($this->_filter) && $this->_filter->literal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force item to be output as a literal.
|
||||
*/
|
||||
public function forceLiteral()
|
||||
{
|
||||
$this->_filter = $this->_filterParams();
|
||||
// Keep binary status, if set
|
||||
$this->_filter->literal = true;
|
||||
$this->_filter->quoted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If literal output, is the data binary?
|
||||
*
|
||||
* @return boolean True if the literal output is binary.
|
||||
*/
|
||||
public function binary()
|
||||
{
|
||||
return (isset($this->_filter) && !empty($this->_filter->binary));
|
||||
}
|
||||
|
||||
/**
|
||||
* Force item to be output as a binary literal.
|
||||
*/
|
||||
public function forceBinary()
|
||||
{
|
||||
$this->_filter = $this->_filterParams();
|
||||
$this->_filter->binary = true;
|
||||
$this->_filter->literal = true;
|
||||
$this->_filter->quoted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the data.
|
||||
*
|
||||
* @since 2.2.0
|
||||
*
|
||||
* @return integer Data length.
|
||||
*/
|
||||
public function length()
|
||||
{
|
||||
return $this->_data->length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the contents of the string as a stream object.
|
||||
*
|
||||
* @since 2.3.0
|
||||
*
|
||||
* @return Horde_Stream The stream object.
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Extend string element to allow for non-ASCII characters.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.25.0
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Format_String_Nonascii
|
||||
extends Horde_Imap_Client_Data_Format_String
|
||||
implements Horde_Imap_Client_Data_Format_String_Support_Nonascii
|
||||
{
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface a Horde_Imap_Client_Data_Format_String object should extend if
|
||||
* it supports non-ASCII output (RFC 3501 [4.3.1]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.25.0
|
||||
*/
|
||||
interface Horde_Imap_Client_Data_Format_String_Support_Nonascii
|
||||
{
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2013-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Namespace data.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.21.0
|
||||
*
|
||||
* @property-read string $base The namespace base ($name without trailing
|
||||
* delimiter) (UTF-8).
|
||||
* @property string $delimiter The namespace delimiter.
|
||||
* @property boolean $hidden Is this a hidden namespace?
|
||||
* @property string $name The namespace name (UTF-8).
|
||||
* @property string $translation Returns the translated name of the namespace
|
||||
* (UTF-8).
|
||||
* @property integer $type The namespace type. Either self::NS_PERSONAL,
|
||||
* self::NS_OTHER, or self::NS_SHARED.
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Namespace implements Serializable
|
||||
{
|
||||
/* Namespace type constants. */
|
||||
const NS_PERSONAL = 1;
|
||||
const NS_OTHER = 2;
|
||||
const NS_SHARED = 3;
|
||||
|
||||
/**
|
||||
* Data object.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_data = array();
|
||||
|
||||
/**
|
||||
* Strips namespace information from the given mailbox name.
|
||||
*
|
||||
* @param string $mbox Mailbox name.
|
||||
*
|
||||
* @return string Mailbox name with namespace prefix stripped.
|
||||
*/
|
||||
public function stripNamespace($mbox)
|
||||
{
|
||||
$mbox = strval($mbox);
|
||||
$name = $this->name;
|
||||
|
||||
return (strlen($name) && (strpos($mbox, $name) === 0))
|
||||
? substr($mbox, strlen($name))
|
||||
: $mbox;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if (isset($this->_data[$name])) {
|
||||
return $this->_data[$name];
|
||||
}
|
||||
|
||||
switch ($name) {
|
||||
case 'base':
|
||||
return rtrim($this->name, $this->delimiter);
|
||||
|
||||
case 'delimiter':
|
||||
case 'name':
|
||||
case 'translation':
|
||||
return '';
|
||||
|
||||
case 'hidden':
|
||||
return false;
|
||||
|
||||
case 'type':
|
||||
return self::NS_PERSONAL;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'delimiter':
|
||||
case 'name':
|
||||
case 'translation':
|
||||
$this->_data[$name] = strval($value);
|
||||
break;
|
||||
|
||||
case 'hidden':
|
||||
$this->_data[$name] = (bool)$value;
|
||||
break;
|
||||
|
||||
case 'type':
|
||||
$this->_data[$name] = intval($value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return isset($this->_data[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function unserialize($data)
|
||||
{
|
||||
$data = @unserialize($data);
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Cache version change.');
|
||||
}
|
||||
$this->__unserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
public function __unserialize(array $data)
|
||||
{
|
||||
$this->_data = $data;
|
||||
}
|
||||
|
||||
}
|
@ -1,198 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Query the search charsets available on a server.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.24.0
|
||||
*
|
||||
* @property-read array $charsets The list of valid charsets that have been
|
||||
* discovered on the server.
|
||||
*/
|
||||
class Horde_Imap_Client_Data_SearchCharset
|
||||
implements Serializable, SplSubject
|
||||
{
|
||||
/**
|
||||
* Base client object.
|
||||
*
|
||||
* @var Horde_Imap_Client_Base
|
||||
*/
|
||||
protected $_baseob;
|
||||
|
||||
/**
|
||||
* Charset data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_charsets = array(
|
||||
'US-ASCII' => true
|
||||
);
|
||||
|
||||
/**
|
||||
* Observers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_observers = array();
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'charsets':
|
||||
return array_keys(array_filter($this->_charsets));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function setBaseOb(Horde_Imap_Client_Base $ob)
|
||||
{
|
||||
$this->_baseob = $ob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the validity of a charset.
|
||||
*
|
||||
* @param string $charset The charset to query.
|
||||
* @param boolean $cached If true, only query cached values.
|
||||
*
|
||||
* @return boolean True if the charset is valid for searching.
|
||||
*/
|
||||
public function query($charset, $cached = false)
|
||||
{
|
||||
$charset = Horde_String::upper($charset);
|
||||
|
||||
if (isset($this->_charsets[$charset])) {
|
||||
return $this->_charsets[$charset];
|
||||
} elseif ($cached) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$this->_baseob) {
|
||||
throw new RuntimeException(
|
||||
'Base object needs to be defined to query for charset.'
|
||||
);
|
||||
}
|
||||
|
||||
/* Use a dummy search query and search for BADCHARSET response. */
|
||||
$query = new Horde_Imap_Client_Search_Query();
|
||||
$query->charset($charset, false);
|
||||
$query->ids($this->_baseob->getIdsOb(1, true));
|
||||
$query->text('a');
|
||||
try {
|
||||
$this->_baseob->search('INBOX', $query, array(
|
||||
'nocache' => true,
|
||||
'sequence' => true
|
||||
));
|
||||
$this->_charsets[$charset] = true;
|
||||
} catch (Horde_Imap_Client_Exception $e) {
|
||||
$this->_charsets[$charset] = ($e->getCode() !== Horde_Imap_Client_Exception::BADCHARSET);
|
||||
}
|
||||
|
||||
$this->notify();
|
||||
|
||||
return $this->_charsets[$charset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the validity of a given charset.
|
||||
*
|
||||
* @param string $charset The charset.
|
||||
* @param boolean $valid Is charset valid?
|
||||
*/
|
||||
public function setValid($charset, $valid = true)
|
||||
{
|
||||
$charset = Horde_String::upper($charset);
|
||||
$valid = (bool)$valid;
|
||||
|
||||
if (!isset($this->_charsets[$charset]) ||
|
||||
($this->_charsets[$charset] !== $valid)) {
|
||||
$this->_charsets[$charset] = $valid;
|
||||
$this->notify();
|
||||
}
|
||||
}
|
||||
|
||||
/* SplSubject methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function attach(SplObserver $observer)
|
||||
{
|
||||
$this->detach($observer);
|
||||
$this->_observers[] = $observer;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function detach(SplObserver $observer)
|
||||
{
|
||||
if (($key = array_search($observer, $this->_observers, true)) !== false) {
|
||||
unset($this->_observers[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification is triggered internally whenever the object's internal
|
||||
* data storage is altered.
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function notify()
|
||||
{
|
||||
foreach ($this->_observers as $val) {
|
||||
$val->update($this);
|
||||
}
|
||||
}
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function unserialize($data)
|
||||
{
|
||||
$data = @unserialize($data);
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Cache version change');
|
||||
}
|
||||
$this->__unserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return $this->_charsets;
|
||||
}
|
||||
|
||||
public function __unserialize(array $data)
|
||||
{
|
||||
$this->_charsets = $data;
|
||||
}
|
||||
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Query the search charsets available on a server that supports the UTF-8
|
||||
* IMAP extension (RFC 6855).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.24.0
|
||||
*/
|
||||
class Horde_Imap_Client_Data_SearchCharset_Utf8
|
||||
extends Horde_Imap_Client_Data_SearchCharset
|
||||
{
|
||||
/**
|
||||
* Charset data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_charsets = array(
|
||||
'US-ASCII' => true,
|
||||
'UTF-8' => true
|
||||
);
|
||||
|
||||
/**
|
||||
*/
|
||||
public function query($charset, $cached = false)
|
||||
{
|
||||
return isset($this->_charsets[Horde_String::upper($charset)]);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function setValid($charset, $valid = true)
|
||||
{
|
||||
}
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function unserialize($data)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function __unserialize(array $data)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
@ -1,267 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Mailbox synchronization results.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.2.0
|
||||
*
|
||||
* @property-read Horde_Imap_Client_Ids $flagsuids List of messages with flag
|
||||
* changes.
|
||||
* @property-read Horde_Imap_Client_Ids $newmsgsuids List of new messages.
|
||||
* @property-read Horde_Imap_Client_Ids $vanisheduids List of messages that
|
||||
* have vanished.
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Sync
|
||||
{
|
||||
/**
|
||||
* Mappings of status() values to sync keys.
|
||||
*
|
||||
* @since 2.8.0
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $map = array(
|
||||
'H' => 'highestmodseq',
|
||||
'M' => 'messages',
|
||||
'U' => 'uidnext',
|
||||
'V' => 'uidvalidity'
|
||||
);
|
||||
|
||||
/**
|
||||
* Are there messages that have had flag changes?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $flags = null;
|
||||
|
||||
/**
|
||||
* The previous value of HIGHESTMODSEQ.
|
||||
*
|
||||
* @since 2.8.0
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $highestmodseq = null;
|
||||
|
||||
/**
|
||||
* The synchronized mailbox.
|
||||
*
|
||||
* @var Horde_Imap_Client_Mailbox
|
||||
*/
|
||||
public $mailbox;
|
||||
|
||||
/**
|
||||
* The previous number of messages in the mailbox.
|
||||
*
|
||||
* @since 2.8.0
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $messages = null;
|
||||
|
||||
/**
|
||||
* Are there new messages?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $newmsgs = null;
|
||||
|
||||
/**
|
||||
* The previous value of UIDNEXT.
|
||||
*
|
||||
* @since 2.8.0
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $uidnext = null;
|
||||
|
||||
/**
|
||||
* The previous value of UIDVALIDITY.
|
||||
*
|
||||
* @since 2.8.0
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $uidvalidity = null;
|
||||
|
||||
/**
|
||||
* The UIDs of messages that are guaranteed to have vanished. This list is
|
||||
* only guaranteed to be available if the server supports QRESYNC or a
|
||||
* list of known UIDs is passed to the sync() method.
|
||||
*
|
||||
* @var Horde_Imap_Client_Ids
|
||||
*/
|
||||
public $vanished = null;
|
||||
|
||||
/**
|
||||
* UIDs of messages that have had flag changes.
|
||||
*
|
||||
* @var Horde_Imap_Client_Ids
|
||||
*/
|
||||
protected $_flagsuids;
|
||||
|
||||
/**
|
||||
* UIDs of new messages.
|
||||
*
|
||||
* @var Horde_Imap_Client_Ids
|
||||
*/
|
||||
protected $_newmsgsuids;
|
||||
|
||||
/**
|
||||
* UIDs of messages that have vanished.
|
||||
*
|
||||
* @var Horde_Imap_Client_Ids
|
||||
*/
|
||||
protected $_vanisheduids;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Horde_Imap_Client_Base $base_ob Base driver object.
|
||||
* @param mixed $mailbox Mailbox to sync.
|
||||
* @param array $sync Token sync data.
|
||||
* @param array $curr Current sync data.
|
||||
* @param integer $criteria Mask of criteria to return.
|
||||
* @param Horde_Imap_Client_Ids $ids List of known UIDs.
|
||||
*
|
||||
* @throws Horde_Imap_Client_Exception
|
||||
* @throws Horde_Imap_Client_Exception_Sync
|
||||
*/
|
||||
public function __construct(Horde_Imap_Client_Base $base_ob, $mailbox,
|
||||
$sync, $curr, $criteria, $ids)
|
||||
{
|
||||
foreach (self::$map as $key => $val) {
|
||||
if (isset($sync[$key])) {
|
||||
$this->$val = $sync[$key];
|
||||
}
|
||||
}
|
||||
|
||||
/* Check uidvalidity. */
|
||||
if (!$this->uidvalidity || ($curr['V'] != $this->uidvalidity)) {
|
||||
throw new Horde_Imap_Client_Exception_Sync('UIDs in cached mailbox have changed.', Horde_Imap_Client_Exception_Sync::UIDVALIDITY_CHANGED);
|
||||
}
|
||||
|
||||
$this->mailbox = $mailbox;
|
||||
|
||||
/* This was a UIDVALIDITY check only. */
|
||||
if (!$criteria) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sync_all = ($criteria & Horde_Imap_Client::SYNC_ALL);
|
||||
|
||||
/* New messages. */
|
||||
if ($sync_all ||
|
||||
($criteria & Horde_Imap_Client::SYNC_NEWMSGS) ||
|
||||
($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS)) {
|
||||
$this->newmsgs = empty($this->uidnext)
|
||||
? !empty($curr['U'])
|
||||
: (!empty($curr['U']) && ($curr['U'] > $this->uidnext));
|
||||
|
||||
if ($this->newmsgs &&
|
||||
($sync_all ||
|
||||
($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS))) {
|
||||
$new_ids = empty($this->uidnext)
|
||||
? Horde_Imap_Client_Ids::ALL
|
||||
: ($this->uidnext . ':' . $curr['U']);
|
||||
|
||||
$squery = new Horde_Imap_Client_Search_Query();
|
||||
$squery->ids(new Horde_Imap_Client_Ids($new_ids));
|
||||
$sres = $base_ob->search($mailbox, $squery);
|
||||
|
||||
$this->_newmsgsuids = $sres['match'];
|
||||
}
|
||||
}
|
||||
|
||||
/* Do single status call to get all necessary data. */
|
||||
if ($this->highestmodseq &&
|
||||
($sync_all ||
|
||||
($criteria & Horde_Imap_Client::SYNC_FLAGS) ||
|
||||
($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS) ||
|
||||
($criteria & Horde_Imap_Client::SYNC_VANISHED) ||
|
||||
($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS))) {
|
||||
$status_sync = $base_ob->status($mailbox, Horde_Imap_Client::STATUS_SYNCMODSEQ | Horde_Imap_Client::STATUS_SYNCFLAGUIDS | Horde_Imap_Client::STATUS_SYNCVANISHED);
|
||||
|
||||
if (!is_null($ids)) {
|
||||
$ids = $base_ob->resolveIds($mailbox, $ids);
|
||||
}
|
||||
}
|
||||
|
||||
/* Flag changes. */
|
||||
if ($sync_all || ($criteria & Horde_Imap_Client::SYNC_FLAGS)) {
|
||||
$this->flags = $this->highestmodseq
|
||||
? ($this->highestmodseq != $curr['H'])
|
||||
: true;
|
||||
}
|
||||
|
||||
if ($sync_all || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS)) {
|
||||
if ($this->highestmodseq) {
|
||||
if ($this->highestmodseq == $status_sync['syncmodseq']) {
|
||||
$this->_flagsuids = is_null($ids)
|
||||
? $status_sync['syncflaguids']
|
||||
: $base_ob->getIdsOb(array_intersect($ids->ids, $status_sync['syncflaguids']->ids));
|
||||
} else {
|
||||
$squery = new Horde_Imap_Client_Search_Query();
|
||||
$squery->modseq($this->highestmodseq + 1);
|
||||
$sres = $base_ob->search($mailbox, $squery, array(
|
||||
'ids' => $ids
|
||||
));
|
||||
$this->_flagsuids = $sres['match'];
|
||||
}
|
||||
} else {
|
||||
/* Without MODSEQ, need to mark all FLAGS as changed. */
|
||||
$this->_flagsuids = $base_ob->resolveIds($mailbox, is_null($ids) ? $base_ob->getIdsOb(Horde_Imap_Client_Ids::ALL) : $ids);
|
||||
}
|
||||
}
|
||||
|
||||
/* Vanished messages. */
|
||||
if ($sync_all ||
|
||||
($criteria & Horde_Imap_Client::SYNC_VANISHED) ||
|
||||
($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS)) {
|
||||
if ($this->highestmodseq &&
|
||||
($this->highestmodseq == $status_sync['syncmodseq'])) {
|
||||
$vanished = is_null($ids)
|
||||
? $status_sync['syncvanished']
|
||||
: $base_ob->getIdsOb(array_intersect($ids->ids, $status_sync['syncvanished']->ids));
|
||||
} else {
|
||||
$vanished = $base_ob->vanished($mailbox, $this->highestmodseq ? $this->highestmodseq : 1, array(
|
||||
'ids' => $ids
|
||||
));
|
||||
}
|
||||
|
||||
$this->vanished = (bool)count($vanished);
|
||||
$this->_vanisheduids = $vanished;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'flagsuids':
|
||||
case 'newmsgsuids':
|
||||
case 'vanisheduids':
|
||||
return empty($this->{'_' . $name})
|
||||
? new Horde_Imap_Client_Ids()
|
||||
: $this->{'_' . $name};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2008-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2008-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representing the threaded sort results from
|
||||
* Horde_Imap_Client_Base#thread().
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2008-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Data_Thread implements Countable, Serializable
|
||||
{
|
||||
/**
|
||||
* Internal thread data structure. Keys are base values, values are arrays
|
||||
* with keys as the ID and values as the level.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_thread = array();
|
||||
|
||||
/**
|
||||
* The index type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_type;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $data See $_thread.
|
||||
* @param string $type Either 'sequence' or 'uid'.
|
||||
*/
|
||||
public function __construct($data, $type)
|
||||
{
|
||||
$this->_thread = $data;
|
||||
$this->_type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ID type.
|
||||
*
|
||||
* @return string Either 'sequence' or 'uid'.
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sorted list of messages indices.
|
||||
*
|
||||
* @return Horde_Imap_Client_Ids The sorted list of messages.
|
||||
*/
|
||||
public function messageList()
|
||||
{
|
||||
return new Horde_Imap_Client_Ids($this->_getAllIndices(), $this->getType() == 'sequence');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of messages in a thread.
|
||||
*
|
||||
* @param integer $index An index contained in the thread.
|
||||
*
|
||||
* @return array Keys are indices, values are objects with the following
|
||||
* properties:
|
||||
* - base: (integer) Base ID of the thread. If null, thread is a single
|
||||
* message.
|
||||
* - last: (boolean) If true, this is the last index in the sublevel.
|
||||
* - level: (integer) The sublevel of the index.
|
||||
*/
|
||||
public function getThread($index)
|
||||
{
|
||||
foreach ($this->_thread as $v) {
|
||||
if (isset($v[$index])) {
|
||||
reset($v);
|
||||
|
||||
$ob = new stdClass;
|
||||
$ob->base = (count($v) > 1) ? key($v) : null;
|
||||
$ob->last = false;
|
||||
|
||||
$levels = $out = array();
|
||||
$last = 0;
|
||||
|
||||
while (($v2 = current($v)) !== false) {
|
||||
$k2 = key($v);
|
||||
$ob2 = clone $ob;
|
||||
$ob2->level = $v2;
|
||||
$out[$k2] = $ob2;
|
||||
|
||||
if (($last < $v2) && isset($levels[$v2])) {
|
||||
$out[$levels[$v2]]->last = true;
|
||||
}
|
||||
$levels[$v2] = $k2;
|
||||
$last = $v2;
|
||||
next($v);
|
||||
}
|
||||
|
||||
foreach ($levels as $v) {
|
||||
$out[$v]->last = true;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of all threads.
|
||||
*
|
||||
* @return array Keys of thread arrays are indices, values are objects with the following
|
||||
* properties:
|
||||
* - base: (integer) Base ID of the thread. If null, thread is a single
|
||||
* message.
|
||||
* - last: (boolean) If true, this is the last index in the sublevel.
|
||||
* - level: (integer) The sublevel of the index.
|
||||
*/
|
||||
public function getThreads()
|
||||
{
|
||||
$data = array();
|
||||
foreach ($this->_thread as $v) {
|
||||
reset($v);
|
||||
|
||||
$ob = new stdClass;
|
||||
$ob->base = (count($v) > 1) ? key($v) : null;
|
||||
$ob->last = false;
|
||||
|
||||
$levels = $out = array();
|
||||
$last = 0;
|
||||
|
||||
while (($v2 = current($v)) !== false) {
|
||||
$k2 = key($v);
|
||||
$ob2 = clone $ob;
|
||||
$ob2->level = $v2;
|
||||
$out[$k2] = $ob2;
|
||||
|
||||
if (($last < $v2) && isset($levels[$v2])) {
|
||||
$out[$levels[$v2]]->last = true;
|
||||
}
|
||||
$levels[$v2] = $k2;
|
||||
$last = $v2;
|
||||
next($v);
|
||||
}
|
||||
|
||||
foreach ($levels as $v) {
|
||||
$out[$v]->last = true;
|
||||
}
|
||||
|
||||
$data[] = $out;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/* Countable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return count($this->_getAllIndices());
|
||||
}
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function unserialize($data)
|
||||
{
|
||||
$data = @unserialize($data);
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Cache version changed.');
|
||||
}
|
||||
$this->__unserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return [$this->_thread, $this->_type];
|
||||
}
|
||||
|
||||
public function __unserialize(array $data)
|
||||
{
|
||||
list($this->_thread, $this->_type) = $data;
|
||||
}
|
||||
|
||||
/* Protected methods. */
|
||||
|
||||
/**
|
||||
* Return all indices.
|
||||
*
|
||||
* @return array An array of indices.
|
||||
*/
|
||||
protected function _getAllIndices()
|
||||
{
|
||||
$out = array();
|
||||
|
||||
foreach ($this->_thread as $val) {
|
||||
$out += $val;
|
||||
}
|
||||
|
||||
return array_keys($out);
|
||||
}
|
||||
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* A wrapper around PHP's native DateTime class that handles improperly
|
||||
* formatted dates and adds a few features missing from the base object
|
||||
* (string representation; doesn't fail on bad date input).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_DateTime extends DateTime
|
||||
{
|
||||
/**
|
||||
*/
|
||||
public function __construct($time = null, $tz = null)
|
||||
{
|
||||
/* See https://bugs.php.net/bug.php?id=67118 */
|
||||
$bug_67118 = (version_compare(PHP_VERSION, '5.6', '>=')) ||
|
||||
in_array(PHP_VERSION, array('5.4.29', '5.5.13'));
|
||||
$tz = new DateTimeZone('UTC');
|
||||
|
||||
/* Bug #14381 Catch malformed offset - which doesn't cause
|
||||
DateTime to throw exception. */
|
||||
if ($time !== null && substr(rtrim($time), -5) === ' 0000') {
|
||||
$time = substr(trim($time), 0, strlen(trim($time)) - 5) . ' +0000';
|
||||
try {
|
||||
if ($bug_67118) {
|
||||
new DateTime($time, $tz);
|
||||
}
|
||||
parent::__construct($time, $tz);
|
||||
return;
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
|
||||
try {
|
||||
if ($bug_67118) {
|
||||
new DateTime($time === null ? 'now' : $time, $tz);
|
||||
}
|
||||
parent::__construct($time === null ? 'now' : $time, $tz);
|
||||
return;
|
||||
} catch (Exception $e) {}
|
||||
|
||||
/* Check for malformed day-of-week parts, usually incorrectly
|
||||
* localized. E.g. Fr, 15 Apr 2016 15:15:09 +0000 */
|
||||
if ($time !== null && !preg_match("/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun),/", $time)) {
|
||||
$time = preg_replace("/^(\S*,)/", '', $time, 1, $i);
|
||||
if ($i) {
|
||||
try {
|
||||
if ($bug_67118) {
|
||||
new DateTime($time, $tz);
|
||||
}
|
||||
parent::__construct($time, $tz);
|
||||
return;
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/* Bug #5717 - Check for UT vs. UTC. */
|
||||
if ($time !== null && substr(rtrim($time), -3) === ' UT') {
|
||||
try {
|
||||
if ($bug_67118) {
|
||||
new DateTime($time . 'C', $tz);
|
||||
}
|
||||
parent::__construct($time . 'C', $tz);
|
||||
return;
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
|
||||
/* Bug #9847 - Catch paranthesized timezone information at end of date
|
||||
* string. */
|
||||
$date = preg_replace("/\s*\([^\)]+\)\s*$/", '', $time, -1, $i);
|
||||
if ($i) {
|
||||
try {
|
||||
if ($bug_67118) {
|
||||
new DateTime($date, $tz);
|
||||
}
|
||||
parent::__construct($date, $tz);
|
||||
return;
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
|
||||
parent::__construct('@-1', $tz);
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation: UNIX timestamp.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->error()
|
||||
? '0'
|
||||
: strval($this->getTimestamp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Was this an unparseable date?
|
||||
*
|
||||
* @return boolean True if unparseable.
|
||||
*/
|
||||
public function error()
|
||||
{
|
||||
return ($this->getTimestamp() === -1);
|
||||
}
|
||||
|
||||
}
|
@ -1,303 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2008-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2008-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception handler for the Horde_Imap_Client package.
|
||||
*
|
||||
* Additional server debug information MAY be found in the $details
|
||||
* property.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2008-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Exception extends Horde_Exception_Wrapped
|
||||
{
|
||||
/* Error message codes. */
|
||||
|
||||
/**
|
||||
* Unspecified error (DEFAULT).
|
||||
*/
|
||||
const UNSPECIFIED = 0;
|
||||
|
||||
/**
|
||||
* There was an unrecoverable error in UTF7IMAP -> UTF8 conversion.
|
||||
*/
|
||||
const UTF7IMAP_CONVERSION = 3;
|
||||
|
||||
/**
|
||||
* The server ended the connection.
|
||||
*/
|
||||
const DISCONNECT = 4;
|
||||
|
||||
/**
|
||||
* The charset used in the search query is not supported on the
|
||||
* server. */
|
||||
const BADCHARSET = 5;
|
||||
|
||||
/**
|
||||
* There were errors parsing the MIME/RFC 2822 header of the part.
|
||||
*/
|
||||
const PARSEERROR = 6;
|
||||
|
||||
/**
|
||||
* The server could not decode the MIME part (see RFC 3516).
|
||||
*/
|
||||
const UNKNOWNCTE = 7;
|
||||
|
||||
/**
|
||||
* The comparator specified by setComparator() was not recognized by the
|
||||
* IMAP server
|
||||
*/
|
||||
const BADCOMPARATOR = 9;
|
||||
|
||||
/**
|
||||
* RFC 7162 [3.1.2.2] - All mailboxes are not required to support
|
||||
* mod-sequences.
|
||||
*/
|
||||
const MBOXNOMODSEQ = 10;
|
||||
|
||||
/**
|
||||
* Thrown if server denies the network connection.
|
||||
*/
|
||||
const SERVER_CONNECT = 11;
|
||||
|
||||
/**
|
||||
* Thrown if read error for server response.
|
||||
*/
|
||||
const SERVER_READERROR = 12;
|
||||
|
||||
/**
|
||||
* Thrown if write error in server interaction.
|
||||
*/
|
||||
const SERVER_WRITEERROR = 16;
|
||||
|
||||
/**
|
||||
* Thrown on CATENATE if the URL is invalid.
|
||||
*/
|
||||
const CATENATE_BADURL = 13;
|
||||
|
||||
/**
|
||||
* Thrown on CATENATE if the message was too big.
|
||||
*/
|
||||
const CATENATE_TOOBIG = 14;
|
||||
|
||||
/**
|
||||
* Thrown on CREATE if special-use attribute is not supported.
|
||||
*/
|
||||
const USEATTR = 15;
|
||||
|
||||
/**
|
||||
* The user did not have permissions to carry out the operation.
|
||||
*/
|
||||
const NOPERM = 17;
|
||||
|
||||
/**
|
||||
* The operation was not successful because another user is holding
|
||||
* a necessary resource. The operation may succeed if attempted later.
|
||||
*/
|
||||
const INUSE = 18;
|
||||
|
||||
/**
|
||||
* The operation failed because data on the server was corrupt.
|
||||
*/
|
||||
const CORRUPTION = 19;
|
||||
|
||||
/**
|
||||
* The operation failed because it exceeded some limit on the server.
|
||||
*/
|
||||
const LIMIT = 20;
|
||||
|
||||
/**
|
||||
* The operation failed because the user is over their quota.
|
||||
*/
|
||||
const OVERQUOTA = 21;
|
||||
|
||||
/**
|
||||
* The operation failed because the requested creation object already
|
||||
* exists.
|
||||
*/
|
||||
const ALREADYEXISTS = 22;
|
||||
|
||||
/**
|
||||
* The operation failed because the requested deletion object did not
|
||||
* exist.
|
||||
*/
|
||||
const NONEXISTENT = 23;
|
||||
|
||||
/**
|
||||
* Setting metadata failed because the size of its value is too large.
|
||||
* The maximum octet count the server is willing to accept will be
|
||||
* in the exception message string.
|
||||
*/
|
||||
const METADATA_MAXSIZE = 24;
|
||||
|
||||
/**
|
||||
* Setting metadata failed because the maximum number of allowed
|
||||
* annotations has already been reached.
|
||||
*/
|
||||
const METADATA_TOOMANY = 25;
|
||||
|
||||
/**
|
||||
* Setting metadata failed because the server does not support private
|
||||
* annotations on one of the specified mailboxes.
|
||||
*/
|
||||
const METADATA_NOPRIVATE = 26;
|
||||
|
||||
/**
|
||||
* Invalid metadata entry.
|
||||
*/
|
||||
const METADATA_INVALID = 27;
|
||||
|
||||
|
||||
// Login failures
|
||||
|
||||
/**
|
||||
* Could not start mandatory TLS connection.
|
||||
*/
|
||||
const LOGIN_TLSFAILURE = 100;
|
||||
|
||||
/**
|
||||
* Could not find an available authentication method.
|
||||
*/
|
||||
const LOGIN_NOAUTHMETHOD = 101;
|
||||
|
||||
/**
|
||||
* Generic authentication failure.
|
||||
*/
|
||||
const LOGIN_AUTHENTICATIONFAILED = 102;
|
||||
|
||||
/**
|
||||
* Remote server is unavailable.
|
||||
*/
|
||||
const LOGIN_UNAVAILABLE = 103;
|
||||
|
||||
/**
|
||||
* Authentication succeeded, but authorization failed.
|
||||
*/
|
||||
const LOGIN_AUTHORIZATIONFAILED = 104;
|
||||
|
||||
/**
|
||||
* Authentication is no longer permitted with this passphrase.
|
||||
*/
|
||||
const LOGIN_EXPIRED = 105;
|
||||
|
||||
/**
|
||||
* Login requires privacy.
|
||||
*/
|
||||
const LOGIN_PRIVACYREQUIRED = 106;
|
||||
|
||||
/**
|
||||
* Server verification failed (SCRAM authentication).
|
||||
*/
|
||||
const LOGIN_SERVER_VERIFICATION_FAILED = 107;
|
||||
|
||||
|
||||
// Mailbox access failures
|
||||
|
||||
/**
|
||||
* Could not open/access mailbox
|
||||
*/
|
||||
const MAILBOX_NOOPEN = 200;
|
||||
|
||||
/**
|
||||
* Could not complete the command because the mailbox is read-only
|
||||
*/
|
||||
const MAILBOX_READONLY = 201;
|
||||
|
||||
|
||||
// POP3 specific error codes
|
||||
|
||||
/**
|
||||
* Temporary issue. Generally, there is no need to alarm the user for
|
||||
* errors of this type.
|
||||
*/
|
||||
const POP3_TEMP_ERROR = 300;
|
||||
|
||||
/**
|
||||
* Permanent error indicated by server.
|
||||
*/
|
||||
const POP3_PERM_ERROR = 301;
|
||||
|
||||
|
||||
// Unsupported feature error codes
|
||||
|
||||
/**
|
||||
* Function/feature is not supported on this server.
|
||||
*/
|
||||
const NOT_SUPPORTED = 400;
|
||||
|
||||
|
||||
/**
|
||||
* Raw error message (in English).
|
||||
*
|
||||
* @since 2.18.0
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $raw_msg = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $message Error message (non-translated).
|
||||
* @param int $code Error code.
|
||||
*/
|
||||
public function __construct($message = null, $code = null)
|
||||
{
|
||||
parent::__construct($message, $code);
|
||||
|
||||
$this->raw_msg = $this->message;
|
||||
try {
|
||||
$this->message = Horde_Imap_Client_Translation::t($this->message);
|
||||
} catch (Horde_Translation_Exception $e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the error message to be altered.
|
||||
*
|
||||
* @param string $msg Error message.
|
||||
*/
|
||||
public function setMessage($msg)
|
||||
{
|
||||
$this->message = strval($msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the error code to be altered.
|
||||
*
|
||||
* @param integer $code Error code.
|
||||
*/
|
||||
public function setCode($code)
|
||||
{
|
||||
$this->code = intval($code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform substitution of variables in the error message.
|
||||
*
|
||||
* Needed to allow for correct translation of error message.
|
||||
*
|
||||
* @since 2.22.0
|
||||
*
|
||||
* @param array $args Arguments used for substitution.
|
||||
*/
|
||||
public function messagePrintf(array $args = array())
|
||||
{
|
||||
$this->raw_msg = vsprintf($this->raw_msg, $args);
|
||||
$this->message = vsprintf($this->message, $args);
|
||||
}
|
||||
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception thrown for non-supported server extensions.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Exception_NoSupportExtension
|
||||
extends Horde_Imap_Client_Exception
|
||||
{
|
||||
/**
|
||||
* The extension not supported on the server.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $extension;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $extension The extension not supported on the server.
|
||||
* @param string $msg A non-standard error message to use instead
|
||||
* of the default.
|
||||
*/
|
||||
public function __construct($extension, $msg = null)
|
||||
{
|
||||
$this->extension = $extension;
|
||||
|
||||
if (is_null($msg)) {
|
||||
$msg = sprintf(
|
||||
Horde_Imap_Client_Translation::r("The server does not support the %s extension."),
|
||||
$extension
|
||||
);
|
||||
}
|
||||
|
||||
parent::__construct($msg, self::NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception thrown for non-supported IMAP features on POP3 servers.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Exception_NoSupportPop3
|
||||
extends Horde_Imap_Client_Exception
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $feature The feature not supported in POP3.
|
||||
*/
|
||||
public function __construct($feature)
|
||||
{
|
||||
parent::__construct(
|
||||
Horde_Imap_Client_Translation::r("%s not supported on POP3 servers."),
|
||||
self::NOT_SUPPORTED
|
||||
);
|
||||
$this->messagePrintf(array($feature));
|
||||
}
|
||||
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception thrown if search query text cannot be converted to different
|
||||
* charset.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Exception_SearchCharset
|
||||
extends Horde_Imap_Client_Exception
|
||||
{
|
||||
/**
|
||||
* Charset that was attempted to be converted to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $charset;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $charset The charset that was attempted to be converted
|
||||
* to.
|
||||
*/
|
||||
public function __construct($charset)
|
||||
{
|
||||
$this->charset = $charset;
|
||||
|
||||
parent::__construct(
|
||||
Horde_Imap_Client_Translation::r("Cannot convert search query text to new charset"),
|
||||
self::BADCHARSET
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception thrown for server error responses.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*
|
||||
* @property-read string $command The command that caused the BAD/NO error
|
||||
* status.
|
||||
* @property-read array $resp_data The response data array.
|
||||
* @property-read integer $status Server error status.
|
||||
*/
|
||||
class Horde_Imap_Client_Exception_ServerResponse extends Horde_Imap_Client_Exception
|
||||
{
|
||||
/**
|
||||
* Pipeline object.
|
||||
*
|
||||
* @var Horde_Imap_Client_Interaction_Pipeline
|
||||
*/
|
||||
protected $_pipeline;
|
||||
|
||||
/**
|
||||
* Server response object.
|
||||
*
|
||||
* @var Horde_Imap_Client_Interaction_Server
|
||||
*/
|
||||
protected $_server;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string|null $msg Error message.
|
||||
* @param integer $code Error code.
|
||||
* @param Horde_Imap_Client_Interaction_Server $server Server ob.
|
||||
* @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline ob.
|
||||
*/
|
||||
public function __construct(
|
||||
$msg,
|
||||
$code,
|
||||
Horde_Imap_Client_Interaction_Server $server,
|
||||
Horde_Imap_Client_Interaction_Pipeline $pipeline
|
||||
)
|
||||
{
|
||||
$this->details = strval($server->token);
|
||||
|
||||
$this->_pipeline = $pipeline;
|
||||
$this->_server = $server;
|
||||
|
||||
parent::__construct($msg, $code);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'command':
|
||||
return ($this->_server instanceof Horde_Imap_Client_Interaction_Server_Tagged)
|
||||
? $this->_pipeline->getCmd($this->_server->tag)->getCommand()
|
||||
: null;
|
||||
|
||||
case 'resp_data':
|
||||
return $this->_pipeline->data;
|
||||
|
||||
case 'status':
|
||||
return $this->_server->status;
|
||||
|
||||
default:
|
||||
return parent::__get($name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception thrown for mailbox synchronization errors.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Exception_Sync extends Horde_Exception_Wrapped
|
||||
{
|
||||
/* Error message codes. */
|
||||
|
||||
/**
|
||||
* Token could not be parsed.
|
||||
*/
|
||||
const BAD_TOKEN = 1;
|
||||
|
||||
/**
|
||||
* UIDVALIDITY of the mailbox changed.
|
||||
*/
|
||||
const UIDVALIDITY_CHANGED = 2;
|
||||
|
||||
}
|
@ -1,393 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetch query object for use with Horde_Imap_Client_Base#fetch().
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Fetch_Query implements ArrayAccess, Countable, Iterator
|
||||
{
|
||||
/**
|
||||
* Internal data array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_data = array();
|
||||
|
||||
/**
|
||||
* Get the full text of the message.
|
||||
*
|
||||
* @param array $opts The following options are available:
|
||||
* - length: (integer) The length of the substring to return.
|
||||
* DEFAULT: The entire text is returned.
|
||||
* - peek: (boolean) If set, does not set the '\Seen' flag on the
|
||||
* message.
|
||||
* DEFAULT: The seen flag is set.
|
||||
* - start: (integer) If a portion of the full text is desired to be
|
||||
* returned, the starting position is identified here.
|
||||
* DEFAULT: The entire text is returned.
|
||||
*/
|
||||
public function fullText(array $opts = array())
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_FULLMSG] = $opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return header text.
|
||||
*
|
||||
* Header text is defined only for the base RFC 2822 message or
|
||||
* message/rfc822 parts.
|
||||
*
|
||||
* @param array $opts The following options are available:
|
||||
* - id: (string) The MIME ID to obtain the header text for.
|
||||
* DEFAULT: The header text for the base message will be
|
||||
* returned.
|
||||
* - length: (integer) The length of the substring to return.
|
||||
* DEFAULT: The entire text is returned.
|
||||
* - peek: (boolean) If set, does not set the '\Seen' flag on the
|
||||
* message.
|
||||
* DEFAULT: The seen flag is set.
|
||||
* - start: (integer) If a portion of the full text is desired to be
|
||||
* returned, the starting position is identified here.
|
||||
* DEFAULT: The entire text is returned.
|
||||
*/
|
||||
public function headerText(array $opts = array())
|
||||
{
|
||||
$id = isset($opts['id'])
|
||||
? $opts['id']
|
||||
: 0;
|
||||
$this->_data[Horde_Imap_Client::FETCH_HEADERTEXT][$id] = $opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return body text.
|
||||
*
|
||||
* Body text is defined only for the base RFC 2822 message or
|
||||
* message/rfc822 parts.
|
||||
*
|
||||
* @param array $opts The following options are available:
|
||||
* - id: (string) The MIME ID to obtain the body text for.
|
||||
* DEFAULT: The body text for the entire message will be
|
||||
* returned.
|
||||
* - length: (integer) The length of the substring to return.
|
||||
* DEFAULT: The entire text is returned.
|
||||
* - peek: (boolean) If set, does not set the '\Seen' flag on the
|
||||
* message.
|
||||
* DEFAULT: The seen flag is set.
|
||||
* - start: (integer) If a portion of the full text is desired to be
|
||||
* returned, the starting position is identified here.
|
||||
* DEFAULT: The entire text is returned.
|
||||
*/
|
||||
public function bodyText(array $opts = array())
|
||||
{
|
||||
$id = isset($opts['id'])
|
||||
? $opts['id']
|
||||
: 0;
|
||||
$this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id] = $opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return MIME header text.
|
||||
*
|
||||
* MIME header text is defined only for non-RFC 2822 messages and
|
||||
* non-message/rfc822 parts.
|
||||
*
|
||||
* @param string $id The MIME ID to obtain the MIME header text for.
|
||||
* @param array $opts The following options are available:
|
||||
* - length: (integer) The length of the substring to return.
|
||||
* DEFAULT: The entire text is returned.
|
||||
* - peek: (boolean) If set, does not set the '\Seen' flag on the
|
||||
* message.
|
||||
* DEFAULT: The seen flag is set.
|
||||
* - start: (integer) If a portion of the full text is desired to be
|
||||
* returned, the starting position is identified here.
|
||||
* DEFAULT: The entire text is returned.
|
||||
*/
|
||||
public function mimeHeader($id, array $opts = array())
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_MIMEHEADER][$id] = $opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the body part data for a MIME ID.
|
||||
*
|
||||
* @param string $id The MIME ID to obtain the body part text for.
|
||||
* @param array $opts The following options are available:
|
||||
* - decode: (boolean) Attempt to server-side decode the bodypart data
|
||||
* if it is MIME transfer encoded.
|
||||
* DEFAULT: false
|
||||
* - length: (integer) The length of the substring to return.
|
||||
* DEFAULT: The entire text is returned.
|
||||
* - peek: (boolean) If set, does not set the '\Seen' flag on the
|
||||
* message.
|
||||
* DEFAULT: The seen flag is set.
|
||||
* - start: (integer) If a portion of the full text is desired to be
|
||||
* returned, the starting position is identified here.
|
||||
* DEFAULT: The entire text is returned.
|
||||
*/
|
||||
public function bodyPart($id, array $opts = array())
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_BODYPART][$id] = $opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the decoded body part size for a MIME ID.
|
||||
*
|
||||
* @param string $id The MIME ID to obtain the decoded body part size
|
||||
* for.
|
||||
*/
|
||||
public function bodyPartSize($id)
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns RFC 2822 header text that matches a search string.
|
||||
*
|
||||
* This header search work only with the base RFC 2822 message or
|
||||
* message/rfc822 parts.
|
||||
*
|
||||
* @param string $label A unique label associated with this particular
|
||||
* search. This is how the results are stored.
|
||||
* @param array $search The search string(s) (case-insensitive).
|
||||
* @param array $opts The following options are available:
|
||||
* - cache: (boolean) If true, and 'peek' is also true, will cache
|
||||
* the result of this call.
|
||||
* DEFAULT: false
|
||||
* - id: (string) The MIME ID to search.
|
||||
* DEFAULT: The base message part
|
||||
* - length: (integer) The length of the substring to return.
|
||||
* DEFAULT: The entire text is returned.
|
||||
* - notsearch: (boolean) Do a 'NOT' search on the headers.
|
||||
* DEFAULT: false
|
||||
* - peek: (boolean) If set, does not set the '\Seen' flag on the
|
||||
* message.
|
||||
* DEFAULT: The seen flag is set.
|
||||
* - start: (integer) If a portion of the full text is desired to be
|
||||
* returned, the starting position is identified here.
|
||||
* DEFAULT: The entire text is returned.
|
||||
*/
|
||||
public function headers($label, $search, array $opts = array())
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_HEADERS][$label] = array_merge(
|
||||
$opts,
|
||||
array(
|
||||
'headers' => array_map('strval', $search)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return MIME structure information.
|
||||
*/
|
||||
public function structure()
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_STRUCTURE] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return envelope header data.
|
||||
*/
|
||||
public function envelope()
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_ENVELOPE] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return flags set for the message.
|
||||
*/
|
||||
public function flags()
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_FLAGS] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the internal (IMAP) date of the message.
|
||||
*/
|
||||
public function imapDate()
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_IMAPDATE] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size (in bytes) of the message.
|
||||
*/
|
||||
public function size()
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_SIZE] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the unique ID of the message.
|
||||
*/
|
||||
public function uid()
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_UID] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sequence number of the message.
|
||||
*/
|
||||
public function seq()
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_SEQ] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mod-sequence value for the message.
|
||||
*
|
||||
* The server must support the CONDSTORE IMAP extension, and the mailbox
|
||||
* must support mod-sequences.
|
||||
*/
|
||||
public function modseq()
|
||||
{
|
||||
$this->_data[Horde_Imap_Client::FETCH_MODSEQ] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the query contain the given criteria?
|
||||
*
|
||||
* @param integer $criteria The criteria to remove.
|
||||
*
|
||||
* @return boolean True if the query contains the given criteria.
|
||||
*/
|
||||
public function contains($criteria)
|
||||
{
|
||||
return isset($this->_data[$criteria]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an entry under a given criteria.
|
||||
*
|
||||
* @param integer $criteria Criteria ID.
|
||||
* @param string $key The key to remove.
|
||||
*/
|
||||
public function remove($criteria, $key)
|
||||
{
|
||||
if (isset($this->_data[$criteria]) &&
|
||||
is_array($this->_data[$criteria])) {
|
||||
unset($this->_data[$criteria][$key]);
|
||||
if (empty($this->_data[$criteria])) {
|
||||
unset($this->_data[$criteria]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash of the current query object.
|
||||
*
|
||||
* @return string Hash.
|
||||
*/
|
||||
public function hash()
|
||||
{
|
||||
return hash('md5', serialize($this));
|
||||
}
|
||||
|
||||
/* ArrayAccess methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->_data[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return isset($this->_data[$offset])
|
||||
? $this->_data[$offset]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->_data[$offset] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->_data[$offset]);
|
||||
}
|
||||
|
||||
/* Countable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return count($this->_data);
|
||||
}
|
||||
|
||||
/* Iterator methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
$opts = current($this->_data);
|
||||
|
||||
return (!empty($opts) && ($this->key() == Horde_Imap_Client::FETCH_BODYPARTSIZE))
|
||||
? array_keys($opts)
|
||||
: $opts;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function key()
|
||||
{
|
||||
return key($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function next()
|
||||
{
|
||||
next($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function rewind()
|
||||
{
|
||||
reset($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function valid()
|
||||
{
|
||||
return !is_null($this->key());
|
||||
}
|
||||
|
||||
}
|
@ -1,188 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetch results object for use with Horde_Imap_Client_Base#fetch().
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*
|
||||
* @property-read integer $key_type The key type (sequence or UID).
|
||||
*/
|
||||
class Horde_Imap_Client_Fetch_Results
|
||||
implements ArrayAccess, Countable, IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Key type constants.
|
||||
*/
|
||||
const SEQUENCE = 1;
|
||||
const UID = 2;
|
||||
|
||||
/**
|
||||
* Internal data array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_data = array();
|
||||
|
||||
/**
|
||||
* Key type.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $_keyType;
|
||||
|
||||
/**
|
||||
* Class to use when creating a new fetch object.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_obClass;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $ob_class Class to use when creating a new fetch
|
||||
* object.
|
||||
* @param integer $key_type Key type.
|
||||
*/
|
||||
public function __construct($ob_class = 'Horde_Imap_Client_Data_Fetch',
|
||||
$key_type = self::UID)
|
||||
{
|
||||
$this->_obClass = $ob_class;
|
||||
$this->_keyType = $key_type;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'key_type':
|
||||
return $this->_keyType;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a fetch object, creating and storing an empty object in the
|
||||
* results set if it doesn't currently exist.
|
||||
*
|
||||
* @param string $key The key to retrieve.
|
||||
*
|
||||
* @return Horde_Imap_Client_Data_Fetch The fetch object.
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
if (!isset($this->_data[$key])) {
|
||||
$this->_data[$key] = new $this->_obClass();
|
||||
}
|
||||
|
||||
return $this->_data[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of IDs.
|
||||
*
|
||||
* @return array ID list.
|
||||
*/
|
||||
public function ids()
|
||||
{
|
||||
ksort($this->_data);
|
||||
return array_keys($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first fetch object in the results, if there is only one
|
||||
* object.
|
||||
*
|
||||
* @return null|Horde_Imap_Client_Data_Fetch The fetch object if there is
|
||||
* only one object, or null.
|
||||
*/
|
||||
public function first()
|
||||
{
|
||||
return (count($this->_data) === 1)
|
||||
? reset($this->_data)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all fetch results.
|
||||
*
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->_data = array();
|
||||
}
|
||||
|
||||
/* ArrayAccess methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->_data[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return isset($this->_data[$offset])
|
||||
? $this->_data[$offset]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->_data[$offset] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->_data[$offset]);
|
||||
}
|
||||
|
||||
/* Countable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return count($this->_data);
|
||||
}
|
||||
|
||||
/* IteratorAggregate methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
ksort($this->_data);
|
||||
return new ArrayIterator($this->_data);
|
||||
}
|
||||
|
||||
}
|
@ -1,511 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object that provides a way to identify a list of IMAP indices.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*
|
||||
* @property-read boolean $all Does this represent an ALL message set?
|
||||
* @property-read array $ids The list of IDs.
|
||||
* @property-read boolean $largest Does this represent the largest ID in use?
|
||||
* @property-read string $max The largest ID (@since 2.20.0).
|
||||
* @property-read string $min The smallest ID (@since 2.20.0).
|
||||
* @property-read string $range_string Generates a range string consisting of
|
||||
* all messages between begin and end of
|
||||
* ID list.
|
||||
* @property-read boolean $search_res Does this represent a search result?
|
||||
* @property-read boolean $sequence Are these sequence IDs? If false, these
|
||||
* are UIDs.
|
||||
* @property-read boolean $special True if this is a "special" ID
|
||||
* representation.
|
||||
* @property-read string $tostring Return the non-sorted string
|
||||
* representation.
|
||||
* @property-read string $tostring_sort Return the sorted string
|
||||
* representation.
|
||||
*/
|
||||
class Horde_Imap_Client_Ids implements Countable, Iterator, Serializable
|
||||
{
|
||||
/**
|
||||
* "Special" representation constants.
|
||||
*/
|
||||
const ALL = "\01";
|
||||
const SEARCH_RES = "\02";
|
||||
const LARGEST = "\03";
|
||||
|
||||
/**
|
||||
* Allow duplicate IDs?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $duplicates = false;
|
||||
|
||||
/**
|
||||
* List of IDs.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $_ids = array();
|
||||
|
||||
/**
|
||||
* Are IDs message sequence numbers?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_sequence = false;
|
||||
|
||||
/**
|
||||
* Are IDs sorted?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_sorted = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $ids See self::add().
|
||||
* @param boolean $sequence Are $ids message sequence numbers?
|
||||
*/
|
||||
public function __construct($ids = null, $sequence = false)
|
||||
{
|
||||
$this->add($ids);
|
||||
$this->_sequence = $sequence;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'all':
|
||||
return ($this->_ids === self::ALL);
|
||||
|
||||
case 'ids':
|
||||
return is_array($this->_ids)
|
||||
? $this->_ids
|
||||
: array();
|
||||
|
||||
case 'largest':
|
||||
return ($this->_ids === self::LARGEST);
|
||||
|
||||
case 'max':
|
||||
$this->sort();
|
||||
return end($this->_ids);
|
||||
|
||||
case 'min':
|
||||
$this->sort();
|
||||
return reset($this->_ids);
|
||||
|
||||
case 'range_string':
|
||||
if (!count($this)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$min = $this->min;
|
||||
$max = $this->max;
|
||||
|
||||
return ($min == $max)
|
||||
? $min
|
||||
: $min . ':' . $max;
|
||||
|
||||
case 'search_res':
|
||||
return ($this->_ids === self::SEARCH_RES);
|
||||
|
||||
case 'sequence':
|
||||
return (bool)$this->_sequence;
|
||||
|
||||
case 'special':
|
||||
return is_string($this->_ids);
|
||||
|
||||
case 'tostring':
|
||||
case 'tostring_sort':
|
||||
if ($this->all) {
|
||||
return '1:*';
|
||||
} elseif ($this->largest) {
|
||||
return '*';
|
||||
} elseif ($this->search_res) {
|
||||
return '$';
|
||||
}
|
||||
return strval($this->_toSequenceString($name == 'tostring_sort'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->tostring;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add IDs to the current object.
|
||||
*
|
||||
* @param mixed $ids Either self::ALL, self::SEARCH_RES, self::LARGEST,
|
||||
* Horde_Imap_Client_Ids object, array, or sequence
|
||||
* string.
|
||||
*/
|
||||
public function add($ids)
|
||||
{
|
||||
if (!is_null($ids)) {
|
||||
if (is_string($ids) &&
|
||||
in_array($ids, array(self::ALL, self::SEARCH_RES, self::LARGEST))) {
|
||||
$this->_ids = $ids;
|
||||
} elseif ($add = $this->_resolveIds($ids)) {
|
||||
if (is_array($this->_ids) && !empty($this->_ids)) {
|
||||
foreach ($add as $val) {
|
||||
$this->_ids[] = $val;
|
||||
}
|
||||
} else {
|
||||
$this->_ids = $add;
|
||||
}
|
||||
if (!$this->duplicates) {
|
||||
$this->_ids = (count($this->_ids) > 25000)
|
||||
? array_unique($this->_ids)
|
||||
: array_keys(array_flip($this->_ids));
|
||||
}
|
||||
}
|
||||
|
||||
$this->_sorted = is_array($this->_ids) && (count($this->_ids) === 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removed IDs from the current object.
|
||||
*
|
||||
* @since 2.17.0
|
||||
*
|
||||
* @param mixed $ids Either Horde_Imap_Client_Ids object, array, or
|
||||
* sequence string.
|
||||
*/
|
||||
public function remove($ids)
|
||||
{
|
||||
if (!$this->isEmpty() &&
|
||||
($remove = $this->_resolveIds($ids))) {
|
||||
$this->_ids = array_diff($this->_ids, array_unique($remove));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this object empty (i.e. does not contain IDs)?
|
||||
*
|
||||
* @return boolean True if object is empty.
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return (is_array($this->_ids) && !count($this->_ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the order of the IDs.
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
if (is_array($this->_ids)) {
|
||||
$this->_ids = array_reverse($this->_ids);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the IDs.
|
||||
*/
|
||||
public function sort()
|
||||
{
|
||||
if (!$this->_sorted && is_array($this->_ids)) {
|
||||
$this->_sort($this->_ids);
|
||||
$this->_sorted = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the IDs numerically.
|
||||
*
|
||||
* @param array $ids The array list.
|
||||
*/
|
||||
protected function _sort(&$ids)
|
||||
{
|
||||
sort($ids, SORT_NUMERIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split the sequence string at an approximate length.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @param integer $length Length to split.
|
||||
*
|
||||
* @return array A list containing individual sequence strings.
|
||||
*/
|
||||
public function split($length)
|
||||
{
|
||||
$id = new Horde_Stream_Temp();
|
||||
$id->add($this->tostring_sort, true);
|
||||
|
||||
$out = array();
|
||||
|
||||
do {
|
||||
$out[] = $id->substring(0, $length) . $id->getToChar(',');
|
||||
} while (!$id->eof());
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the $ids input to add() and remove().
|
||||
*
|
||||
* @param mixed $ids Either Horde_Imap_Client_Ids object, array, or
|
||||
* sequence string.
|
||||
*
|
||||
* @return array An array of IDs.
|
||||
*/
|
||||
protected function _resolveIds($ids)
|
||||
{
|
||||
if ($ids instanceof Horde_Imap_Client_Ids) {
|
||||
return $ids->ids;
|
||||
} elseif (is_array($ids)) {
|
||||
return $ids;
|
||||
} elseif (is_string($ids) || is_integer($ids)) {
|
||||
return is_numeric($ids)
|
||||
? array($ids)
|
||||
: $this->_fromSequenceString($ids);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an IMAP message sequence string from a list of indices.
|
||||
*
|
||||
* Index Format: range_start:range_end,uid,uid2,...
|
||||
*
|
||||
* @param boolean $sort Numerically sort the IDs before creating the
|
||||
* range?
|
||||
*
|
||||
* @return string The IMAP message sequence string.
|
||||
*/
|
||||
protected function _toSequenceString($sort = true)
|
||||
{
|
||||
if (empty($this->_ids)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$in = $this->_ids;
|
||||
|
||||
if ($sort && !$this->_sorted) {
|
||||
$this->_sort($in);
|
||||
}
|
||||
|
||||
$first = $last = array_shift($in);
|
||||
$i = count($in) - 1;
|
||||
$out = array();
|
||||
|
||||
foreach ($in as $key => $val) {
|
||||
if (($last + 1) == $val) {
|
||||
$last = $val;
|
||||
}
|
||||
|
||||
if (($i == $key) || ($last != $val)) {
|
||||
if ($last == $first) {
|
||||
$out[] = $first;
|
||||
if ($i == $key) {
|
||||
$out[] = $val;
|
||||
}
|
||||
} else {
|
||||
$out[] = $first . ':' . $last;
|
||||
if (($i == $key) && ($last != $val)) {
|
||||
$out[] = $val;
|
||||
}
|
||||
}
|
||||
$first = $last = $val;
|
||||
}
|
||||
}
|
||||
|
||||
return empty($out)
|
||||
? $first
|
||||
: implode(',', $out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an IMAP message sequence string into a list of indices.
|
||||
*
|
||||
* @see _toSequenceString()
|
||||
*
|
||||
* @param string $str The IMAP message sequence string.
|
||||
*
|
||||
* @return array An array of indices.
|
||||
*/
|
||||
protected function _fromSequenceString($str)
|
||||
{
|
||||
$ids = array();
|
||||
$str = trim($str);
|
||||
|
||||
if (!strlen($str)) {
|
||||
return $ids;
|
||||
}
|
||||
|
||||
$idarray = explode(',', $str);
|
||||
|
||||
foreach ($idarray as $val) {
|
||||
$range = explode(':', $val);
|
||||
if (isset($range[1])) {
|
||||
for ($i = min($range), $j = max($range); $i <= $j; ++$i) {
|
||||
$ids[] = $i;
|
||||
}
|
||||
} else {
|
||||
$ids[] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/* Countable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return is_array($this->_ids)
|
||||
? count($this->_ids)
|
||||
: 0;
|
||||
}
|
||||
|
||||
/* Iterator methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
return is_array($this->_ids)
|
||||
? current($this->_ids)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function key()
|
||||
{
|
||||
return is_array($this->_ids)
|
||||
? key($this->_ids)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function next()
|
||||
{
|
||||
if (is_array($this->_ids)) {
|
||||
next($this->_ids);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function rewind()
|
||||
{
|
||||
if (is_array($this->_ids)) {
|
||||
reset($this->_ids);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function valid()
|
||||
{
|
||||
return !is_null($this->key());
|
||||
}
|
||||
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
public function unserialize($data)
|
||||
{
|
||||
$data = @unserialize($data);
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Cache version change.');
|
||||
}
|
||||
|
||||
$this->__unserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
$save = array();
|
||||
|
||||
if ($this->duplicates) {
|
||||
$save['d'] = 1;
|
||||
}
|
||||
|
||||
if ($this->_sequence) {
|
||||
$save['s'] = 1;
|
||||
}
|
||||
|
||||
if ($this->_sorted) {
|
||||
$save['is'] = 1;
|
||||
}
|
||||
|
||||
switch ($this->_ids) {
|
||||
case self::ALL:
|
||||
$save['a'] = true;
|
||||
break;
|
||||
|
||||
case self::LARGEST:
|
||||
$save['l'] = true;
|
||||
break;
|
||||
|
||||
case self::SEARCH_RES:
|
||||
$save['sr'] = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
$save['i'] = strval($this);
|
||||
break;
|
||||
}
|
||||
|
||||
return $save;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __unserialize($data)
|
||||
{
|
||||
$this->duplicates = !empty($data['d']);
|
||||
$this->_sequence = !empty($data['s']);
|
||||
$this->_sorted = !empty($data['is']);
|
||||
|
||||
if (isset($data['a'])) {
|
||||
$this->_ids = self::ALL;
|
||||
} elseif (isset($data['l'])) {
|
||||
$this->_ids = self::LARGEST;
|
||||
} elseif (isset($data['sr'])) {
|
||||
$this->_ids = self::SEARCH_RES;
|
||||
} elseif (isset($data['i'])) {
|
||||
$this->add($data['i']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,256 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object implementing lookups between UIDs and message sequence numbers.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.1.0
|
||||
*
|
||||
* @property-read array $map The raw ID mapping data.
|
||||
* @property-read Horde_Imap_Client_Ids $seq The sorted sequence values.
|
||||
* @property-read Horde_Imap_Client_Ids $uids The sorted UIDs.
|
||||
*/
|
||||
class Horde_Imap_Client_Ids_Map implements Countable, IteratorAggregate, Serializable
|
||||
{
|
||||
/**
|
||||
* Sequence -> UID mapping.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_ids = array();
|
||||
|
||||
/**
|
||||
* Is the array sorted?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_sorted = true;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $ids Array of sequence -> UID mapping.
|
||||
*/
|
||||
public function __construct(array $ids = array())
|
||||
{
|
||||
$this->update($ids);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'map':
|
||||
return $this->_ids;
|
||||
|
||||
case 'seq':
|
||||
$this->sort();
|
||||
return new Horde_Imap_Client_Ids(array_keys($this->_ids), true);
|
||||
|
||||
case 'uids':
|
||||
$this->sort();
|
||||
return new Horde_Imap_Client_Ids($this->_ids);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the mapping.
|
||||
*
|
||||
* @param array $ids Array of sequence -> UID mapping.
|
||||
*
|
||||
* @return boolean True if the mapping changed.
|
||||
*/
|
||||
public function update($ids)
|
||||
{
|
||||
if (empty($ids)) {
|
||||
return false;
|
||||
} elseif (empty($this->_ids)) {
|
||||
$this->_ids = $ids;
|
||||
$change = true;
|
||||
} else {
|
||||
$change = false;
|
||||
foreach ($ids as $k => $v) {
|
||||
if (!isset($this->_ids[$k]) || ($this->_ids[$k] != $v)) {
|
||||
$this->_ids[$k] = $v;
|
||||
$change = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($change) {
|
||||
$this->_sorted = false;
|
||||
}
|
||||
|
||||
return $change;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Sequence <-> UID lookup table.
|
||||
*
|
||||
* @param Horde_Imap_Client_Ids $ids IDs to lookup.
|
||||
*
|
||||
* @return array Keys are sequence numbers, values are UIDs.
|
||||
*/
|
||||
public function lookup(Horde_Imap_Client_Ids $ids)
|
||||
{
|
||||
if ($ids->all) {
|
||||
return $this->_ids;
|
||||
} elseif ($ids->sequence) {
|
||||
return array_intersect_key($this->_ids, array_flip($ids->ids));
|
||||
}
|
||||
|
||||
return array_intersect($this->_ids, $ids->ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes messages from the ID mapping.
|
||||
*
|
||||
* @param Horde_Imap_Client_Ids $ids IDs to remove.
|
||||
*/
|
||||
public function remove(Horde_Imap_Client_Ids $ids)
|
||||
{
|
||||
/* For sequence numbers, we need to reindex anytime we have an index
|
||||
* that appears equal to or after a previously seen index. If an IMAP
|
||||
* server is smart, it will expunge in reverse order instead. */
|
||||
if ($ids->sequence) {
|
||||
$remove = $ids->ids;
|
||||
} else {
|
||||
$ids->sort();
|
||||
$remove = array_reverse(array_keys($this->lookup($ids)));
|
||||
}
|
||||
|
||||
if (empty($remove)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->sort();
|
||||
|
||||
if (count($remove) == count($this->_ids) &&
|
||||
!array_diff($remove, array_keys($this->_ids))) {
|
||||
$this->_ids = array();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the minimum sequence number to remove. We know entries before
|
||||
* this are untouched so no need to process them multiple times. */
|
||||
$first = min($remove);
|
||||
$edit = $newids = array();
|
||||
foreach (array_keys($this->_ids) as $i => $seq) {
|
||||
if ($seq >= $first) {
|
||||
$i += (($seq == $first) ? 0 : 1);
|
||||
$newids = array_slice($this->_ids, 0, $i, true);
|
||||
$edit = array_slice($this->_ids, $i + (($seq == $first) ? 0 : 1), null, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($edit)) {
|
||||
foreach ($remove as $val) {
|
||||
$found = false;
|
||||
$tmp = array();
|
||||
|
||||
foreach (array_keys($edit) as $i => $seq) {
|
||||
if ($found) {
|
||||
$tmp[$seq - 1] = $edit[$seq];
|
||||
} elseif ($seq >= $val) {
|
||||
$tmp = array_slice($edit, 0, ($seq == $val) ? $i : $i + 1, true);
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
|
||||
$edit = $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_ids = $newids + $edit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the map.
|
||||
*/
|
||||
public function sort()
|
||||
{
|
||||
if (!$this->_sorted) {
|
||||
ksort($this->_ids, SORT_NUMERIC);
|
||||
$this->_sorted = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Countable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return count($this->_ids);
|
||||
}
|
||||
|
||||
/* IteratorAggregate method. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->_ids);
|
||||
}
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
public function unserialize($data)
|
||||
{
|
||||
$data = @unserialize($data);
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Cache version change.');
|
||||
}
|
||||
$this->__unserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
/* Sort before storing; provides more compressible representation. */
|
||||
$this->sort();
|
||||
|
||||
return [
|
||||
strval(new Horde_Imap_Client_Ids(array_keys($this->_ids))),
|
||||
strval(new Horde_Imap_Client_Ids(array_values($this->_ids)))
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __unserialize($data)
|
||||
{
|
||||
$keys = new Horde_Imap_Client_Ids($data[0]);
|
||||
$vals = new Horde_Imap_Client_Ids($data[1]);
|
||||
$this->_ids = array_combine($keys->ids, $vals->ids);
|
||||
|
||||
/* Guaranteed to be sorted if unserializing. */
|
||||
$this->_sorted = true;
|
||||
}
|
||||
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Wrapper around Ids object that correctly handles POP3 UID strings.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Ids_Pop3 extends Horde_Imap_Client_Ids
|
||||
{
|
||||
/**
|
||||
*/
|
||||
protected function _sort(&$ids)
|
||||
{
|
||||
/* There is no guarantee of POP3 UIDL order - IDs need to be unique,
|
||||
* but there is no requirement they need be incrementing. RFC
|
||||
* 1939[7] */
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a POP3 message sequence string.
|
||||
*
|
||||
* Index Format: UID1[SPACE]UID2...
|
||||
*
|
||||
* @param boolean $sort Not used in this class.
|
||||
*
|
||||
* @return string The POP3 message sequence string.
|
||||
*/
|
||||
protected function _toSequenceString($sort = true)
|
||||
{
|
||||
/* $sort is ignored - see _sort(). */
|
||||
|
||||
/* Use space as delimiter as it is the only printable ASCII character
|
||||
* that is not allowed as part of the UID (RFC 1939 [7]). */
|
||||
return implode(' ', count($this->_ids) > 25000 ? array_unique($this->_ids) : array_keys(array_flip($this->_ids)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a POP3 message sequence string into a list of indices.
|
||||
*
|
||||
* @param string $str The POP3 message sequence string.
|
||||
*
|
||||
* @return array An array of UIDs.
|
||||
*/
|
||||
protected function _fromSequenceString($str)
|
||||
{
|
||||
return explode(' ', trim($str));
|
||||
}
|
||||
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object representing an IMAP client command interaction (RFC 3501
|
||||
* [2.2.1]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2016 Horde LLC
|
||||
* @deprecated
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Interaction_Client extends Horde_Imap_Client_Data_Format_List
|
||||
{
|
||||
/**
|
||||
* The command tag.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $tag;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $tag The tag to use. If not set, will be automatically
|
||||
* generated.
|
||||
*/
|
||||
public function __construct($tag = null)
|
||||
{
|
||||
$this->tag = is_null($tag)
|
||||
? substr(strval(new Horde_Support_Randomid()), 0, 10)
|
||||
: strval($tag);
|
||||
|
||||
parent::__construct($this->tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the command.
|
||||
*
|
||||
* @return string The command.
|
||||
*/
|
||||
public function getCommand()
|
||||
{
|
||||
return isset($this->_data[1])
|
||||
? $this->_data[1]
|
||||
: null;
|
||||
}
|
||||
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object representing an IMAP command (RFC 3501 [2.2.1]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.10.0
|
||||
*
|
||||
* @property-read boolean $continuation True if the command requires a server
|
||||
* continuation response.
|
||||
*/
|
||||
class Horde_Imap_Client_Interaction_Command
|
||||
extends Horde_Imap_Client_Data_Format_List
|
||||
{
|
||||
/**
|
||||
* Debug string(s) to use instead of command text.
|
||||
*
|
||||
* Multiple entries refer to the various steps in a continuation command.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $debug = array();
|
||||
|
||||
/**
|
||||
* Use LITERAL+ if available
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $literalplus = true;
|
||||
|
||||
/**
|
||||
* Are literal8's available?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $literal8 = false;
|
||||
|
||||
/**
|
||||
* A callback to run on error.
|
||||
*
|
||||
* If callback returns true, the command will be treated as successful.
|
||||
*
|
||||
* @since 2.24.0
|
||||
*
|
||||
* @var callback
|
||||
*/
|
||||
public $on_error = null;
|
||||
|
||||
/**
|
||||
* A callback to run on success.
|
||||
*
|
||||
* @since 2.28.0
|
||||
*
|
||||
* @var callback
|
||||
*/
|
||||
public $on_success = null;
|
||||
|
||||
/**
|
||||
* Pipeline object associated with this command.
|
||||
*
|
||||
* @since 2.28.0
|
||||
*
|
||||
* @var Horde_Imap_Client_Interaction_Pipeline
|
||||
*/
|
||||
public $pipeline;
|
||||
|
||||
/**
|
||||
* Server response.
|
||||
*
|
||||
* @var Horde_Imap_Client_Interaction_Server
|
||||
*/
|
||||
public $response;
|
||||
|
||||
/**
|
||||
* The command tag.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $tag;
|
||||
|
||||
/**
|
||||
* Command timer.
|
||||
*
|
||||
* @var Horde_Support_Timer
|
||||
*/
|
||||
protected $_timer;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $cmd The IMAP command.
|
||||
* @param string $tag The tag to use. If not set, will be automatically
|
||||
* generated.
|
||||
*/
|
||||
public function __construct($cmd, $tag = null)
|
||||
{
|
||||
$this->tag = is_null($tag)
|
||||
? substr(new Horde_Support_Randomid(), 0, 10)
|
||||
: strval($tag);
|
||||
|
||||
parent::__construct($this->tag);
|
||||
|
||||
$this->add($cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'continuation':
|
||||
return $this->_continuationCheck($this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the command.
|
||||
*
|
||||
* @return string The command.
|
||||
*/
|
||||
public function getCommand()
|
||||
{
|
||||
return $this->_data[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the command timer.
|
||||
*/
|
||||
public function startTimer()
|
||||
{
|
||||
$this->_timer = new Horde_Support_Timer();
|
||||
$this->_timer->push();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the timer data.
|
||||
*
|
||||
* @return mixed Null if timer wasn't started, or a float containing
|
||||
* elapsed command time.
|
||||
*/
|
||||
public function getTimer()
|
||||
{
|
||||
return $this->_timer
|
||||
? round($this->_timer->pop(), 4)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive check for continuation functions.
|
||||
*/
|
||||
protected function _continuationCheck($list)
|
||||
{
|
||||
foreach ($list as $val) {
|
||||
if (($val instanceof Horde_Imap_Client_Interaction_Command_Continuation) ||
|
||||
(($val instanceof Horde_Imap_Client_Data_Format_String) &&
|
||||
$val->literal())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (($val instanceof Horde_Imap_Client_Data_Format_List) &&
|
||||
$this->_continuationCheck($val)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2013-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object representing a portion of an IMAP command that requires data
|
||||
* sent in a continuation response (RFC 3501 [2.2.1]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.10.0
|
||||
*/
|
||||
class Horde_Imap_Client_Interaction_Command_Continuation
|
||||
{
|
||||
/**
|
||||
* Is this an optional continuation request?
|
||||
*
|
||||
* @since 2.13.0
|
||||
* @var boolean
|
||||
*/
|
||||
public $optional = false;
|
||||
|
||||
/**
|
||||
* Closure function to run after continuation response.
|
||||
*
|
||||
* @var Closure
|
||||
*/
|
||||
protected $_closure;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Closure $closure A function to run after the continuation
|
||||
* response is received. It receives one
|
||||
* argument - a Continuation object - and should
|
||||
* return a list of arguments to send to the
|
||||
* server (via a
|
||||
* Horde_Imap_Client_Data_Format_List object).
|
||||
*/
|
||||
public function __construct($closure)
|
||||
{
|
||||
$this->_closure = $closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the closure object.
|
||||
*
|
||||
* @param Horde_Imap_Client_Interaction_Server_Continuation $ob Continuation
|
||||
* object.
|
||||
*
|
||||
* @return Horde_Imap_Client_Data_Format_List Further commands to issue
|
||||
* to the server.
|
||||
*/
|
||||
public function getCommands(
|
||||
Horde_Imap_Client_Interaction_Server_Continuation $ob
|
||||
)
|
||||
{
|
||||
$closure = $this->_closure;
|
||||
return $closure($ob);
|
||||
}
|
||||
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2013-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object representing a series of IMAP client commands (RFC 3501 [2.2.1])
|
||||
* to be processed at the same time.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2013-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.10.0
|
||||
*
|
||||
* @property-read boolean $finished True if all commands have finished.
|
||||
*/
|
||||
class Horde_Imap_Client_Interaction_Pipeline implements Countable, IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Data storage from server responses.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $data = array(
|
||||
'modseqs' => array(),
|
||||
'modseqs_nouid' => array()
|
||||
);
|
||||
|
||||
/**
|
||||
* Fetch results.
|
||||
*
|
||||
* @var Horde_Imap_Client_Fetch_Results
|
||||
*/
|
||||
public $fetch;
|
||||
|
||||
/**
|
||||
* The list of commands.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_commands = array();
|
||||
|
||||
/**
|
||||
* The list of commands to complete.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_todo = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Horde_Imap_Client_Fetch_Results $fetch Fetch results object.
|
||||
*/
|
||||
public function __construct(Horde_Imap_Client_Fetch_Results $fetch)
|
||||
{
|
||||
$this->fetch = $fetch;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'finished':
|
||||
return empty($this->_todo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a command to the pipeline.
|
||||
*
|
||||
* @param Horde_Imap_Client_Interaction_Command $cmd Command object.
|
||||
* @param boolean $top Add command to top
|
||||
* of queue?
|
||||
*/
|
||||
public function add(Horde_Imap_Client_Interaction_Command $cmd,
|
||||
$top = false)
|
||||
{
|
||||
if ($top) {
|
||||
// This won't re-index keys, which may be numerical.
|
||||
$this->_commands = array($cmd->tag => $cmd) + $this->_commands;
|
||||
} else {
|
||||
$this->_commands[$cmd->tag] = $cmd;
|
||||
}
|
||||
$this->_todo[$cmd->tag] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a command as completed.
|
||||
*
|
||||
* @param Horde_Imap_Client_Interaction_Server_Tagged $resp Tagged server
|
||||
* response.
|
||||
*
|
||||
* @return Horde_Imap_Client_Interaction_Command Command that was
|
||||
* completed. Returns null
|
||||
* if tagged response
|
||||
* is not contained in this
|
||||
* pipeline object.
|
||||
*/
|
||||
public function complete(Horde_Imap_Client_Interaction_Server_Tagged $resp)
|
||||
{
|
||||
if (isset($this->_commands[$resp->tag])) {
|
||||
$cmd = $this->_commands[$resp->tag];
|
||||
$cmd->response = $resp;
|
||||
unset($this->_todo[$resp->tag]);
|
||||
} else {
|
||||
/* This can be reached if a previous pipeline action was aborted,
|
||||
* e.g. via an Exception. */
|
||||
$cmd = null;
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the command for a given tag.
|
||||
*
|
||||
* @param string $tag The command tag.
|
||||
*
|
||||
* @return Horde_Imap_Client_Interaction_Command A command object (or
|
||||
* null if the tag does
|
||||
* not exist).
|
||||
*/
|
||||
public function getCmd($tag)
|
||||
{
|
||||
return isset($this->_commands[$tag])
|
||||
? $this->_commands[$tag]
|
||||
: null;
|
||||
}
|
||||
|
||||
/* Countable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return count($this->_commands);
|
||||
}
|
||||
|
||||
/* IteratorAggregate methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->_commands);
|
||||
}
|
||||
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object representing an IMAP server command interaction (RFC 3501
|
||||
* [2.2.2]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Interaction_Server
|
||||
{
|
||||
/**
|
||||
* Response codes (RFC 3501 [7.1]).
|
||||
*/
|
||||
const BAD = 1;
|
||||
const BYE = 2;
|
||||
const NO = 3;
|
||||
const OK = 4;
|
||||
const PREAUTH = 5;
|
||||
|
||||
/**
|
||||
* Check for status response?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_checkStatus = true;
|
||||
|
||||
/**
|
||||
* Response code (RFC 3501 [7.1]). Properties:
|
||||
* - code: (string) Response code.
|
||||
* - data: (array) Data associated with response.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $responseCode = null;
|
||||
|
||||
/**
|
||||
* Status response from the server.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $status = null;
|
||||
|
||||
/**
|
||||
* IMAP server data.
|
||||
*
|
||||
* @var Horde_Imap_Client_Tokenize
|
||||
*/
|
||||
public $token;
|
||||
|
||||
/**
|
||||
* Auto-scan an incoming line to determine the response type.
|
||||
*
|
||||
* @param Horde_Imap_Client_Tokenize $t Tokenized data returned from the
|
||||
* server.
|
||||
*
|
||||
* @return Horde_Imap_Client_Interaction_Server A server response object.
|
||||
*/
|
||||
public static function create(Horde_Imap_Client_Tokenize $t)
|
||||
{
|
||||
$t->rewind();
|
||||
$tag = $t->next();
|
||||
$t->next();
|
||||
|
||||
switch ($tag) {
|
||||
case '+':
|
||||
return new Horde_Imap_Client_Interaction_Server_Continuation($t);
|
||||
|
||||
case '*':
|
||||
return new Horde_Imap_Client_Interaction_Server_Untagged($t);
|
||||
|
||||
default:
|
||||
return new Horde_Imap_Client_Interaction_Server_Tagged($t, $tag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Horde_Imap_Client_Tokenize $token Tokenized data returned from
|
||||
* the server.
|
||||
*/
|
||||
public function __construct(Horde_Imap_Client_Tokenize $token)
|
||||
{
|
||||
$this->token = $token;
|
||||
|
||||
/* Check for response status. */
|
||||
$status = $token->current();
|
||||
$valid = array('BAD', 'BYE', 'NO', 'OK', 'PREAUTH');
|
||||
|
||||
if (in_array($status, $valid)) {
|
||||
$this->status = constant(__CLASS__ . '::' . $status);
|
||||
$resp_text = $token->next();
|
||||
|
||||
/* Check for response code. Only occurs if there is a response
|
||||
* status. */
|
||||
if (is_string($resp_text) && ($resp_text[0] === '[')) {
|
||||
$resp = new stdClass;
|
||||
$resp->data = array();
|
||||
|
||||
if ($resp_text[strlen($resp_text) - 1] === ']') {
|
||||
$resp->code = substr($resp_text, 1, -1);
|
||||
} else {
|
||||
$resp->code = substr($resp_text, 1);
|
||||
|
||||
while (($elt = $token->next()) !== false) {
|
||||
if (is_string($elt) && $elt[strlen($elt) - 1] === ']') {
|
||||
$resp->data[] = substr($elt, 0, -1);
|
||||
break;
|
||||
}
|
||||
$resp->data[] = is_string($elt)
|
||||
? $elt
|
||||
: $token->flushIterator();
|
||||
}
|
||||
}
|
||||
|
||||
$token->next();
|
||||
$this->responseCode = $resp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return strval($this->token);
|
||||
}
|
||||
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object representing an IMAP continuation response (RFC 3501 [2.2.2]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Interaction_Server_Continuation extends Horde_Imap_Client_Interaction_Server
|
||||
{
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object representing an IMAP tagged response (RFC 3501 [2.2.2]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Interaction_Server_Tagged
|
||||
extends Horde_Imap_Client_Interaction_Server
|
||||
{
|
||||
/**
|
||||
* Tag.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $tag;
|
||||
|
||||
/**
|
||||
* @param string $tag Response tag.
|
||||
*/
|
||||
public function __construct(Horde_Imap_Client_Tokenize $token, $tag)
|
||||
{
|
||||
$this->tag = $tag;
|
||||
|
||||
parent::__construct($token);
|
||||
|
||||
if (is_null($this->status)) {
|
||||
throw new Horde_Imap_Client_Exception(
|
||||
Horde_Imap_Client_Translation::r("Bad tagged response.")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object representing an IMAP untagged response (RFC 3501 [2.2.2]).
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2012-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Interaction_Server_Untagged extends Horde_Imap_Client_Interaction_Server
|
||||
{
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* An object that provides a way to switch between UTF7-IMAP and
|
||||
* human-readable representations of a mailbox name.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2011-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*
|
||||
* @property-read string $list_escape Escapes mailbox for use in LIST
|
||||
* command (UTF-8).
|
||||
* @property-read string $utf7imap Mailbox in UTF7-IMAP.
|
||||
* @property-read string $utf8 Mailbox in UTF-8.
|
||||
*/
|
||||
class Horde_Imap_Client_Mailbox implements Serializable
|
||||
{
|
||||
/**
|
||||
* UTF7-IMAP representation of mailbox.
|
||||
* If boolean true, it is identical to UTF-8 representation.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $_utf7imap;
|
||||
|
||||
/**
|
||||
* UTF8 representation of mailbox.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_utf8;
|
||||
|
||||
/**
|
||||
* Shortcut to obtaining mailbox object.
|
||||
*
|
||||
* @param string $mbox The mailbox name.
|
||||
* @param boolean $utf7imap Is mailbox UTF7-IMAP encoded? Otherwise,
|
||||
* mailbox is assumed to be UTF-8.
|
||||
*
|
||||
* @return Horde_Imap_Client_Mailbox A mailbox object.
|
||||
*/
|
||||
public static function get($mbox, $utf7imap = false)
|
||||
{
|
||||
return ($mbox instanceof Horde_Imap_Client_Mailbox)
|
||||
? $mbox
|
||||
: new Horde_Imap_Client_Mailbox($mbox, $utf7imap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $mbox The mailbox name.
|
||||
* @param boolean $utf7imap Is mailbox UTF7-IMAP encoded (true).
|
||||
* Otherwise, mailbox is assumed to be UTF-8
|
||||
* encoded.
|
||||
*/
|
||||
public function __construct($mbox, $utf7imap = false)
|
||||
{
|
||||
if (strcasecmp($mbox, 'INBOX') === 0) {
|
||||
$mbox = 'INBOX';
|
||||
}
|
||||
|
||||
if ($utf7imap) {
|
||||
$this->_utf7imap = $mbox;
|
||||
} else {
|
||||
$this->_utf8 = $mbox;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'list_escape':
|
||||
return preg_replace("/\*+/", '%', $this->utf8);
|
||||
|
||||
case 'utf7imap':
|
||||
if (!isset($this->_utf7imap)) {
|
||||
$n = Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($this->_utf8);
|
||||
$this->_utf7imap = ($n == $this->_utf8)
|
||||
? true
|
||||
: $n;
|
||||
}
|
||||
|
||||
return ($this->_utf7imap === true)
|
||||
? $this->_utf8
|
||||
: $this->_utf7imap;
|
||||
|
||||
case 'utf8':
|
||||
if (!isset($this->_utf8)) {
|
||||
$this->_utf8 = Horde_Imap_Client_Utf7imap::Utf7ImapToUtf8($this->_utf7imap);
|
||||
if ($this->_utf8 == $this->_utf7imap) {
|
||||
$this->_utf7imap = true;
|
||||
}
|
||||
}
|
||||
return (string)$this->_utf8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->utf8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this mailbox to another mailbox string.
|
||||
*
|
||||
* @return boolean True if the items are equal.
|
||||
*/
|
||||
public function equals($mbox)
|
||||
{
|
||||
return ($this->utf8 == $mbox);
|
||||
}
|
||||
|
||||
/* Serializable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function unserialize($data)
|
||||
{
|
||||
$data = @unserialize($data);
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Cache value changed.');
|
||||
}
|
||||
$this->__unserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return [$this->_utf7imap, $this->_utf8];
|
||||
}
|
||||
|
||||
public function __unserialize(array $data)
|
||||
{
|
||||
list($this->_utf7imap, $this->_utf8) = $data;
|
||||
}
|
||||
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2004-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2004-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* Container of IMAP mailboxes.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2004-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
class Horde_Imap_Client_Mailbox_List implements Countable, IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* The delimiter character to use.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_delimiter;
|
||||
|
||||
/**
|
||||
* Mailbox list.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_mboxes = array();
|
||||
|
||||
/**
|
||||
* Should we sort with INBOX at the front of the list?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_sortinbox;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $mboxes A mailbox or list of mailboxes.
|
||||
*/
|
||||
public function __construct($mboxes)
|
||||
{
|
||||
$this->_mboxes = is_array($mboxes)
|
||||
? $mboxes
|
||||
: array($mboxes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the list of mailboxes.
|
||||
*
|
||||
* @param array $opts Options:
|
||||
* - delimiter: (string) The delimiter to use.
|
||||
* DEFAULT: '.'
|
||||
* - inbox: (boolean) Always put INBOX at the head of the list?
|
||||
* DEFAULT: Yes
|
||||
* - noupdate: (boolean) Do not update the object's mailbox list?
|
||||
* DEFAULT: true
|
||||
*
|
||||
* @return array List of sorted mailboxes (index association is kept).
|
||||
*/
|
||||
public function sort(array $opts = array())
|
||||
{
|
||||
$this->_delimiter = isset($opts['delimiter'])
|
||||
? $opts['delimiter']
|
||||
: '.';
|
||||
$this->_sortinbox = (!isset($opts['inbox']) || !empty($opts['inbox']));
|
||||
|
||||
if (empty($opts['noupdate'])) {
|
||||
$mboxes = &$this->_mboxes;
|
||||
} else {
|
||||
$mboxes = $this->_mboxes;
|
||||
}
|
||||
|
||||
uasort($mboxes, array($this, '_mboxCompare'));
|
||||
|
||||
return $mboxes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hierarchical folder sorting function (used with usort()).
|
||||
*
|
||||
* @param string $a Comparison item 1.
|
||||
* @param string $b Comparison item 2.
|
||||
*
|
||||
* @return integer See usort().
|
||||
*/
|
||||
final protected function _mboxCompare($a, $b)
|
||||
{
|
||||
/* Always return INBOX as "smaller". */
|
||||
if ($this->_sortinbox) {
|
||||
if (strcasecmp($a, 'INBOX') === 0) {
|
||||
return -1;
|
||||
} elseif (strcasecmp($b, 'INBOX') === 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
$a_parts = explode($this->_delimiter, $a);
|
||||
$b_parts = explode($this->_delimiter, $b);
|
||||
|
||||
$a_count = count($a_parts);
|
||||
$b_count = count($b_parts);
|
||||
|
||||
for ($i = 0, $iMax = min($a_count, $b_count); $i < $iMax; ++$i) {
|
||||
if ($a_parts[$i] != $b_parts[$i]) {
|
||||
/* If only one of the folders is under INBOX, return it as
|
||||
* "smaller". */
|
||||
if ($this->_sortinbox && ($i === 0)) {
|
||||
$a_base = (strcasecmp($a_parts[0], 'INBOX') === 0);
|
||||
$b_base = (strcasecmp($b_parts[0], 'INBOX') === 0);
|
||||
if ($a_base && !$b_base) {
|
||||
return -1;
|
||||
} elseif (!$a_base && $b_base) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
$cmp = strnatcasecmp($a_parts[$i], $b_parts[$i]);
|
||||
return ($cmp === 0)
|
||||
? strcmp($a_parts[$i], $b_parts[$i])
|
||||
: $cmp;
|
||||
} elseif ($a_parts[$i] !== $b_parts[$i]) {
|
||||
return strlen($a_parts[$i]) - strlen($b_parts[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
return ($a_count - $b_count);
|
||||
}
|
||||
|
||||
/* Countable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return count($this->_mboxes);
|
||||
}
|
||||
|
||||
/* IteratorAggregate methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->_mboxes);
|
||||
}
|
||||
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright 2014-2017 Horde LLC (http://www.horde.org/)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPL). If you
|
||||
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
||||
*
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
*/
|
||||
|
||||
/**
|
||||
* List of namespaces.
|
||||
*
|
||||
* @author Michael Slusarz <slusarz@horde.org>
|
||||
* @category Horde
|
||||
* @copyright 2014-2017 Horde LLC
|
||||
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
||||
* @package Imap_Client
|
||||
* @since 2.21.0
|
||||
*/
|
||||
class Horde_Imap_Client_Namespace_List
|
||||
implements ArrayAccess, Countable, IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* The list of namespace objects.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_ns = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $ns The list of namespace objects.
|
||||
*/
|
||||
public function __construct($ns = array())
|
||||
{
|
||||
foreach ($ns as $val) {
|
||||
$this->_ns[strval($val)] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get namespace info for a full mailbox path.
|
||||
*
|
||||
* @param string $mbox The mailbox path.
|
||||
* @param boolean $personal If true, will return the empty namespace only
|
||||
* if it is a personal namespace.
|
||||
*
|
||||
* @return mixed The Horde_Imap_Client_Data_Namespace object for the
|
||||
* mailbox path, or null if the path doesn't exist.
|
||||
*/
|
||||
public function getNamespace($mbox, $personal = false)
|
||||
{
|
||||
$mbox = strval($mbox);
|
||||
|
||||
if ($ns = $this[$mbox]) {
|
||||
return $ns;
|
||||
}
|
||||
|
||||
foreach ($this->_ns as $val) {
|
||||
$mbox = $mbox . $val->delimiter;
|
||||
if (strlen($val->name) && (strpos($mbox, $val->name) === 0)) {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
|
||||
return (($ns = $this['']) && (!$personal || ($ns->type === $ns::NS_PERSONAL)))
|
||||
? $ns
|
||||
: null;
|
||||
}
|
||||
|
||||
/* ArrayAccess methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->_ns[strval($offset)]);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
$offset = strval($offset);
|
||||
|
||||
return isset($this->_ns[$offset])
|
||||
? $this->_ns[$offset]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if ($value instanceof Horde_Imap_Client_Data_Namespace) {
|
||||
$this->_ns[strval($value)] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->_ns[strval($offset)]);
|
||||
}
|
||||
|
||||
/* Countable methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return count($this->_ns);
|
||||
}
|
||||
|
||||
/* IteratorAggregate methods. */
|
||||
|
||||
/**
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->_ns);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user