364 lines
11 KiB
PHP
364 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* The Serialize:: class provides various methods of encapsulating data.
|
|
*
|
|
* Copyright 2001-2016 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* See the enclosed file COPYING for license information (LGPL). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
|
*
|
|
* @author Stephane Huther <shuther1@free.fr>
|
|
* @author Michael Slusarz <slusarz@horde.org>
|
|
* @package Serialize
|
|
* @category Horde
|
|
*/
|
|
class Horde_Serialize
|
|
{
|
|
/* Type constants */
|
|
const UNKNOWN = -1;
|
|
const NONE = 0;
|
|
const WDDX = 1;
|
|
const BZIP = 2;
|
|
const IMAP8 = 3;
|
|
const IMAPUTF7 = 4;
|
|
const IMAPUTF8 = 5;
|
|
const BASIC = 6;
|
|
const GZ_DEFLATE = 7;
|
|
const GZ_COMPRESS = 8;
|
|
const GZ_ENCODE = 9;
|
|
const BASE64 = 10;
|
|
const RAW = 12;
|
|
const URL = 13;
|
|
const UTF7 = 14;
|
|
const UTF7_BASIC = 15;
|
|
const JSON = 16;
|
|
const LZF = 17;
|
|
|
|
/**
|
|
* Serialize a value.
|
|
*
|
|
* See the list of constants at the top of the file for the serializing
|
|
* techniques that can be used.
|
|
*
|
|
* @param mixed $data The data to be serialized.
|
|
* @param mixed $mode The mode of serialization. Can be either a single
|
|
* mode or array of modes. If array, will be
|
|
* serialized in the order provided.
|
|
* @param mixed $params Any additional parameters the serialization method
|
|
* requires.
|
|
*
|
|
* @return string The serialized data.
|
|
* @throws Horde_Serialize_Exception
|
|
*/
|
|
public static function serialize($data, $mode = array(self::BASIC),
|
|
$params = null)
|
|
{
|
|
if (!is_array($mode)) {
|
|
$mode = array($mode);
|
|
}
|
|
|
|
/* Parse through the list of serializing modes. */
|
|
foreach ($mode as $val) {
|
|
/* Check to make sure the mode is supported. */
|
|
if (!self::hasCapability($val)) {
|
|
throw new Horde_Serialize_Exception('Unsupported serialization type');
|
|
}
|
|
$data = self::_serialize($data, $val, $params);
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Unserialize a value.
|
|
*
|
|
* See the list of constants at the top of the file for the serializing
|
|
* techniques that can be used.
|
|
*
|
|
* @param mixed $data The data to be unserialized.
|
|
* @param mixed $mode The mode of unserialization. Can be either a
|
|
* single mode or array of modes. If array, will be
|
|
* unserialized in the order provided.
|
|
* @param mixed $params Any additional parameters the unserialization
|
|
* method requires.
|
|
*
|
|
* @return string The unserialized data.
|
|
* @throws Horde_Serialize_Exception
|
|
*/
|
|
public static function unserialize($data, $mode = self::BASIC,
|
|
$params = null)
|
|
{
|
|
if (!is_array($mode)) {
|
|
$mode = array($mode);
|
|
}
|
|
|
|
/* Parse through the list of unserializing modes. */
|
|
foreach ($mode as $val) {
|
|
/* Check to make sure the mode is supported. */
|
|
if (!self::hasCapability($val)) {
|
|
throw new Horde_Serialize_Exception('Unsupported unserialization type');
|
|
}
|
|
$data = self::_unserialize($data, $val, $params);
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Check whether or not a serialization method is supported.
|
|
*
|
|
* @param integer $mode The serialization method.
|
|
*
|
|
* @return boolean True if supported, false if not.
|
|
*/
|
|
public static function hasCapability($mode)
|
|
{
|
|
switch ($mode) {
|
|
case self::BZIP:
|
|
return Horde_Util::extensionExists('bz2');
|
|
|
|
case self::WDDX:
|
|
return Horde_Util::extensionExists('wddx');
|
|
|
|
case self::IMAPUTF7:
|
|
return class_exists('Horde_Imap_Client');
|
|
|
|
case self::IMAPUTF8:
|
|
return class_exists('Horde_Mime');
|
|
|
|
case self::GZ_DEFLATE:
|
|
case self::GZ_COMPRESS:
|
|
case self::GZ_ENCODE:
|
|
return Horde_Util::extensionExists('zlib');
|
|
|
|
case self::LZF:
|
|
return Horde_Util::extensionExists('lzf');
|
|
|
|
case self::NONE:
|
|
case self::BASIC:
|
|
case self::BASE64:
|
|
case self::IMAP8:
|
|
case self::RAW:
|
|
case self::URL:
|
|
case self::UTF7:
|
|
case self::UTF7_BASIC:
|
|
case self::JSON:
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Serialize data.
|
|
*
|
|
* @param mixed $data The data to be serialized.
|
|
* @param mixed $mode The mode of serialization. Can be
|
|
* either a single mode or array of modes.
|
|
* If array, will be serialized in the
|
|
* order provided.
|
|
* @param mixed $params Any additional parameters the serialization method
|
|
* requires.
|
|
*
|
|
* @return string A serialized string.
|
|
* @throws Horde_Serialize_Exception
|
|
*/
|
|
protected static function _serialize($data, $mode, $params = null)
|
|
{
|
|
switch ($mode) {
|
|
case self::NONE:
|
|
break;
|
|
|
|
// $params['level'] = Level of compression (default: 3)
|
|
// $params['workfactor'] = How does compression phase behave when given
|
|
// worst case, highly repetitive, input data
|
|
// (default: 30)
|
|
case self::BZIP:
|
|
$data = bzcompress($data, isset($params['level']) ? $params['level'] : 3, isset($params['workfactor']) ? $params['workfactor'] : 30);
|
|
if (is_integer($data)) {
|
|
$data = false;
|
|
}
|
|
break;
|
|
|
|
case self::WDDX:
|
|
$data = wddx_serialize_value($data);
|
|
break;
|
|
|
|
case self::IMAP8:
|
|
$data = quoted_printable_encode($data);
|
|
break;
|
|
|
|
case self::IMAPUTF7:
|
|
$data = Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap(Horde_String::convertCharset($data, 'ISO-8859-1', 'UTF-8'));
|
|
break;
|
|
|
|
case self::IMAPUTF8:
|
|
$data = Horde_Mime::decode($data);
|
|
break;
|
|
|
|
// $params['level'] = Level of compression (default: 3)
|
|
case self::GZ_DEFLATE:
|
|
$data = gzdeflate($data, isset($params['level']) ? $params['level'] : 3);
|
|
break;
|
|
|
|
case self::BASIC:
|
|
$data = serialize($data);
|
|
break;
|
|
|
|
// $params['level'] = Level of compression (default: 3)
|
|
case self::GZ_COMPRESS:
|
|
$data = gzcompress($data, isset($params['level']) ? $params['level'] : 3);
|
|
break;
|
|
|
|
case self::BASE64:
|
|
$data = base64_encode($data);
|
|
break;
|
|
|
|
// $params['level'] = Level of compression (default: 3)
|
|
case self::GZ_ENCODE:
|
|
$data = gzencode($data, isset($params['level']) ? $params['level'] : 3);
|
|
break;
|
|
|
|
case self::RAW:
|
|
$data = rawurlencode($data);
|
|
break;
|
|
|
|
case self::URL:
|
|
$data = urlencode($data);
|
|
break;
|
|
|
|
// $params = Source character set
|
|
case self::UTF7:
|
|
$data = Horde_String::convertCharset($data, $params, 'UTF-7');
|
|
break;
|
|
|
|
// $params = Source character set
|
|
case self::UTF7_BASIC:
|
|
$data = self::serialize($data, array(self::UTF7, self::BASIC), $params);
|
|
break;
|
|
|
|
case self::JSON:
|
|
$tmp = json_encode($data);
|
|
|
|
/* Basic error handling attempts.
|
|
* TODO: JSON_ERROR_UTF8 = 5; available as of PHP 5.3.3 */
|
|
if (json_last_error() === 5) {
|
|
$data = json_encode(Horde_String::convertCharset($data, $params, 'UTF-8', true));
|
|
} else {
|
|
$data = $tmp;
|
|
}
|
|
break;
|
|
|
|
case self::LZF:
|
|
$data = lzf_compress($data);
|
|
break;
|
|
}
|
|
|
|
if ($data === false) {
|
|
throw new Horde_Serialize_Exception('Serialization failed.');
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Unserialize data.
|
|
*
|
|
* @param mixed $data The data to be unserialized.
|
|
* @param mixed $mode The mode of unserialization. Can be either a
|
|
* single mode or array of modes. If array, will be
|
|
* unserialized in the order provided.
|
|
* @param mixed $params Any additional parameters the unserialization
|
|
* method requires.
|
|
*
|
|
* @return mixed Unserialized data.
|
|
* @throws Horde_Serialize_Exception
|
|
*/
|
|
protected static function _unserialize(&$data, $mode, $params = null)
|
|
{
|
|
switch ($mode) {
|
|
case self::NONE:
|
|
break;
|
|
|
|
case self::RAW:
|
|
$data = rawurldecode($data);
|
|
break;
|
|
|
|
case self::URL:
|
|
$data = urldecode($data);
|
|
break;
|
|
|
|
case self::WDDX:
|
|
$data = wddx_deserialize($data);
|
|
break;
|
|
|
|
case self::BZIP:
|
|
// $params['small'] = Use bzip2 'small memory' mode?
|
|
$data = bzdecompress($data, isset($params['small']) ? $params['small'] : false);
|
|
break;
|
|
|
|
case self::IMAP8:
|
|
$data = quoted_printable_decode($data);
|
|
break;
|
|
|
|
case self::IMAPUTF7:
|
|
$data = Horde_String::convertCharset(Horde_Imap_Client_Utf7imap::Utf7ImapToUtf8($data), 'UTF-8', 'ISO-8859-1');
|
|
break;
|
|
|
|
case self::IMAPUTF8:
|
|
$data = Horde_Mime::encode($data);
|
|
break;
|
|
|
|
case self::BASIC:
|
|
$data2 = @unserialize($data);
|
|
// Unserialize can return false both on error and if $data is the
|
|
// false value.
|
|
if (($data2 === false) && ($data == serialize(false))) {
|
|
return $data2;
|
|
}
|
|
$data = $data2;
|
|
break;
|
|
|
|
case self::GZ_DEFLATE:
|
|
$data = gzinflate($data);
|
|
break;
|
|
|
|
case self::BASE64:
|
|
$data = base64_decode($data);
|
|
break;
|
|
|
|
case self::GZ_COMPRESS:
|
|
$data = gzuncompress($data);
|
|
break;
|
|
|
|
// $params = Output character set
|
|
case self::UTF7:
|
|
$data = Horde_String::convertCharset($data, 'utf-7', $params);
|
|
break;
|
|
|
|
// $params = Output character set
|
|
case self::UTF7_BASIC:
|
|
$data = self::unserialize($data, array(self::BASIC, self::UTF7), $params);
|
|
break;
|
|
|
|
case self::JSON:
|
|
$out = json_decode($data);
|
|
if (!is_null($out) || (strcasecmp($data, 'null') === 0)) {
|
|
return $out;
|
|
}
|
|
break;
|
|
|
|
case self::LZF:
|
|
$data = @lzf_decompress($data);
|
|
break;
|
|
}
|
|
|
|
if ($data === false) {
|
|
throw new Horde_Serialize_Exception('Unserialization failed.');
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
}
|