MDL-16780, MDL-24058 removing PHP4 JSON implementation and related AJAX pear stuff that is not used any more - it is buggy, so we would have to either fix it (waste of time) or we have to remove it; no core code is using this and contrib can be easily updated to use standard json_encode()

This commit is contained in:
Petr Skoda 2010-09-02 12:27:47 +00:00
parent 8f46ae619c
commit c1c89e3b21
12 changed files with 0 additions and 2696 deletions

View File

@ -1,357 +0,0 @@
<?php
/**
* OO AJAX Implementation for PHP, contains HTML_AJAX_Action
*
* SVN Rev: $Id$
*
* @category HTML
* @package AJAX
* @author Elizabeth Smith <auroraeosrose@gmail.com>
* @copyright 2005-2008 Elizabeth Smith
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: 0.5.6
* @link http://htmlajax.org/HTML_AJAX/Using%20haSerializer
*/
/**
* Require the response class and json serializer
*/
require_once 'HTML/AJAX/Response.php';
require_once 'HTML/AJAX/Serializer/JSON.php';
/**
* Helper class to eliminate the need to write javascript functions to deal with data
*
* This class creates information that can be properly serialized and used by
* the haaction serializer which eliminates the need for php users to write
* javascript for dealing with the information returned by an ajax method -
* instead the javascript is basically created for them
*
* @category HTML
* @package AJAX
* @author Elizabeth Smith <auroraeosrose@gmail.com>
* @copyright 2005-2008 Elizabeth Smith
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: 0.5.6
* @link http://htmlajax.org/HTML_AJAX/Using%20haSerializer
*/
class HTML_AJAX_Action extends HTML_AJAX_Response
{
/**
* Content type for the HAA response
*
* goofy but unique content type to tell the javascript which deserializer to use
* overrides HTML_AJAX_Response
*
* @var string
* @access public
*/
var $contentType = 'application/html_ajax_action';
/**
* An array holding all the actions for the class
*
* these have numeric keys and each new action is added on the end, remember
* these are executed in the order added
*
* @var array
* @access private
*/
var $_actions = array();
/**
* Prepends data to the attribute identified by id
*
* The data will be added to the beginning of the attribute identified by the id
* sent, id must be unique
*
* $response->prependAttr('myid', 'class', 'red');
* $response->prependAttr('myid', array('class' => 'red', 'innerHTML' => 'this is an error'));
*
* @param string $id id for a specific item on the page <div id="myid"></div>
* @param string|array $attribute either an array of attribute/data pairs or a string attribute name
* @param mixed $data should be NULL if attribute is an array, otherwise data you wish to set the attribute to
*
* @return void
* @access public
*/
function prependAttr($id, $attribute, $data = null)
{
if (!is_null($data)) {
$attribute = array($attribute => $data);
}
$this->_actions[] = array(
'action' => 'prepend',
'id' => $id,
'attributes' => $attribute,
'data' => $data,
);
return;
}
/**
* Appends data to the attribute identified by id
*
* The data will be added to the end of the attribute identified by the id
* sent, id must be unique
*
* $response->appendAttr('myid', 'class', 'red');
* $response->appendAttr('myid', array('class' => 'red', 'innerHTML' => 'this is an error'));
*
* @param string $id id for a specific item on the page <div id="myid"></div>
* @param string|array $attribute either an array of attribute/data pairs or a string attribute name
* @param mixed $data should be NULL if attribute is an array, otherwise data you wish to set the attribute to
*
* @return void
* @access public
*/
function appendAttr($id, $attribute, $data = null)
{
if (!is_null($data)) {
$attribute = array($attribute => $data);
}
$this->_actions[] = array(
'action' => 'append',
'id' => $id,
'attributes' => $attribute,
);
return;
}
/**
* Assigns data to the attribute identified by id overwriting any previous values
*
* The data will be assigned to the attribute identified by the id
* sent, id must be unique
*
* $response->assignAttr('myid', 'class', 'red');
* $response->assignAttr('myid', array('class' => 'red', 'innerHTML' => 'this is an error'));
*
* @param string $id id for a specific item on the page <div id="myid"></div>
* @param string|array $attribute either an array of attribute/data pairs or a string attribute name
* @param mixed $data should be NULL if attribute is an array, otherwise data you wish to set the attribute to
*
* @return void
* @access public
*/
function assignAttr($id, $attribute, $data = null)
{
if (!is_null($data)) {
$attribute = array($attribute => $data);
}
$this->_actions[] = array(
'action' => 'assign',
'id' => $id,
'attributes' => $attribute,
);
return;
}
/**
* Deletes or assigns a value of an empty string to an attribute
*
* You may send either a single attribute or an array of attributes to clear
*
* $response->clearAttr('myid', 'class');
* $response->clearAttr('myid', array('class', 'innerHTML'));
*
* @param string $id id for a specific item on the page <div id="myid"></div>
* @param string|array $attribute either an array of attribute/data pairs or a string attribute name
*
* @return void
* @access public
*/
function clearAttr($id, $attribute)
{
if (!is_array($attribute)) {
$attribute = array($attribute);
}
$this->_actions[] = array(
'action' => 'clear',
'id' => $id,
'attributes' => $attribute,
);
return;
}
/**
* create a dom node via javascript
*
* higher level dom manipulation - creates a new node to insert into the dom
* You can control where the new node is inserted with two things, the insertion
* type and the id/ The type should be append, prepend, insertBefore, or insertAfter
*
* The id is a sibling node - like a div in the same div you want to add more to
* If you choose to append or prepend a node it will be placed at the beginning
* or end of the node with the id you send. If you choose insertBefore or
* InsertAfter it will be put right before or right after the node you specified.
* You can send an array of attributes to apply to the new node as well,
* so you don't have to create it and then assign Attributes.
*
* <code>
* $response->createNode('myid', 'div');
* $response->createNode('submit', 'input',
* array('id' => 'key',
* 'name' => 'key',
* 'type' => 'hidden',
* 'value' => $id),
* 'insertBefore');
* <code>
*
* @param string $id id for a specific item on the page <div id="myid"></div>
* @param string $tag html node to create
* @param array $attributes array of attribute -> data to fill the node with
* @param string $type append|prepend|insertBefore|insertAfter default is append
*
* @return void
* @access public
*/
function createNode($id, $tag, $attributes, $type = 'append')
{
$types = array('append', 'prepend', 'insertBefore', 'insertAfter');
if (!in_array($type, $types)) {
$type = 'append';
}
settype($attributes, 'array');
$this->_actions[] = array(
'action' => 'create',
'id' => $id,
'tag' => $tag,
'attributes' => $attributes,
'type' => $type,
);
return;
}
/**
* Replace a dom node via javascript
*
* higher level dom manipulation - replaces one node with another
* This can be used to replace a div with a form for inline editing
* use innerHtml attribute to change inside text
*
* $response->replaceNode('myid', 'div', array('innerHTML' => 'loading complete'));
* $response->replaceNode('mydiv', 'form', array('innerHTML' => $form));
*
* @param string $id id for a specific item on the page <div id="myid"></div>
* @param string $tag html node to create
* @param array $attributes array of attribute -> data to fill the node with
*
* @return void
* @access public
*/
function replaceNode($id, $tag, $attributes)
{
settype($attributes, 'array');
$this->_actions[] = array(
'action' => 'replace',
'id' => $id,
'tag' => $tag,
'attributes' => $attributes,
);
return;
}
/**
* Delete a dom node via javascript
*
* $response->removeNode('myid');
* $response->removeNode(array('mydiv', 'myform'));
*
* @param string $id id for a specific item on the page <div id="myid"></div>
*
* @return void
* @access public
*/
function removeNode($id)
{
$this->_actions[] = array(
'action' => 'remove',
'id' => $id,
);
return;
}
/**
* Send a string to a javascript eval
*
* This will send the data right to the eval javascript function, it will NOT
* allow you to dynamically add a javascript function for use later on because
* it is constrined by the eval function
*
* @param string $data string to pass to the alert javascript function
*
* @return void
* @access public
*/
function insertScript($data)
{
$this->_actions[] = array(
'action' => 'script',
'data' => $data,
);
return;
}
/**
* Send a string to a javascript alert
*
* This will send the data right to the alert javascript function
*
* @param string $data string to pass to the alert javascript function
*
* @return void
* @access public
*/
function insertAlert($data)
{
$this->_actions[] = array(
'action' => 'alert',
'data' => $data,
);
return;
}
/**
* Returns the serialized content of the response class
*
* we actually use the json serializer underneath, so we send the actions array
* to the json serializer and return the data
*
* @return string serialized response content
* @access public
*/
function getPayload()
{
$serializer = new HTML_AJAX_Serializer_JSON();
return $serializer->serialize($this->_actions);
}
/**
* Adds all the actions from one response object to another, feature request
* #6635 at pear.php.net
*
* @param object &$instance referenced HTML_AJAX_Action object
*
* @return array
* @access public
*/
function combineActions(&$instance)
{
$this->_actions = array_merge($this->_actions, $instance->retrieveActions());
}
/**
* to follow proper property access we need a way to retrieve the private
* actions array
*
* @return array
* @access public
*/
function retrieveActions()
{
return $this->_actions;
}
}
?>

