%PDF- %PDF-
| Direktori : /usr/local/prospamfilter/library/Cpanel/Parser/ |
| Current File : //usr/local/prospamfilter/library/Cpanel/Parser/JSON.php |
<?php
/**
* Cpanel_Parser_JSON
*
* Copyright (c) 2011, cPanel, Inc.
* All rights reserved.
* http://cpanel.net
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of cPanel, Inc. nor the
* names of its contributors may 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 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 Cpanel
* @package Cpanel_Parser
* @author David Neimeyer <david.neimeyer@cpanel.net>
* @copyright Copyright (c) 2011, cPanel, Inc., All rights Reserved. (http://cpanel.net)
* @license http://sdk.cpanel.net/license/bsd.html BSD License
* @version 0.1.0
* @link http://sdk.cpanel.net
* @since 0.1.0
*/
/**
* JSON Parser
*
* @class Cpanel_Parser_JSON
* @category Cpanel
* @package Cpanel_Parser
* @author David Neimeyer <david.neimeyer@cpanel.net>
* @copyright Copyright (c) 2011, cPanel, Inc., All rights Reserved. (http://cpanel.net)
* @license http://sdk.cpanel.net/license/bsd.html BSD License
* @version 0.1.0
* @link http://sdk.cpanel.net
* @since 0.1.0
*/
class Cpanel_Parser_JSON extends Cpanel_Core_Object
implements Cpanel_Parser_Interface
{
/**
* Value for standard JSON print; no additional whitespace or line breaking
* characters
*/
const CONDENSED_MODE = 1;
/**
* Value for JSON print with whitespace and line breaking characters
*/
const EXPANDED_MODE = 2;
/**
* Response format type that this parser can encode/decode
*/
const PARSER_TYPE = 'JSON';
/**
* Generic prefix for parser error messaging
*/
const ERROR_DECODE = 'JSON Decode - ';
/**
* Observed encode/decode error
*/
private $_hasParseError;
/**
* Constructor
*
* By default, Cpanel_Parser_JSON::CONDENSED_MODE will be set
*
* @param array $optsArray Optional configuration data
*
* @return Cpanel_Parser_JSON
*/
public function __construct($optsArray = array())
{
parent::__construct($optsArray);
$mode = $this->getOption('mode');
$this->setMode(self::CONDENSED_MODE);
if ($mode) {
$this->setMode($mode);
}
return $this;
}
/**
* Determine if an RFT can be parsed with this parser
*
* @param string $type The name of a response format type to evaluate
*
* @see Cpanel_Parser_Interface::canParse()
*
* @return bool Whether this parser can parse a sting of $type
*/
public function canParse($type)
{
return (strtolower($type) == 'json') ? true : false;
}
/**
* Parse a string into an array structure
*
* NOTE: After basic validation, if the parser cannot successfully parse
* $str, internal property "_hasParseError" will be set to true. An error
* will NOT be throw. This is to ensure a premature exit does not occur
* since the query (likely) succeeded. Problem as this level are ambiguous,
* and therefore left to the invoking script/application to manage.
*
* @param string $str String to parse
*
* @see Cpanel_Parser_JSON::getParserInternalErrors
* @see Cpanel_Parser_Interface::parse()
*
* @return array|string Array representation of string on success,
* otherwise a string expressing error.
* @throws Exception If $str is not a string
*/
public function parse($str)
{
if (!is_string($str)) {
throw new Exception('Input must be a raw response string');
} elseif (empty($str)) {
$this->_hasParseError = true;
return $this->getParserInternalErrors(
self::ERROR_DECODE, 'Cannot decode empty string.'
);
}
/**
* @see https://trac.spamexperts.com/ticket/18188
*/
if (function_exists('iconv')) {
$str = iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($str));
}
$r = json_decode($str, true);
if (is_null($r)) {
$this->_hasParseError = true;
return $this->getParserInternalErrors(self::ERROR_DECODE);
}
return $r;
}
/**
* Encode array structure into this parser's format type
*
* If Cpanel_Parser_JSON::EXPANDED_MODE was set via {@link setMode()}
* then the returned string will have excessive whitespace and line breaking
* characters
*
* NOTE: unlike {@link parse()}, this method WILL throw an Exception If
* encoding fails. There should be no ambiguity, if the response objects
* "_response" container has invalid data, there is a problem (that needs
* to be addressed by the script/application developer).
*
* @param Cpanel_Query_Object $obj Response object containing data to
* encode
*
* @see Cpanel_Parser_Interface::encodeQueryObject()
*
* @return string JSON string
* @throws Exception If $obj is an invalid response object
* @throws Exception If encoding fails
*/
public function encodeQueryObject($obj)
{
if (!($obj instanceof Cpanel_Query_Object)) {
throw new Exception('Parser can only encode known query object');
}
$arr = $obj->getResponse('array');
$jsonStr = '';
$msg = '';
try {
$jsonStr = json_encode($arr);
}
catch(Exception $e) {
$msg = ". " . $e->getMessage();
$msg.= '. Store data likely contains a resource' . ' or non-UTF8 string.';
}
if (!empty($msg) || empty($jsonStr)) {
throw new Exception('JSON encoding error for ' . __FUNCTION__ . $msg);
}
if ($this->mode == self::EXPANDED_MODE) {
$jsonStr = $this->prettyPrint($jsonStr);
}
return $jsonStr;
}
/**
* Generate an error string to bubble up
*
* If running on PHP >= 5.3, json_last_error() will be used to retrieve any
* relevant errors
*
* @param string $prefix A string to prefix the returned error string for
* contextual reference
* @param string $default A default error message if one can not be
* determined (from the native PHP JSON functions)
*
* @see Cpanel_Parser_Interface::getParserInternalErrors()
*
* @return string String detailing an error has occurred
*/
public function getParserInternalErrors($prefix = '', $default = ' Could not load string')
{
$errmsg = '';
if ($this->_hasParseError) {
$errmsg.= $prefix;
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
switch (json_last_error()) {
case JSON_ERROR_DEPTH:
//Parse do not support setting depth, but it's here anyway
//@codeCoverageIgnoreStart
$errmsg.= 'Maximum stack depth exceeded.';
break;
//@codeCoverageIgnoreEnd
case JSON_ERROR_CTRL_CHAR:
$errmsg.= 'Unexpected control character found.';
break;
case JSON_ERROR_SYNTAX:
$errmsg.= 'Syntax error, malformed JSON.';
break;
case JSON_ERROR_STATE_MISMATCH:
$errmsg.= 'Invalid or malformed JSON.';
break;
//@todo with 5.3.3 add JSON_ERROR_UTF8 to switch
case JSON_ERROR_NONE:
default:
$errmsg.= $default;
}
//@codeCoverageIgnoreStart
} else {
$errmsg.= $default;
}
//@codeCoverageIgnoreEnd
}
return $errmsg;
}
/**
* Pretty-print JSON string
*
* Use 'indent' option to select indentation string - by default it's a tab
*
* @param string $json Original JSON string
* @param array $options Encoding options
*
* @return string
*
* @category Zend
* @package Zend_Json
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id: Json.php 23775 2011-03-01 17:25:24Z ralph $
*/
public static function prettyPrint($json, $options = array())
{
$tokens = preg_split('|([\{\}\]\[,])|', $json, -1, PREG_SPLIT_DELIM_CAPTURE);
$result = "";
$indent = 0;
$ind = "\t";
if (isset($options['indent'])) {
$ind = $options['indent'];
}
foreach ($tokens as $token) {
if ($token == "") continue;
$prefix = str_repeat($ind, $indent);
if ($token == "{" || $token == "[") {
$indent++;
if ($result != "" && $result[strlen($result) - 1] == "\n") {
$result.= $prefix;
}
$result.= "$token\n";
} else if ($token == "}" || $token == "]") {
$indent--;
$prefix = str_repeat($ind, $indent);
$result.= "\n$prefix$token";
} else if ($token == ",") {
$result.= "$token\n";
} else {
$result.= $prefix . $token;
}
}
return $result;
}
/**
* Set special encode mode for JSON
*
* @param int $flag Constant value to set encoding mode to
*
* @see Cpanel_Parser_JSON::CONDENSED_MODE
* @see Cpanel_Parser_JSON::EXPANDED_MODE
*
* @return Cpanel_Parser_JSON
*/
public function setMode($flag)
{
if (empty($flag) || !is_int($flag)) {
$this->mode = self::CONDENSED_MODE;
} elseif ($flag == self::CONDENSED_MODE || $flag == self::EXPANDED_MODE) {
$this->mode = $flag;
}
return $this;
}
}
?>