View File

@ -1,144 +0,0 @@
<?php
/**
* AJAX Debugging implementation
*
* SVN Rev: $Id$
*/
/**
* Newline to use
*/
define ("HTML_AJAX_NEWLINE", "\n");
// {{{ class HTML_AJAX_Debug
/**
* AJAX Debugging implementation
*
* @category HTML
* @package AJAX
* @author David Coallier <davidc@php.net>
* @copyright 2005 David Coallier
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: 0.5.6
*/
class HTML_AJAX_Debug {
// {{{ properties
/**
* This is the error message.
*
* @access private
*/
var $errorMsg;
/**
* The line where the error occured.
*
* @access private
*/
var $errorLine;
/**
* The error code.
*
* @access private
*/
var $errorCode;
/**
* The file where the error occured.
*
* @access private
*/
var $errorFile;
/**
* Time the error occured
*
* @access private
*/
var $_timeOccured;
/**
* The whole error itself
*
* @access private
* @see errorMsg
* @see errorLine
* @see errorFile
* @see errorCode
*/
var $error;
/**
* The file to save the error to.
*
* @access private
* @default ajaxErrLog.xml
*/
var $file = 'ajaxErrLog.xml';
// }}}
// {{{ constructor
/**
* The constructor.
*
* @param string $errorMsg The error message.
* @param string $errLine The line where error occured.
* @param string $errCode The error Code.
* @param string $errFile The file where error occured.
*/
function HTML_AJAX_Debug($errMsg, $errLine, $errCode, $errFile)
{
$this->errorMsg = $errMsg;
$this->errorLine = $errLine;
$this->errorCode = $errCode;
$this->errorFile = $errFile;
$this->_timeOccured = date("Y-m-d H:i:s", time());
$this->xmlError();
}
// }}}
// {{{ xmlError
/**
* This functions formats the error to xml format then we can save it.
*
* @access protected
* @return $this->error the main error.
*/
function xmlError()
{
$error = " <when>{$this->_timeOccured}</when>" . HTML_AJAX_NEWLINE;
$error .= " <msg>{$this->errorMsg}</msg>" . HTML_AJAX_NEWLINE;
$error .= " <code>{$this->errorCode}</code>" . HTML_AJAX_NEWLINE;
$error .= " <line>{$this->errorLine}</line>" . HTML_AJAX_NEWLINE;
$error .= " <file>{$this->errorFile}</file>" . HTML_AJAX_NEWLINE . HTML_AJAX_NEWLINE;
return $this->error = $error;
}
// }}}
// {{{ sessionError
/**
* This function pushes the array $_SESSION['html_ajax_debug']['time'][]
* with the values inside of $this->error
*
* @access public
*/
function sessionError()
{
$_SESSION['html_ajax_debug']['time'][] = $this->error;
}
// }}}
// {{{ _saveError
/**
* This function saves the error to a file
* appending to this file.
*
* @access private.
*/
function _saveError()
{
if ($handle = fopen($this->file, 'a')) {
fwrite($handle, $this->error);
}
}
// }}}
}
// }}}
?>

View File

@ -1,186 +0,0 @@
<?php
/**
* HTML/JavaScript Generation Helper
*
* SVN Rev: $Id$
*
* @category HTML
* @package AJAX
* @author Joshua Eichorn <josh@bluga.net>
* @copyright 2005 Joshua Eichorn
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: 0.5.6
*/
/**
* HTML/JavaScript Generation Helper
*
* @category HTML
* @package AJAX
* @author Joshua Eichorn <josh@bluga.net>
* @copyright 2005 Joshua Eichorn
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: 0.5.6
* @link http://pear.php.net/package/HTML_AJAX
*/
class HTML_AJAX_Helper
{
/**
* URL where an HTML_AJAX_Server instance is serving up clients and taking ajax requests
*/
var $serverUrl = 'server.php';
/**
* JS libraries to include
*
* @var array
*/
var $jsLibraries = array('Util','Main','Request','HttpClient','Dispatcher','Behavior','Loading','JSON','iframe');
/**
* Remote class stubs to include
*/
var $stubs = array();
/**
* Combine jsLibraries into a single require and remove duplicates
*/
var $combineJsIncludes = false;
/**
* Include all needed libraries, stubs, and set defaultServer
*
* @return string
*/
function setupAJAX()
{
$libs = array(0=>array());
$combinedLibs = array();
$this->jsLibraries = array_unique($this->jsLibraries);
foreach($this->jsLibraries as $library) {
if (is_array($library)) {
$library = array_unique($library);
$combinedLibs = array_merge($combinedLibs,$library);
$libs[] = implode(',',$library);
}
else {
$libs[0][] = $library;
$combinedLibs[] = $library;
}
}
$libs[0] = implode(',',$libs[0]);
$sep = '?';
if (strstr($this->serverUrl,'?')) {
$sep = '&';
}
$ret = '';
if ($this->combineJsIncludes == true) {
$list = implode(',',$combinedLibs);
$ret .= "<script type='text/javascript' src='{$this->serverUrl}{$sep}client={$list}'></script>\n";
}
else {
foreach($libs as $list) {
$ret .= "<script type='text/javascript' src='{$this->serverUrl}{$sep}client={$list}'></script>\n";
}
}
if (count($this->stubs) > 0) {
$stubs = implode(',',$this->stubs);
$ret .= "<script type='text/javascript' src='{$this->serverUrl}{$sep}stub={$stubs}'></script>\n";
}
$ret .= $this->encloseInScript('HTML_AJAX.defaultServerUrl = '.$this->escape($this->serverUrl));
return $ret;
}
/**
* Create a custom Loading message
*
* @param string $body HTML body of the loading div
* @param string $class CSS class of the div
* @param string $style style tag of the loading div
*/
function loadingMessage($body, $class = 'HTML_AJAX_Loading',
$style = 'position: absolute; top: 0; right: 0; background-color: red; width: 80px; padding: 4px; display: none')
{
return "<div id='HTML_AJAX_LOADING' class='{$class}' style=\"{$style}\">{$body}</div>\n";
}
/**
* Update the contents of an element using ajax
*
* @param string $id id of the element to update
* @param string|array $update Either a url to update with or a array like array('class','method')
* @param string $type replace or append
* @param boolean $enclose
*/
function updateElement($id, $update, $type, $enclose = false) {
if (is_array($update)) {
$updateStr = "";
$comma = '';
foreach($update as $item) {
$updateStr .= $comma.$this->escape($item);
$comma = ',';
}
}
else {
$updateStr = $this->escape($update);
}
$ret = "HTML_AJAX.{$type}(".$this->escape($id).",{$updateStr});\n";
if ($enclose) {
$ret = $this->encloseInScript($ret);
}
return $ret;
}
/**
* Escape a string and add quotes allowing it to be a javascript paramater
*
* @param string $input
* @return string
* @todo do something here besides a quick hack
*/
function escape($input) {
return "'".addslashes($input)."'";
}
/**
* Enclose a string in a script block
*
* @param string $input
* @return string
*/
function encloseInScript($input) {
return '<script type="text/javascript">'.$input."</script>\n";
}
/**
* Generate a JSON String
*
* @param string $input
* @return string
*/
function jsonEncode($input) {
require_once 'HTML/AJAX/Serializer/JSON.php';
$s = new HTML_AJAX_Serializer_JSON();
return $s->serialize($input);
}
/**
* Check the request headers to see if this is an AJAX request
*
* @return boolean
*/
function isAJAX() {
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
return true;
}
return false;
}
}
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
?>

View File

@ -1,819 +0,0 @@
<?php
/**
* This is an embedded version of HTML_AJAX_JSON since it has yet to have
* a PEAR release it has been renamed to HTML_AJAX_JSON so no problems
* will be caused by an eventual release
* Feel free to report bugs against it to HTML_AJAX
*
* SVN Rev: $Id$
*/
/**
* Needed for compat functions
*/
require_once 'HTML/AJAX.php';
/**
* Converts to and from JSON format.
*
* JSON (JavaScript Object Notation) is a lightweight data-interchange
* format. It is easy for humans to read and write. It is easy for machines
* to parse and generate. It is based on a subset of the JavaScript
* Programming Language, Standard ECMA-262 3rd Edition - December 1999.
* This feature can also be found in Python. JSON is a text format that is
* completely language independent but uses conventions that are familiar
* to programmers of the C-family of languages, including C, C++, C#, Java,
* JavaScript, Perl, TCL, and many others. These properties make JSON an
* ideal data-interchange language.
*
* This package provides a simple encoder and decoder for JSON notation. It
* is intended for use with client-side Javascript applications that make
* use of HTTPRequest to perform server communication functions - data can
* be encoded into JSON notation for use in a client-side javascript, or
* decoded from incoming Javascript requests. JSON format is native to
* Javascript, and can be directly eval()'ed with no further parsing
* overhead
*
* All strings should be in ASCII or UTF-8 format!
*
* LICENSE: 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.
*
* THIS SOFTWARE IS PROVIDED ``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 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
* @package HTML_AJAX_JSON
* @author Michal Migurski <mike-json@teczno.com>
* @author Matt Knapp <mdknapp[at]gmail[dot]com>
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
* @copyright 2005 Michal Migurski
* @license http://www.opensource.org/licenses/bsd-license.php
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
*/
/**
* Marker constant for HTML_AJAX_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_SLICE', 1);
/**
* Marker constant for HTML_AJAX_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_STR', 2);
/**
* Marker constant for HTML_AJAX_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_ARR', 3);
/**
* Marker constant for HTML_AJAX_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_OBJ', 4);
/**
* Marker constant for HTML_AJAX_JSON::decode(), used to flag stack state
*/
define('SERVICES_JSON_IN_CMT', 5);
/**
* Behavior switch for HTML_AJAX_JSON::decode()
*/
define('SERVICES_JSON_LOOSE_TYPE', 16);
/**
* Behavior switch for HTML_AJAX_JSON::decode()
*/
define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
/**
* Converts to and from JSON format.
*
* Brief example of use:
*
* <code>
* // create a new instance of HTML_AJAX_JSON
* $json = new HTML_AJAX_JSON();
*
* // convert a complexe value to JSON notation, and send it to the browser
* $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
* $output = $json->encode($value);
*
* print($output);
* // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
*
* // accept incoming POST data, assumed to be in JSON notation
* $input = file_get_contents('php://input', 1000000);
* $value = $json->decode($input);
* </code>
*/
class HTML_AJAX_JSON
{
/**
* constructs a new JSON instance
*
* @param int $use object behavior flags; combine with boolean-OR
*
* possible values:
* - SERVICES_JSON_LOOSE_TYPE: loose typing.
* "{...}" syntax creates associative arrays
* instead of objects in decode().
* - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
* Values which can't be encoded (e.g. resources)
* appear as NULL instead of throwing errors.
* By default, a deeply-nested resource will
* bubble up with an error, so all return values
* from encode() should be checked with isError()
*/
function HTML_AJAX_JSON($use = 0)
{
$this->use = $use;
}
/**
* convert a string from one UTF-16 char to one UTF-8 char
*
* Normally should be handled by mb_convert_encoding, but
* provides a slower PHP-only method for installations
* that lack the multibye string extension.
*
* @param string $utf16 UTF-16 character
* @return string UTF-8 character
* @access private
*/
function utf162utf8($utf16)
{
// oh please oh please oh please oh please oh please
if(function_exists('mb_convert_encoding'))
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
$bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
switch(true) {
case ((0x7F & $bytes) == $bytes):
// this case should never be reached, because we are in ASCII range
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0x7F & $bytes);
case (0x07FF & $bytes) == $bytes:
// return a 2-byte UTF-8 character
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0xC0 | (($bytes >> 6) & 0x1F))
. chr(0x80 | ($bytes & 0x3F));
case (0xFFFF & $bytes) == $bytes:
// return a 3-byte UTF-8 character
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0xE0 | (($bytes >> 12) & 0x0F))
. chr(0x80 | (($bytes >> 6) & 0x3F))
. chr(0x80 | ($bytes & 0x3F));
}
// ignoring UTF-32 for now, sorry
return '';
}
/**
* convert a string from one UTF-8 char to one UTF-16 char
*
* Normally should be handled by mb_convert_encoding, but
* provides a slower PHP-only method for installations
* that lack the multibye string extension.
*
* @param string $utf8 UTF-8 character
* @return string UTF-16 character
* @access private
*/
function utf82utf16($utf8)
{
// oh please oh please oh please oh please oh please
if(function_exists('mb_convert_encoding'))
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
switch(strlen($utf8)) {
case 1:
// this case should never be reached, because we are in ASCII range
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return $utf8;
case 2:
// return a UTF-16 character from a 2-byte UTF-8 char
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr(0x07 & (ord($utf8{0}) >> 2))
. chr((0xC0 & (ord($utf8{0}) << 6))
| (0x3F & ord($utf8{1})));
case 3:
// return a UTF-16 character from a 3-byte UTF-8 char
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
return chr((0xF0 & (ord($utf8{0}) << 4))
| (0x0F & (ord($utf8{1}) >> 2)))
. chr((0xC0 & (ord($utf8{1}) << 6))
| (0x7F & ord($utf8{2})));
}
// ignoring UTF-32 for now, sorry
return '';
}
/**
* encodes an arbitrary variable into JSON format
*
* @param mixed $var any number, boolean, string, array, or object to be encoded.
* see argument 1 to HTML_AJAX_JSON() above for array-parsing behavior.
* if var is a strng, note that encode() always expects it
* to be in ASCII or UTF-8 format!
*
* @return mixed JSON string representation of input var or an error if a problem occurs
* @access public
*/
function encode($var)
{
switch (gettype($var)) {
case 'boolean':
return $var ? 'true' : 'false';
case 'NULL':
return 'null';
case 'integer':
return (int) $var;
case 'double':
case 'float':
return (float) $var;
case 'string':
// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
$ascii = '';
$strlen_var = strlen($var);
/*
* Iterate over every character in the string,
* escaping with a slash or encoding to UTF-8 where necessary
*/
for ($c = 0; $c < $strlen_var; ++$c) {
$ord_var_c = ord($var{$c});
switch (true) {
case $ord_var_c == 0x08:
$ascii .= '\b';
break;
case $ord_var_c == 0x09:
$ascii .= '\t';
break;
case $ord_var_c == 0x0A:
$ascii .= '\n';
break;
case $ord_var_c == 0x0C:
$ascii .= '\f';
break;
case $ord_var_c == 0x0D:
$ascii .= '\r';
break;
case $ord_var_c == 0x22:
case $ord_var_c == 0x2F:
case $ord_var_c == 0x5C:
// double quote, slash, slosh
$ascii .= '\\'.$var{$c};
break;
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
// characters U-00000000 - U-0000007F (same as ASCII)
$ascii .= $var{$c};
break;
case (($ord_var_c & 0xE0) == 0xC0):
// characters U-00000080 - U-000007FF, mask 110XXXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c, ord($var{$c + 1}));
$c += 1;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF0) == 0xE0):
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}));
$c += 2;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF8) == 0xF0):
// characters U-00010000 - U-001FFFFF, mask 11110XXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}));
$c += 3;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFC) == 0xF8):
// characters U-00200000 - U-03FFFFFF, mask 111110XX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}),
ord($var{$c + 4}));
$c += 4;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFE) == 0xFC):
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c + 1}),
ord($var{$c + 2}),
ord($var{$c + 3}),
ord($var{$c + 4}),
ord($var{$c + 5}));
$c += 5;
$utf16 = $this->utf82utf16($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
}
}
return '"'.$ascii.'"';
case 'array':
/*
* As per JSON spec if any array key is not an integer
* we must treat the the whole array as an object. We
* also try to catch a sparsely populated associative
* array with numeric keys here because some JS engines
* will create an array with empty indexes up to
* max_index which can cause memory issues and because
* the keys, which may be relevant, will be remapped
* otherwise.
*
* As per the ECMA and JSON specification an object may
* have any string as a property. Unfortunately due to
* a hole in the ECMA specification if the key is a
* ECMA reserved word or starts with a digit the
* parameter is only accessible using ECMAScript's
* bracket notation.
*/
// treat as a JSON object
if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
$properties = array_map(array($this, 'name_value'),
array_keys($var),
array_values($var));
foreach($properties as $property)
if(HTML_AJAX_JSON::isError($property))
return $property;
return '{' . join(',', $properties) . '}';
}
// treat it like a regular array
$elements = array_map(array($this, 'encode'), $var);
foreach($elements as $element)
if(HTML_AJAX_JSON::isError($element))
return $element;
return '[' . join(',', $elements) . ']';
case 'object':
$vars = get_object_vars($var);
$properties = array_map(array($this, 'name_value'),
array_keys($vars),
array_values($vars));
foreach($properties as $property)
if(HTML_AJAX_JSON::isError($property))
return $property;
return '{' . join(',', $properties) . '}';
default:
return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
? 'null'
: new HTML_AJAX_JSON_Error(gettype($var)." can not be encoded as JSON string");
}
}
/**
* array-walking function for use in generating JSON-formatted name-value pairs
*
* @param string $name name of key to use
* @param mixed $value reference to an array element to be encoded
*
* @return string JSON-formatted name-value pair, like '"name":value'
* @access private
*/
function name_value($name, $value)
{
$encoded_value = $this->encode($value);
if(HTML_AJAX_JSON::isError($encoded_value))
return $encoded_value;
return $this->encode(strval($name)) . ':' . $encoded_value;
}
/**
* reduce a string by removing leading and trailing comments and whitespace
*
* @param $str string string value to strip of comments and whitespace
*
* @return string string value stripped of comments and whitespace
* @access private
*/
function reduce_string($str)
{
$str = preg_replace(array(
// eliminate single line comments in '// ...' form
'#^\s*//(.+)$#m',
// eliminate multi-line comments in '/* ... */' form, at start of string
'#^\s*/\*(.+)\*/#Us',
// eliminate multi-line comments in '/* ... */' form, at end of string
'#/\*(.+)\*/\s*$#Us'
), '', $str);
// eliminate extraneous space
return trim($str);
}
/**
* decodes a JSON string into appropriate variable
*
* @param string $str JSON-formatted string
*
* @return mixed number, boolean, string, array, or object
* corresponding to given JSON input string.
* See argument 1 to HTML_AJAX_JSON() above for object-output behavior.
* Note that decode() always returns strings
* in ASCII or UTF-8 format!
* @access public
*/
function decode($str)
{
$str = $this->reduce_string($str);
switch (strtolower($str)) {
case 'true':
return true;
case 'false':
return false;
case 'null':
return null;
default:
if (is_numeric($str)) {
// Lookie-loo, it's a number
// This would work on its own, but I'm trying to be
// good about returning integers where appropriate:
// return (float)$str;
// Return float or int, as appropriate
return ((float)$str == (integer)$str)
? (integer)$str
: (float)$str;
} elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
// STRINGS RETURNED IN UTF-8 FORMAT
$delim = substr($str, 0, 1);
$chrs = substr($str, 1, -1);
$utf8 = '';
$strlen_chrs = strlen($chrs);
for ($c = 0; $c < $strlen_chrs; ++$c) {
$substr_chrs_c_2 = substr($chrs, $c, 2);
$ord_chrs_c = ord($chrs{$c});
switch (true) {
case $substr_chrs_c_2 == '\b':
$utf8 .= chr(0x08);
++$c;
break;
case $substr_chrs_c_2 == '\t':
$utf8 .= chr(0x09);
++$c;
break;
case $substr_chrs_c_2 == '\n':
$utf8 .= chr(0x0A);
++$c;
break;
case $substr_chrs_c_2 == '\f':
$utf8 .= chr(0x0C);
++$c;
break;
case $substr_chrs_c_2 == '\r':
$utf8 .= chr(0x0D);
++$c;
break;
case $substr_chrs_c_2 == '\\"':
case $substr_chrs_c_2 == '\\\'':
case $substr_chrs_c_2 == '\\\\':
case $substr_chrs_c_2 == '\\/':
if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
($delim == "'" && $substr_chrs_c_2 != '\\"')) {
$utf8 .= $chrs{++$c};
}
break;
case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
// single, escaped unicode character
$utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
. chr(hexdec(substr($chrs, ($c + 4), 2)));
$utf8 .= $this->utf162utf8($utf16);
$c += 5;
break;
case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
$utf8 .= $chrs{$c};
break;
case ($ord_chrs_c & 0xE0) == 0xC0:
// characters U-00000080 - U-000007FF, mask 110XXXXX
//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 2);
++$c;
break;
case ($ord_chrs_c & 0xF0) == 0xE0:
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 3);
$c += 2;
break;
case ($ord_chrs_c & 0xF8) == 0xF0:
// characters U-00010000 - U-001FFFFF, mask 11110XXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 4);
$c += 3;
break;
case ($ord_chrs_c & 0xFC) == 0xF8:
// characters U-00200000 - U-03FFFFFF, mask 111110XX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 5);
$c += 4;
break;
case ($ord_chrs_c & 0xFE) == 0xFC:
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 6);
$c += 5;
break;
}
}
return $utf8;
} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
// array, or object notation
if ($str{0} == '[') {
$stk = array(SERVICES_JSON_IN_ARR);
$arr = array();
} else {
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
$stk = array(SERVICES_JSON_IN_OBJ);
$obj = array();
} else {
$stk = array(SERVICES_JSON_IN_OBJ);
$obj = new stdClass();
}
}
array_push($stk, array('what' => SERVICES_JSON_SLICE,
'where' => 0,
'delim' => false));
$chrs = substr($str, 1, -1);
$chrs = $this->reduce_string($chrs);
if ($chrs == '') {
if (reset($stk) == SERVICES_JSON_IN_ARR) {
return $arr;
} else {
return $obj;
}
}
//print("\nparsing {$chrs}\n");
$strlen_chrs = strlen($chrs);
for ($c = 0; $c <= $strlen_chrs; ++$c) {
$top = end($stk);
$substr_chrs_c_2 = substr($chrs, $c, 2);
if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
// found a comma that is not inside a string, array, etc.,
// OR we've reached the end of the character list
$slice = substr($chrs, $top['where'], ($c - $top['where']));
array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
//print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
if (reset($stk) == SERVICES_JSON_IN_ARR) {
// we are in an array, so just push an element onto the stack
array_push($arr, $this->decode($slice));
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
// we are in an object, so figure
// out the property name and set an
// element in an associative array,
// for now
if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
// "name":value pair
$key = $this->decode($parts[1]);
$val = $this->decode($parts[2]);
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
$obj[$key] = $val;
} else {
$obj->$key = $val;
}
} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
// name:value pair, where name is unquoted
$key = $parts[1];
$val = $this->decode($parts[2]);
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
$obj[$key] = $val;
} else {
$obj->$key = $val;
}
}
}
} elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
// found a quote, and we are not inside a string
array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
//print("Found start of string at {$c}\n");
} elseif (($chrs{$c} == $top['delim']) &&
($top['what'] == SERVICES_JSON_IN_STR) &&
(($chrs{$c - 1} != '\\') ||
($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) {
// found a quote, we're in a string, and it's not escaped
array_pop($stk);
//print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
} elseif (($chrs{$c} == '[') &&
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
// found a left-bracket, and we are in an array, object, or slice
array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
//print("Found start of array at {$c}\n");
} elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
// found a right-bracket, and we're in an array
array_pop($stk);
//print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
} elseif (($chrs{$c} == '{') &&
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
// found a left-brace, and we are in an array, object, or slice
array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
//print("Found start of object at {$c}\n");
} elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
// found a right-brace, and we're in an object
array_pop($stk);
//print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
} elseif (($substr_chrs_c_2 == '/*') &&
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
// found a comment start, and we are in an array, object, or slice
array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
$c++;
//print("Found start of comment at {$c}\n");
} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
// found a comment end, and we're in one now
array_pop($stk);
$c++;
for ($i = $top['where']; $i <= $c; ++$i)
$chrs = substr_replace($chrs, ' ', $i, 1);
//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
}
}
if (reset($stk) == SERVICES_JSON_IN_ARR) {
return $arr;
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
return $obj;
}
}
}
}
/**
* @todo Ultimately, this should just call PEAR::isError()
*/
function isError($data, $code = null)
{
if (HTML_AJAX_class_exists('pear', false)) {
return PEAR::isError($data, $code);
} elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
is_subclass_of($data, 'services_json_error'))) {
return true;
}
return false;
}
}
if (HTML_AJAX_class_exists('pear_error', false)) {
class HTML_AJAX_JSON_Error extends PEAR_Error
{
function HTML_AJAX_JSON_Error($message = 'unknown error', $code = null,
$mode = null, $options = null, $userinfo = null)
{
parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
}
}
} else {
/**
* @todo Ultimately, this class shall be descended from PEAR_Error
*/
class HTML_AJAX_JSON_Error
{
function HTML_AJAX_JSON_Error($message = 'unknown error', $code = null,
$mode = null, $options = null, $userinfo = null)
{
}
}
}
// Future-friendly json_encode
if( !function_exists('json_encode') ) {
function json_encode($data) {
$json = new HTML_AJAX_JSON();
return( $json->encode($data) );
}
}
// Future-friendly json_decode
if( !function_exists('json_decode') ) {
function json_decode($data) {
$json = new HTML_AJAX_JSON();
return( $json->decode($data) );
}
}
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
?>

View File

@ -1,78 +0,0 @@
<?php
/**
* OO AJAX Implementation for PHP, contains HTML_AJAX_Response
*
* SVN Rev: $Id$
*
* @category HTML
* @package AJAX
* @author Elizabeth Smith <auroraeosrose@gmail.com>
* @copyright 2005-2006 Elizabeth Smith
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: 0.5.6
*/
/**
* Require the main AJAX library
*/
require_once 'HTML/AJAX.php';
/**
* Simple base class for a response object to use as an ajax callback
*
* This is the base response class, more interesting response classes can be
* built off of this, simply give it a unique content type and override the
* getPayload method or fill the payload property with your extended classes's
* serialized content
*
* @version $Id$
*/
class HTML_AJAX_Response
{
/**
* The base response class uses plain text so use that content type
*
* @var string
* @access public
*/
var $contentType = 'text/plain';
/**
* Assign a string to this variable to use the bare response class
*
* @var string
* @access public
*/
var $payload = '';
/**
* Returns the appropriate content type
*
* This normally simply returns the contentType property but can be overridden
* by an extending class if the content-type is variable
*
* @return string appropriate content type
* @access public
*/
function getContentType()
{
return $this->contentType;
}
/**
* Returns the serialized content of the response class
*
* You can either fill the payload elsewhere in an extending class and leave
* this method alone, or you can override it if you have a different type
* of payload that needs special treatment
*
* @return string serialized response content
* @access public
*/
function getPayload()
{
return $this->payload;
}
}
?>

View File

@ -1,20 +0,0 @@
<?php
require_once 'HTML/AJAX/Serializer/JSON.php';
// $Id
/**
* Error Serializer, for now just uses JSON
*
* @category HTML
* @package AJAX
* @author Joshua Eichorn <josh@bluga.net>
* @copyright 2005 Joshua Eichorn
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 0.5.6
* @link http://pear.php.net/package/HTML_AJAX
*/
class HTML_AJAX_Serializer_Error extends HTML_AJAX_Serializer_JSON
{
}
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
?>

View File

@ -1,96 +0,0 @@
<?php
require_once 'HTML/AJAX/JSON.php';
// $Id$
/**
* JSON Serializer
*
* @category HTML
* @package AJAX
* @author Joshua Eichorn <josh@bluga.net>
* @copyright 2005 Joshua Eichorn
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: 0.5.6
* @link http://pear.php.net/package/PackageName
*/
// {{{ class HTMLA_AJAX_Serialize_JSON
class HTML_AJAX_Serializer_JSON
{
// {{{ variables-properties
/**
* JSON instance
* @var HTML_AJAX_JSON
* @access private
*/
var $_json;
/**
* use json php extension http://www.aurore.net/projects/php-json/
* @access private
*/
var $_jsonext;
/**
* use loose typing to decode js objects into php associative arrays
* @access public
*/
var $loose_type;
// }}}
// {{{ constructor
function HTML_AJAX_Serializer_JSON($use_loose_type = true)
{
$this->loose_type = (bool) $use_loose_type;
$this->_jsonext = $this->_detect();
if(!$this->_jsonext) {
$use_loose_type = ($this->loose_type) ? SERVICES_JSON_LOOSE_TYPE : 0;
$this->_json = new HTML_AJAX_JSON($use_loose_type);
}
}
// }}}
// {{{ serialize
/**
* This function serializes and input passed to it.
*
* @access public
* @param string $input The input to serialize.
* @return string $input The serialized input.
*/
function serialize($input)
{
if($this->_jsonext) {
return json_encode($input);
} else {
return $this->_json->encode($input);
}
}
// }}}
// {{{ unserialize
/**
* this function unserializes the input passed to it.
*
* @access public
* @param string $input The input to unserialize
* @return string $input The unserialized input.
*/
function unserialize($input)
{
if($this->_jsonext) {
return json_decode($input, $this->loose_type);
} else {
return $this->_json->decode($input);
}
}
// }}}
// {{{ _detect
/**
* detects the loaded extension
*/
function _detect()
{
return extension_loaded('json');
}
// }}}
}
// }}}
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
?>

View File

@ -1,28 +0,0 @@
<?php
// $Id$
/**
* Null Serializer
*
* @category HTML
* @package AJAX
* @author Joshua Eichorn <josh@bluga.net>
* @copyright 2005 Joshua Eichorn
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: 0.5.6
* @link http://pear.php.net/package/PackageName
*/
class HTML_AJAX_Serializer_Null
{
function serialize($input)
{
return $input;
}
function unserialize($input)
{
return $input;
}
}
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
?>

View File

@ -1,88 +0,0 @@
<?php
// $Id$
/**
* PHP Serializer
*
* @category HTML
* @package AJAX
* @author Arpad Ray <arpad@php.net>
* @copyright 2005 Arpad Ray
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: 0.5.6
* @link http://pear.php.net/package/HTML_AJAX
*/
class HTML_AJAX_Serializer_PHP
{
function serialize($input)
{
return serialize($input);
}
/**
* Unserializes the given string
*
* Triggers an error if a class is found which is not
* in the provided array of allowed class names.
*
* @param string $input
* the serialized string to process
* @param array $allowedClasses
* an array of class names to check objects against
* before instantion
* @return mixed
* the unserialized variable on success, or false on
* failure. If this method fails it will also trigger
* a warning.
*/
function unserialize($input, $allowedClasses)
{
if (version_compare(PHP_VERSION, '4.3.10', '<')
|| (substr(PHP_VERSION, 0, 1) == '5' && version_compare(PHP_VERSION, '5.0.3', '<'))) {
trigger_error('Unsafe version of PHP for native unserialization');
return false;
}
$classes = $this->_getSerializedClassNames($input);
if ($classes === false) {
trigger_error('Invalidly serialized string');
return false;
}
$diff = array_diff($classes, $allowedClasses);
if (!empty($diff)) {
trigger_error('Class(es) not allowed to be serialized');
return false;
}
return unserialize($input);
}
/**
* Extract class names from serialized string
*
* Adapted from code by Harry Fuecks
*
* @param string $string
* the serialized string to process
* @return mixed
* an array of class names found, or false if the input
* is invalidly formed
*/
function _getSerializedClassNames($string) {
// Strip any string representations (which might contain object syntax)
while (($pos = strpos($string, 's:')) !== false) {
$pos2 = strpos($string, ':', $pos + 2);
if ($pos2 === false) {
// invalidly serialized string
return false;
}
$end = $pos + 2 + substr($string, $pos + 2, $pos2) + 1;
$string = substr($string, 0, $pos) . substr($string, $end);
}
// Pull out the class names
preg_match_all('/O:[0-9]+:"(.*)"/U', $string, $matches);
// Make sure names are unique (same object serialized twice)
return array_unique($matches[1]);
}
}
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
?>

View File

@ -1,67 +0,0 @@
<?php
// $Id$
// {{{ http_build_query
/**
* Replacement for http_build_query()
*
* @link http://php.net/function.http-build-query
* @author vlad_mustafin@ukr.net
* @author Arpad Ray <arpad@php.net>
*/
if (!function_exists('http_build_query')) {
function http_build_query($formdata, $numeric_prefix = null, $key = null)
{
$res = array();
foreach ((array)$formdata as $k => $v) {
if (is_resource($v)) {
return null;
}
$tmp_key = urlencode(is_int($k) ? $numeric_prefix . $k : $k);
if (!is_null($key)) {
$tmp_key = $key . '[' . $tmp_key . ']';
}
$res[] = (is_scalar($v))
? $tmp_key . '=' . urlencode($v)
: http_build_query($v, null , $tmp_key);
}
$separator = ini_get('arg_separator.output');
if (strlen($separator) == 0) {
$separator = '&';
}
return implode($separator, $res);
}
}
// }}}
// {{{ class HTML_AJAX_Serialize_Urlencoded
/**
* URL Encoding Serializer
*
* @category HTML
* @package AJAX
* @author Arpad Ray <arpad@php.net>
* @author David Coallier <davidc@php.net>
* @copyright 2005 Arpad Ray
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: 0.5.6
* @link http://pear.php.net/package/HTML_AJAX
*/
class HTML_AJAX_Serializer_Urlencoded
{
// {{{ serialize
function serialize($input)
{
return http_build_query(array('_HTML_AJAX' => $input));
}
// }}}
// {{{ unserialize
function unserialize($input)
{
parse_str($input, $ret);
return (isset($ret['_HTML_AJAX']) ? $ret['_HTML_AJAX'] : $ret);
}
// }}}
}
// }}}
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
?>

View File

@ -1,88 +0,0 @@
<?php
// $Id$
/**
* XML Serializer - does NOT need a js serializer, use responseXML property in XmlHttpRequest
*
* @category HTML
* @package AJAX
* @author Elizabeth Smith <auroraeosrose@gmail.com>
* @copyright 2005-2006 Elizabeth Smith
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: 0.5.6
* @link http://pear.php.net/package/PackageName
*/
class HTML_AJAX_Serializer_XML
{
/**
* Serializes a domdocument into an xml string
*
* Uses dom or domxml to dump a string from a DomDocument instance
* remember dom is always the default and this will die horribly without
* a domdocument instance
*
* @access public
* @param object $input instanceof DomDocument
* @return string xml string of DomDocument
*/
function serialize($input)
{
if(empty($input))
{
return $input;
}
// we check for the dom extension
elseif (extension_loaded('Dom'))
{
return $input->saveXml();
}
// then will check for domxml
elseif (extension_loaded('Domxml'))
{
return $input->dump_mem();
}
// will throw an error
else {
$error = new HTML_AJAX_Serializer_Error();
$this->serializerNewType = 'Error';
return $error->serialize(array('errStr'=>"Missing PHP Dom extension direct XML won't work"));
}
}
/**
* Unserializes the xml string sent from the document
*
* Uses dom or domxml to pump a string into a DomDocument instance
* remember dom is always the default and this will die horribly without
* one or the other, and will throw warnings if you have bad xml
*
* @access public
* @param string $input The input to serialize.
* @return object instanceofDomDocument
*/
function unserialize($input)
{
if(empty($input))
{
return $input;
}
// we check for the dom extension
elseif (extension_loaded('Dom'))
{
$doc = new DOMDocument();
$doc->loadXML($input);
return $doc;
}
// then we check for the domxml extensions
elseif (extension_loaded('Domxml'))
{
return domxml_open_mem($input);
}
// we give up and just return the xml directly
else
{
return $input;
}
}
}
?>

View File

@ -1,725 +0,0 @@
<?php
/**
* OO AJAX Implementation for PHP
*
* SVN Rev: $Id$
*
* @category HTML
* @package AJAX
* @author Joshua Eichorn <josh@bluga.net>
* @copyright 2005 Joshua Eichorn
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: @package_version@
*/
/**
* Require the main AJAX library
*/
require_once 'HTML/AJAX.php';
/**
* Class for creating an external AJAX server
*
* Can be used in 2 different modes, registerClass mode where you create an instance of the server and add the classes that will be registered
* and then run handle request
*
* Or you can extend it and add init{className} methods for each class you want to export
*
* Client js generation is exposed through 2 _GET params client and stub
* Setting the _GET param client to `all` will give you all the js classes needed
* Setting the _GET param stub to `all` will give you stubs of all registered classes, you can also set it too just 1 class
*
* @category HTML
* @package AJAX
* @author Joshua Eichorn <josh@bluga.net>
* @copyright 2005 Joshua Eichorn
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version Release: @package_version@
* @link http://pear.php.net/package/PackageName
*/
class HTML_AJAX_Server
{
/**
* Client options array if set to true the code looks at _GET
* @var bool|array
*/
var $options = true;
/**
* HTML_AJAX instance
* @var HTML_AJAX
*/
var $ajax;
/**
* Set to true if your extending the server to add init{className methods}
* @var boolean
* @access public
*/
var $initMethods = false;
/**
* Location on filesystem of client javascript library
* @var false|string if false the default pear data dir location is used
*/
var $clientJsLocation = false;
/**
* An array of options that tell the server howto Cache output
*
* The rules are functions that make etag hash used to see if the client needs to download updated content
* If you extend this class you can make your own rule function the naming convention is _cacheRule{RuleName}
*
* <code>
* array(
* 'httpCacheClient' => true, // send 304 headers for responses to ?client=* requests
* 'ClientCacheRule' => 'File', // create a hash from file names and modified times, options: file|content
* 'ClientCacheExpects'=> 'files', // what type of content to send to the hash function, options: files|classes|content
* 'httpCacheStub' => true, // send 304 headers for responses to ?stub=* requests
* 'StubCacheRule' => 'Api', // create a hash from the exposed api, options: api|content
* 'StubCacheExpects'=> 'classes', // what type of content to send to the hash function, options: files|classes|content
* )
* </code>
*
* @var array
* @access public
*/
var $cacheOptions = array(
'httpCacheClient' => true,
'ClientCacheRule' => 'file',
'ClientCacheExpects' => 'files',
'httpCacheStub' => true,
'StubCacheRule' => 'api',
'StubCacheExpects' => 'classes',
);
/**
* Compression Options
*
* <code>
* array(
* 'enabled' => false, // enable compression
* 'type' => 'gzip' // the type of compression to do, options: gzip
* )
* </code>
*
* @var array
* @access public
*/
var $compression = array(
'enabled' => false,
'type' => 'gzip'
);
/**
* Javascript library names and there path
*
* the return of $this->clientJsLocation(), is prepended before running readfile on them
*
* @access public
* @var array
*/
var $javascriptLibraries = array(
'all' => 'HTML_AJAX.js',
'html_ajax' => 'HTML_AJAX.js',
'html_ajax_lite'=> 'HTML_AJAX_lite.js',
'json' => 'serializer/JSON.js',
'request' => 'Request.js',
'main' => array('Compat.js','Main.js','clientPool.js'),
'httpclient' => 'HttpClient.js',
'dispatcher' => 'Dispatcher.js',
'util' => 'util.js',
'loading' => 'Loading.js',
'phpserializer' => 'serializer/phpSerializer.js',
'urlserializer' => 'serializer/UrlSerializer.js',
'haserializer' => 'serializer/haSerializer.js',
'clientpool' => 'clientPool.js',
'iframe' => 'IframeXHR.js',
'alias' => 'Alias.js',
'queues' => 'Queue.js',
'behavior' => array('behavior/behavior.js','behavior/cssQuery-p.js'),
// rules to help you use a minimal library set
'standard' => array('Compat.js','clientPool.js','util.js','Main.js','HttpClient.js','Request.js','serializer/JSON.js',
'Loading.js','serializer/UrlSerializer.js','Alias.js','behavior/behavior.js','behavior/cssQuery-p.js'),
'jsonrpc' => array('Compat.js','util.js','Main.js','clientPool.js','HttpClient.js','Request.js','serializer/JSON.js'),
'proxyobjects' => array('Compat.js','util.js','Main.js','clientPool.js','Request.js','serializer/JSON.js','Dispatcher.js'),
// BC rules
'priorityqueue' => 'Queue.js',
'orderedqueue' => 'Queue.js',
);
/**
* Custom paths to use for javascript libraries, if not set {@link clientJsLocation} is used to find the system path
*
* @access public
* @var array
* @see registerJsLibrary
*/
var $javascriptLibraryPaths = array();
/**
* Array of className => init methods to call, generated from constructor from initClassName methods
*
* @access protected
*/
var $_initLookup = array();
/**
* Constructor creates the HTML_AJAX instance
*
* @param string $serverUrl (Optional) the url the client should be making a request too
*/
function HTML_AJAX_Server($serverUrl = false)
{
$this->ajax = new HTML_AJAX();
// parameters for HTML::AJAX
$parameters = array('stub', 'client');
// keep in the query string all the parameters that don't belong to AJAX
// we remove all string like "parameter=something&". Final '&' can also
// be '&amp;' (to be sure) and is optional. '=something' is optional too.
$querystring = '';
if (isset($_SERVER['QUERY_STRING'])) {
$querystring = preg_replace('/(' . join('|', $parameters) . ')(?:=[^&]*(?:&(?:amp;)?|$))?/', '', $this->ajax->_getServer('QUERY_STRING'));
}
// call the server with this query string
if ($serverUrl === false) {
$serverUrl = htmlentities($this->ajax->_getServer('PHP_SELF'));
}
if (substr($serverUrl,-1) != '?') {
$serverUrl .= '?';
}
$this->ajax->serverUrl = $serverUrl . $querystring;
$methods = get_class_methods($this);
foreach($methods as $method) {
if (preg_match('/^init([a-zA-Z0-9_]+)$/',$method,$match)) {
$this->_initLookup[strtolower($match[1])] = $method;
}
}
}
/**
* Handle a client request, either generating a client or having HTML_AJAX handle the request
*
* @return boolean true if request was handled, false otherwise
*/
function handleRequest()
{
if ($this->options == true) {
$this->_loadOptions();
}
//basically a hook for iframe but allows processing of data earlier
$this->ajax->populatePayload();
if (!isset($_GET['c']) && (count($this->options['client']) > 0 || count($this->options['stub']) > 0) ) {
$this->generateClient();
return true;
} else {
if (!empty($_GET['c'])) {
$this->_init($this->_cleanIdentifier($this->ajax->_getVar('c')));
}
return $this->ajax->handleRequest();
}
}
/**
* Register method passthrough to HTML_AJAX
*
* @see HTML_AJAX::registerClass for docs
*/
function registerClass(&$instance, $exportedName = false, $exportedMethods = false)
{
$this->ajax->registerClass($instance,$exportedName,$exportedMethods);
}
/**
* Change default serialization - important for exporting classes
*
* I wanted this for the xml serializer :)
*/
function setSerializer($type)
{
$this->ajax->serializer = $type;
$this->ajax->unserializer = $type;
}
/**
* Register a new js client library
*
* @param string $libraryName name you'll reference the library as
* @param string|array $fileName actual filename with no path, for example customLib.js
* @param string|false $path Optional, if not set the result from jsClientLocation is used
*/
function registerJSLibrary($libraryName,$fileName,$path = false) {
$libraryName = strtolower($libraryName);
$this->javascriptLibraries[$libraryName] = $fileName;
if ($path !== false) {
$this->javascriptLibraryPaths[$libraryName] = $path;
}
}
/**
* Register init methods from an external class
*
* @param object $instance an external class with initClassName methods
*/
function registerInitObject(&$instance) {
$instance->server =& $this;
$methods = get_class_methods($instance);
foreach($methods as $method) {
if (preg_match('/^init([a-zA-Z0-9_]+)$/',$method,$match)) {
$this->_initLookup[strtolower($match[1])] = array(&$instance,$method);
}
}
}
/**
* Register a callback to be exported to the client
*
* This function uses the PHP callback pseudo-type
*
*/
function registerPhpCallback($callback)
{
if (!is_callable($callback)) {
// invalid callback
return false;
}
if (is_array($callback) && is_object($callback[0])) {
// object method
$this->registerClass($callback[0], strtolower(get_class($callback[0])), array($callback[1]));
return true;
}
// static callback
$this->ajax->registerPhpCallback($callback);
}
/**
* Generate client js
*
* @todo this is going to need tests to cover all the options
*/
function generateClient()
{
$headers = array();
ob_start();
// create a list list of js files were going to need to output
// index is the full file and so is the value, this keeps duplicates out of $fileList
$fileList = array();
if(!is_array($this->options['client'])) {
$this->options['client'] = array();
}
foreach($this->options['client'] as $library) {
if (isset($this->javascriptLibraries[$library])) {
$lib = (array)$this->javascriptLibraries[$library];
foreach($lib as $file) {
if (isset($this->javascriptLibraryPaths[$library])) {
$fileList[$this->javascriptLibraryPaths[$library].$file] = $this->javascriptLibraryPaths[$library].$file;
}
else {
$fileList[$this->clientJsLocation().$file] = $this->clientJsLocation().$file;
}
}
}
}
// do needed class init if were running an init server
if(!is_array($this->options['stub'])) {
$this->options['stub'] = array();
}
$classList = $this->options['stub'];
if ($this->initMethods) {
if (isset($this->options['stub'][0]) && $this->options['stub'][0] === 'all') {
$this->_initAll();
} else {
foreach($this->options['stub'] as $stub) {
$this->_init($stub);
}
}
}
if (isset($this->options['stub'][0]) && $this->options['stub'][0] === 'all') {
$classList = array_keys($this->ajax->_exportedInstances);
}
// if were doing stub and client we have to wait for both ETags before we can compare with the client
$combinedOutput = false;
if ($classList != false && count($classList) > 0 && count($fileList) > 0) {
$combinedOutput = true;
}
if ($classList != false && count($classList) > 0) {
// were setup enough to make a stubETag if the input it wants is a class list
if ($this->cacheOptions['httpCacheStub'] &&
$this->cacheOptions['StubCacheExpects'] == 'classes')
{
$stubETag = $this->_callCacheRule('Stub',$classList);
}
// if were not in combined output compare etags, if method returns true were done
if (!$combinedOutput && isset($stubETag)) {
if ($this->_compareEtags($stubETag)) {
ob_end_clean();
return;
}
}
// output the stubs for all the classes in our list
foreach($classList as $class) {
echo $this->ajax->generateClassStub($class);
}
// if were cacheing and the rule expects content make a tag and check it, if the check is true were done
if ($this->cacheOptions['httpCacheStub'] &&
$this->cacheOptions['StubCacheExpects'] == 'content')
{
$stubETag = $this->_callCacheRule('Stub',ob_get_contents());
}
// if were not in combined output compare etags, if method returns true were done
if (!$combinedOutput && isset($stubETag)) {
if ($this->_compareEtags($stubETag)) {
ob_end_clean();
return;
}
}
}
if (count($fileList) > 0) {
// if were caching and need a file list build our jsETag
if ($this->cacheOptions['httpCacheClient'] &&
$this->cacheOptions['ClientCacheExpects'] === 'files')
{
$jsETag = $this->_callCacheRule('Client',$fileList);
}
// if were not in combined output compare etags, if method returns true were done
if (!$combinedOutput && isset($jsETag)) {
if ($this->_compareEtags($jsETag)) {
ob_end_clean();
return;
}
}
// output the needed client js files
foreach($fileList as $file) {
$this->_readFile($file);
}
// if were caching and need content build the etag
if ($this->cacheOptions['httpCacheClient'] &&
$this->cacheOptions['ClientCacheExpects'] === 'content')
{
$jsETag = $this->_callCacheRule('Client',ob_get_contents());
}
// if were not in combined output compare etags, if method returns true were done
if (!$combinedOutput && isset($jsETag)) {
if ($this->_compareEtags($jsETag)) {
ob_end_clean();
return;
}
}
// were in combined output, merge the 2 ETags and compare
else if (isset($jsETag) && isset($stubETag)) {
if ($this->_compareEtags(md5($stubETag.$jsETag))) {
ob_end_clean();
return;
}
}
}
// were outputting content, add our length header and send the output
$length = ob_get_length();
$output = ob_get_contents();
ob_end_clean();
if ($this->ajax->packJavaScript) {
$output = $this->ajax->packJavaScript($output);
$length = strlen($output);
}
if ($this->compression['enabled'] && $this->compression['type'] == 'gzip' && strpos($_SERVER["HTTP_ACCEPT_ENCODING"], "gzip") !== false) {
$output = gzencode($output,9);
$length = strlen($output);
$headers['Content-Encoding'] = 'gzip';
}
if ($length > 0 && $this->ajax->_sendContentLength()) {
$headers['Content-Length'] = $length;
}
$headers['Content-Type'] = 'text/javascript; charset=utf-8';
$this->ajax->_sendHeaders($headers);
echo($output);
}
/**
* Run readfile on input with basic error checking
*
* @param string $file file to read
* @access private
* @todo is addslashes enough encoding for js?
*/
function _readFile($file)
{
if (file_exists($file)) {
readfile($file);
} else {
$file = addslashes($file);
echo "alert('Unable to find javascript file: $file');";
}
}
/**
* Get the location of the client js
* To override the default pear datadir location set $this->clientJsLocation
*
* @return string
*/
function clientJsLocation()
{
if (!$this->clientJsLocation) {
$path = '@data-dir@'.DIRECTORY_SEPARATOR.'HTML_AJAX'.DIRECTORY_SEPARATOR.'js'.DIRECTORY_SEPARATOR;
if(strpos($path, '@'.'data-dir@') === 0)
{
$path = realpath(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'js').DIRECTORY_SEPARATOR;
}
return $path;
} else {
return $this->clientJsLocation;
}
}
/**
* Set the location of the client js
*
* @access public
* @param string $location Location
* @return void
*/
function setClientJsLocation($location)
{
$this->clientJsLocation = $location;
}
/**
* Set the path to a Javascript libraries
*
* @access public
* @param string $library Library name
* @param string $path Path
* @return void
*/
function setJavascriptLibraryPath($library, $path)
{
$this->javascriptLibraryPaths[$library] = $path;
}
/**
* Set the path to more than one Javascript libraries at once
*
* @access public
* @param array $paths Paths
* @return void
*/
function setJavascriptLibraryPaths($paths)
{
if (is_array($paths)) {
$this->javascriptLibraryPaths = array_merge($this->javascriptLibraryPaths, $paths);
}
}
/**
* Load options from _GET
*
* @access private
*/
function _loadOptions()
{
$this->options = array('client'=>array(),'stub'=>array());
if (isset($_GET['client'])) {
$clients = explode(',',$this->ajax->_getVar('client'));
$client = array();
foreach($clients as $val) {
$cleanVal = $this->_cleanIdentifier($val);
if (!empty($cleanVal)) {
$client[] = strtolower($cleanVal);
}
}
if (count($client) > 0) {
$this->options['client'] = $client;
}
}
if (isset($_GET['stub'])) {
$stubs = explode(',',$this->ajax->_getVar('stub'));
$stub = array();
foreach($stubs as $val) {
$cleanVal = $this->_cleanIdentifier($val);
if (!empty($cleanVal)) {
$stub[] = strtolower($cleanVal);
}
}
if (count($stub) > 0) {
$this->options['stub'] = $stub;
}
}
}
/**
* Clean an identifier like a class name making it safe to use
*
* @param string $input
* @return string
* @access private
*/
function _cleanIdentifier($input) {
return trim(preg_replace('/[^A-Za-z_0-9]/','',$input));
}
/**
* Run every init method on the class
*
* @access private
*/
function _initAll()
{
if ($this->initMethods) {
foreach($this->_initLookup as $class => $method) {
$this->_init($class);
}
}
}
/**
* Init one class
*
* @param string $className
* @access private
*/
function _init($className)
{
$className = strtolower($className);
if ($this->initMethods) {
if (isset($this->_initLookup[$className])) {
$method =& $this->_initLookup[$className];
if (is_array($method)) {
call_user_func($method);
}
else {
$this->$method();
}
} else {
trigger_error("Could find an init method for class: " . $className);
}
}
}
/**
* Generate a hash from a list of files
*
* @param array $files file list
* @return string a hash that can be used as an etag
* @access private
*/
function _cacheRuleFile($files) {
$signature = "";
foreach($files as $file) {
if (file_exists($file)) {
$signature .= $file.filemtime($file);
}
}
return md5($signature);
}
/**
* Generate a hash from the api of registered classes
*
* @param array $classes class list
* @return string a hash that can be used as an etag
* @access private
*/
function _cacheRuleApi($classes) {
$signature = "";
foreach($classes as $class) {
if (isset($this->ajax->_exportedInstances[$class])) {
$signature .= $class.implode(',',$this->ajax->_exportedInstances[$class]['exportedMethods']);
}
}
return md5($signature);
}
/**
* Generate a hash from the raw content
*
* @param array $content
* @return string a hash that can be used as an etag
* @access private
*/
function _cacheRuleContent($content) {
return md5($content);
}
/**
* Send cache control headers
* @access private
*/
function _sendCacheHeaders($etag,$notModified) {
header('Cache-Control: must-revalidate');
header('ETag: '.$etag);
if ($notModified) {
header('HTTP/1.0 304 Not Modified',false,304);
}
}
/**
* Compare eTags
*
* @param string $serverETag server eTag
* @return boolean
* @access private
*/
function _compareEtags($serverETag) {
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
if (strcmp($this->ajax->_getServer('HTTP_IF_NONE_MATCH'),$serverETag) == 0) {
$this->_sendCacheHeaders($serverETag,true);
return true;
}
}
$this->_sendCacheHeaders($serverETag,false);
return false;
}
/**
* Call a cache rule and return its retusn
*
* @param string $rule Stub|Client
* @param mixed $payload
* @return boolean
* @access private
* @todo decide if error checking is needed
*/
function _callCacheRule($rule,$payload) {
$method = '_cacheRule'.$this->cacheOptions[$rule.'CacheRule'];
return call_user_func(array(&$this,$method),$payload);
}
}
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
?>