--- /dev/null
+<?php\r
+ #\r
+ # PEAR::Flickr_API\r
+ #\r
+ # Author: Cal Henderson\r
+ # Version: $Revision: 1.6 $\r
+ # CVS: $Id: API.php,v 1.6 2005/07/25 18:22:13 cal Exp $\r
+ #\r
+\r
+\r
+ require_once 'XML/Tree.php';\r
+ require_once 'HTTP/Request.php';\r
+\r
+\r
+ class Flickr_API {\r
+\r
+ var $_cfg = array(\r
+ 'api_key' => '',\r
+ 'api_secret' => '',\r
+ 'endpoint' => 'http://www.flickr.com/services/rest/',\r
+ 'auth_endpoint' => 'http://www.flickr.com/services/auth/?',\r
+ 'conn_timeout' => 5,\r
+ 'io_timeout' => 5,\r
+ );\r
+\r
+ var $_err_code = 0;\r
+ var $_err_msg = '';\r
+ var $tree;\r
+\r
+ function Flickr_API($params = array()){\r
+\r
+ foreach($params as $k => $v){\r
+ $this->_cfg[$k] = $v;\r
+ }\r
+ }\r
+\r
+ function callMethod($method, $params = array()){\r
+\r
+ $this->_err_code = 0;\r
+ $this->_err_msg = '';\r
+\r
+ #\r
+ # create the POST body\r
+ #\r
+\r
+ $p = $params;\r
+ $p['method'] = $method;\r
+ $p['api_key'] = $this->_cfg['api_key'];\r
+\r
+ if ($this->_cfg['api_secret']){\r
+\r
+ $p['api_sig'] = $this->signArgs($p);\r
+ }\r
+\r
+\r
+ $p2 = array();\r
+ foreach($p as $k => $v){\r
+ $p2[] = urlencode($k).'='.urlencode($v);\r
+ }\r
+\r
+ $body = implode('&', $p2);\r
+\r
+\r
+ #\r
+ # create the http request\r
+ #\r
+\r
+ $req =& new HTTP_Request($this->_cfg['endpoint'], array('timeout' => $this->_cfg['conn_timeout']));\r
+\r
+ $req->_readTimeout = array($this->_cfg['io_timeout'], 0);\r
+\r
+ $req->setMethod(HTTP_REQUEST_METHOD_POST);\r
+ $req->addRawPostData($body);\r
+\r
+ $req->sendRequest();\r
+\r
+ $this->_http_code = $req->getResponseCode();\r
+ $this->_http_head = $req->getResponseHeader();\r
+ $this->_http_body = $req->getResponseBody();\r
+\r
+ if ($this->_http_code != 200){\r
+\r
+ $this->_err_code = 0;\r
+\r
+ if ($this->_http_code){\r
+ $this->_err_msg = "Bad response from remote server: HTTP status code $this->_http_code";\r
+ }else{\r
+ $this->_err_msg = "Couldn't connect to remote server";\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+\r
+ #\r
+ # create xml tree\r
+ #\r
+\r
+ $tree =& new XML_Tree();\r
+ $tree->getTreeFromString($this->_http_body);\r
+\r
+ $this->tree = $tree;\r
+\r
+\r
+ #\r
+ # check we got an <rsp> element at the root\r
+ #\r
+\r
+ if ($tree->root->name != 'rsp'){\r
+\r
+ $this->_err_code = 0;\r
+ $this->_err_msg = "Bad XML response";\r
+\r
+ return 0;\r
+ }\r
+\r
+\r
+ #\r
+ # stat="fail" ?\r
+ #\r
+\r
+ if ($tree->root->attributes['stat'] == 'fail'){\r
+\r
+ $n = null;\r
+ foreach($tree->root->children as $child){\r
+ if ($child->name == 'err'){\r
+ $n = $child->attributes;\r
+ }\r
+ }\r
+\r
+ $this->_err_code = $n['code'];\r
+ $this->_err_msg = $n['msg'];\r
+\r
+ return 0;\r
+ }\r
+\r
+\r
+ #\r
+ # weird status\r
+ #\r
+\r
+ if ($tree->root->attributes['stat'] != 'ok'){\r
+\r
+ $this->_err_code = 0;\r
+ $this->_err_msg = "Unrecognised REST response status";\r
+\r
+ return 0;\r
+ }\r
+\r
+\r
+ #\r
+ # return the tree\r
+ #\r
+\r
+ return $tree->root;\r
+ }\r
+\r
+\r
+ function getErrorCode(){\r
+ return $this->_err_code;\r
+ }\r
+\r
+ function getErrorMessage(){\r
+ return $this->_err_msg;\r
+ }\r
+\r
+ function getAuthUrl($perms, $frob=''){\r
+\r
+ $args = array(\r
+ 'api_key' => $this->_cfg['api_key'],\r
+ 'perms' => $perms,\r
+ );\r
+\r
+ if (strlen($frob)){ $args['frob'] = $frob; }\r
+\r
+ $args['api_sig'] = $this->signArgs($args);\r
+\r
+ #\r
+ # build the url params\r
+ #\r
+\r
+ $pairs = array();\r
+ foreach($args as $k => $v){\r
+ $pairs[] = urlencode($k).'='.urlencode($v);\r
+ }\r
+\r
+ return $this->_cfg['auth_endpoint'].implode('&', $pairs);\r
+ }\r
+\r
+ function signArgs($args){\r
+ ksort($args);\r
+ $a = '';\r
+ foreach($args as $k => $v){\r
+ $a .= $k . $v;\r
+ }\r
+ return md5($this->_cfg['api_secret'].$a);\r
+ }\r
+\r
+ }\r
+\r
+\r
+?>\r
--- /dev/null
+<?php
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 4 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Author: Stig Bakken <ssb@fast.no> |
+// +----------------------------------------------------------------------+
+//
+// $Id: Parser.php,v 1.1 2004/05/11 20:30:51 cal Exp $
+
+require_once 'PEAR.php';
+
+/**
+ * XML Parser class. This is an XML parser based on PHP's "xml" extension,
+ * based on the bundled expat library.
+ *
+ * @author Stig Bakken <ssb@fast.no>
+ * @todo Tests that need to be made:
+ * - error class
+ * - mixing character encodings
+ * - a test using all expat handlers
+ * - options (folding, output charset)
+ * - different parsing modes
+ *
+ * @notes - It requires PHP 4.0.4pl1 or greater
+ * - From revision 1.17, the function names used by the 'func' mode
+ * are in the format "xmltag_$elem", for example: use "xmltag_name"
+ * to handle the <name></name> tags of your xml file.
+ */
+class XML_Parser extends PEAR
+{
+ // {{{ properties
+
+ /**
+ * @var resource XML parser handle
+ */
+ var $parser;
+
+ /**
+ * @var resource File handle if parsing from a file
+ */
+ var $fp;
+
+ /**
+ * @var boolean Whether to do case folding
+ */
+ var $folding = true;
+
+ /**
+ * @var string Mode of operation, one of "event" or "func"
+ */
+ var $mode;
+
+ /**
+ * Mapping from expat handler function to class method.
+ *
+ * @var array
+ */
+ var $handler = array(
+ 'character_data_handler' => 'cdataHandler',
+ 'default_handler' => 'defaultHandler',
+ 'processing_instruction_handler' => 'piHandler',
+ 'unparsed_entity_decl_handler' => 'unparsedHandler',
+ 'notation_decl_handler' => 'notationHandler',
+ 'external_entity_ref_handler' => 'entityrefHandler'
+ );
+
+ /**
+ * @var string source encoding
+ */
+ var $srcenc;
+
+ /**
+ * @var string target encoding
+ */
+ var $tgtenc;
+
+ /*
+ * Use call_user_func when php >= 4.0.7
+ * @var boolean
+ * @see setMode()
+ */
+ var $use_call_user_func = true;
+
+ // }}}
+ // {{{ constructor
+
+ /**
+ * Creates an XML parser.
+ *
+ * @param string source charset encoding, use NULL (default) to use
+ * whatever the document specifies
+ * @param string how this parser object should work, "event" for
+ * startelement/endelement-type events, "func"
+ * to have it call functions named after elements
+ *
+ * @see xml_parser_create
+ */
+ function XML_Parser($srcenc = null, $mode = "event", $tgtenc = null)
+ {
+ $this->PEAR('XML_Parser_Error');
+
+ if ($srcenc === null) {
+ $xp = @xml_parser_create();
+ } else {
+ $xp = @xml_parser_create($srcenc);
+ }
+ if (is_resource($xp)) {
+ if ($tgtenc !== null) {
+ if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING,
+ $tgtenc)) {
+ return $this->raiseError("invalid target encoding");
+ }
+ }
+ $this->parser = $xp;
+ $this->setMode($mode);
+ xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding);
+ }
+ $this->srcenc = $srcenc;
+ $this->tgtenc = $tgtenc;
+ }
+ // }}}
+
+ // {{{ setMode()
+
+ /**
+ * Sets the mode and all handler.
+ *
+ * @param string
+ * @see $handler
+ */
+ function setMode($mode)
+ {
+
+ $this->mode = $mode;
+
+ xml_set_object($this->parser, $this);
+
+ switch ($mode) {
+
+ case "func":
+ // use call_user_func() when php >= 4.0.7
+ // or call_user_method() if not
+ if (version_compare(phpversion(), '4.0.7', 'lt')) {
+ $this->use_call_user_func = false;
+ } else {
+ $this->use_call_user_func = true;
+ }
+
+ xml_set_element_handler($this->parser, "funcStartHandler", "funcEndHandler");
+ break;
+
+ case "event":
+ xml_set_element_handler($this->parser, "startHandler", "endHandler");
+ break;
+ }
+
+ foreach ($this->handler as $xml_func => $method)
+ if (method_exists($this, $method)) {
+ $xml_func = "xml_set_" . $xml_func;
+ $xml_func($this->parser, $method);
+ }
+
+ }
+
+ // }}}
+ // {{{ setInputFile()
+
+ /**
+ * Defines
+ *
+ * @param string Filename (full path)
+ * @return resource fopen handle of the given file
+ * @throws XML_Parser_Error
+ * @see setInput(), parse()
+ * @access public
+ */
+ function setInputFile($file)
+ {
+
+ $fp = @fopen($file, "rb");
+ if (is_resource($fp)) {
+ $this->fp = $fp;
+ return $fp;
+ }
+
+ return $this->raiseError($php_errormsg);
+ }
+
+ // }}}
+ // {{{ setInput()
+
+ /**
+ * Sets the file handle to use with parse().
+ *
+ * @param resource fopen
+ * @access public
+ * @see parse(), setInputFile()
+ */
+ function setInput($fp)
+ {
+ if (is_resource($fp)) {
+ $this->fp = $fp;
+ return true;
+ }
+
+ return $this->raiseError("not a file resource");
+ }
+
+ // }}}
+ // {{{ parse()
+
+ /**
+ * Central parsing function.
+ *
+ * @throws XML_Parser_Error
+ * @return boolean true on success
+ * @see parseString()
+ * @access public
+ */
+ function parse()
+ {
+ if (!is_resource($this->fp)) {
+ return $this->raiseError("no input");
+ }
+
+ while ($data = fread($this->fp, 2048)) {
+
+ $err = $this->parseString($data, feof($this->fp));
+ if (PEAR::isError($err)) {
+ fclose($this->fp);
+ return $err;
+ }
+
+ }
+
+ fclose($this->fp);
+
+ return true;
+ }
+
+ // }}}
+ // {{{ parseString()
+
+ /**
+ * Parses a string.
+ *
+ * @param string XML data
+ * @param boolean ???
+ * @throws XML_Parser_Error
+ * @return mixed true on success or a string with the xml parser error
+ */
+ function parseString($data, $eof = false)
+ {
+ if (!xml_parse($this->parser, $data, $eof)) {
+ $err = $this->raiseError($this->parser);
+ xml_parser_free($this->parser);
+ return $err;
+ }
+
+ return true;
+ }
+
+ // }}}
+ // {{{ funcStartHandler()
+
+ function funcStartHandler($xp, $elem, $attribs)
+ {
+ $func = 'xmltag_' . $elem;
+ if (method_exists($this, $func)) {
+ if ($this->use_call_user_func) {
+ call_user_func(array(&$this, $func), $xp, $elem, $attribs);
+ } else {
+ call_user_method($func, $this, $xp, $elem, $attribs);
+ }
+ }
+
+ }
+
+ // }}}
+ // {{{ funcEndHandler()
+
+ function funcEndHandler($xp, $elem)
+ {
+ $func = 'xmltag_' . $elem . '_';
+ if (method_exists($this, $func)) {
+ if ($this->use_call_user_func) {
+ call_user_func(array(&$this, $func), $xp, $elem);
+ } else {
+ call_user_method($func, $this, $xp, $elem);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ startHandler()
+
+ /**
+ *
+ * @abstract
+ */
+ function startHandler($xp, $elem, &$attribs)
+ {
+ return NULL;
+ }
+
+ // }}}
+ // {{{ endHandler()
+
+ /**
+ *
+ * @abstract
+ */
+ function endHandler($xp, $elem)
+ {
+ return NULL;
+ }
+
+
+ // }}}
+}
+
+class XML_Parser_Error extends PEAR_Error
+{
+ // {{{ properties
+
+ var $error_message_prefix = 'XML_Parser: ';
+
+ // }}}
+ // {{{ constructor()
+
+ function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE)
+ {
+ if (is_resource($msgorparser)) {
+ $code = xml_get_error_code($msgorparser);
+ $msgorparser = sprintf("%s at XML input line %d",
+ xml_error_string($code),
+ xml_get_current_line_number($msgorparser));
+ }
+ $this->PEAR_Error($msgorparser, $code, $mode, $level);
+
+ }
+
+ // }}}
+}
+?>
\ No newline at end of file
--- /dev/null
+<?php
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 4 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Authors: Bernd Römer <berndr@bonn.edu> |
+// | Sebastian Bergmann <sb@sebastian-bergmann.de> |
+// | Tomas V.V.Cox <cox@idecnet.com> (tree mapping from xml file)|
+// +----------------------------------------------------------------------+
+//
+// $Id: Tree.php,v 1.1 2004/05/11 20:30:51 cal Exp $
+//
+
+require_once 'XML/Parser.php';
+require_once 'XML/Tree/Node.php';
+
+/**
+* PEAR::XML_Tree
+*
+* Purpose
+*
+* Allows for the building of XML data structures
+* using a tree representation, without the need
+* for an extension like DOMXML.
+*
+* Example
+*
+* $tree = new XML_Tree;
+* $root =& $tree->addRoot('root');
+* $foo =& $root->addChild('foo');
+*
+* header('Content-Type: text/xml');
+* $tree->dump();
+*
+* @author Bernd Römer <berndr@bonn.edu>
+* @package XML
+* @version $Version$ - 1.0
+*/
+class XML_Tree extends XML_Parser
+{
+ /**
+ * File Handle
+ *
+ * @var ressource
+ */
+ var $file = NULL;
+
+ /**
+ * Filename
+ *
+ * @var string
+ */
+ var $filename = '';
+
+ /**
+ * Namespace
+ *
+ * @var array
+ */
+ var $namespace = array();
+
+ /**
+ * Root
+ *
+ * @var object XML_Tree_Node
+ */
+ var $root = NULL;
+
+ /**
+ * XML Version
+ *
+ * @var string
+ */
+ var $version = '1.0';
+
+ /**
+ * Constructor
+ *
+ * @param string Filename
+ * @param string XML Version
+ */
+ function XML_Tree($filename = '', $version = '1.0') {
+ $this->filename = $filename;
+ $this->version = $version;
+ }
+
+ /**
+ * Add root node.
+ *
+ * @param string $name name of root element
+ * @return object XML_Tree_Node reference to root node
+ *
+ * @access public
+ */
+ function &addRoot($name, $content = '', $attributes = array()) {
+ $this->root = new XML_Tree_Node($name, $content, $attributes);
+ return $this->root;
+ }
+
+ /**
+ * @deprecated
+ */
+ function &add_root($name, $content = '', $attributes = array()) {
+ return $this->addRoot($name, $content, $attributes);
+ }
+
+ /**
+ * inserts a child/tree (child) into tree ($path,$pos) and
+ * maintains namespace integrity
+ *
+ * @param array $path path to parent of child to remove
+ * @param integer $pos position of child to be inserted in its parents children-list
+ * @param mixed $child child-node (by XML_Tree,XML_Node or Name)
+ * @param string $content content (text) for new node
+ * @param array $attributes attribute-hash for new node
+ *
+ * @return object XML_Tree_Node inserted child (node)
+ * @access public
+ */
+ function &insertChild($path,$pos,$child, $content = '', $attributes = array()) {
+ // update namespace to maintain namespace integrity
+ $count=count($path);
+ foreach($this->namespace as $key => $val) {
+ if ((array_slice($val,0,$count)==$path) && ($val[$count]>=$pos))
+ $this->namespace[$key][$count]++;
+ }
+
+ $parent=&$this->get_node_by_path($path);
+ return($parent->insert_child($pos,$child,$content,$attributes));
+ }
+
+ /**
+ * @deprecated
+ */
+ function &insert_child($path,$pos,$child, $content = '', $attributes = array()) {
+ return $this->insertChild($path, $child, $content, $attributes);
+ }
+
+ /*
+ * removes a child ($path,$pos) from tree ($path,$pos) and
+ * maintains namespace integrity
+ *
+ * @param array $path path to parent of child to remove
+ * @param integer $pos position of child in parents children-list
+ *
+ * @return object XML_Tree_Node parent whichs child was removed
+ * @access public
+ */
+ function &removeChild($path,$pos) {
+ // update namespace to maintain namespace integrity
+ $count=count($path);
+ foreach($this->namespace as $key => $val) {
+ if (array_slice($val,0,$count)==$path) {
+ if ($val[$count]==$pos) { unset($this->namespace[$key]); break; }
+ if ($val[$count]>$pos)
+ $this->namespace[$key][$count]--;
+ }
+ }
+
+ $parent=&$this->get_node_by_path($path);
+ return($parent->remove_child($pos));
+ }
+
+ /**
+ * @deprecated
+ */
+ function &remove_child($path, $pos) {
+ return $this->removeChild($path, $pos);
+ }
+
+ /*
+ * Maps a xml file to a objects tree
+ *
+ * @return mixed The objects tree (XML_tree or an Pear error)
+ * @access public
+ */
+ function &getTreeFromFile ()
+ {
+ $this->folding = false;
+ $this->XML_Parser(null, 'event');
+ $err = $this->setInputFile($this->filename);
+ if (PEAR::isError($err)) {
+ return $err;
+ }
+ $this->cdata = null;
+ $err = $this->parse();
+ if (PEAR::isError($err)) {
+ return $err;
+ }
+ return $this->root;
+ }
+
+ function getTreeFromString($str)
+ {
+ $this->folding = false;
+ $this->XML_Parser(null, 'event');
+ $this->cdata = null;
+ $err = $this->parseString($str);
+ if (PEAR::isError($err)) {
+ return $err;
+ }
+ return $this->root;
+ }
+
+ /**
+ * Handler for the xml-data
+ *
+ * @param mixed $xp ignored
+ * @param string $elem name of the element
+ * @param array $attribs attributes for the generated node
+ *
+ * @access private
+ */
+ function startHandler($xp, $elem, &$attribs)
+ {
+ // root elem
+ if (!isset($this->i)) {
+ $this->obj1 =& $this->add_root($elem, null, $attribs);
+ $this->i = 2;
+ } else {
+ // mixed contents
+ if (!empty($this->cdata)) {
+ $parent_id = 'obj' . ($this->i - 1);
+ $parent =& $this->$parent_id;
+ $parent->children[] = &new XML_Tree_Node(null, $this->cdata);
+ }
+ $obj_id = 'obj' . $this->i++;
+ $this->$obj_id = &new XML_Tree_Node($elem, null, $attribs);
+ }
+ $this->cdata = null;
+ return null;
+ }
+
+ /**
+ * Handler for the xml-data
+ *
+ * @param mixed $xp ignored
+ * @param string $elem name of the element
+ *
+ * @access private
+ */
+ function endHandler($xp, $elem)
+ {
+ $this->i--;
+ if ($this->i > 1) {
+ $obj_id = 'obj' . $this->i;
+ // recover the node created in StartHandler
+ $node =& $this->$obj_id;
+ // mixed contents
+ if (count($node->children) > 0) {
+ if (trim($this->cdata)) {
+ $node->children[] = &new XML_Tree_Node(null, $this->cdata);
+ }
+ } else {
+ $node->set_content($this->cdata);
+ }
+ $parent_id = 'obj' . ($this->i - 1);
+ $parent =& $this->$parent_id;
+ // attach the node to its parent node children array
+ $parent->children[] = $node;
+ }
+ $this->cdata = null;
+ return null;
+ }
+
+ /*
+ * The xml character data handler
+ *
+ * @param mixed $xp ignored
+ * @param string $data PCDATA between tags
+ *
+ * @access private
+ */
+ function cdataHandler($xp, $data)
+ {
+ if (trim($data)) {
+ $this->cdata .= $data;
+ }
+ }
+
+ /**
+ * Get a copy of this tree.
+ *
+ * @return object XML_Tree
+ * @access public
+ */
+ function clone() {
+ $clone=new XML_Tree($this->filename,$this->version);
+ $clone->root=$this->root->clone();
+
+ // clone all other vars
+ $temp=get_object_vars($this);
+ foreach($temp as $varname => $value)
+ if (!in_array($varname,array('filename','version','root')))
+ $clone->$varname=$value;
+
+ return($clone);
+ }
+
+ /**
+ * Print text representation of XML tree.
+ *
+ * @access public
+ */
+ function dump() {
+ echo $this->get();
+ }
+
+ /**
+ * Get text representation of XML tree.
+ *
+ * @return string XML
+ * @access public
+ */
+ function &get() {
+ $out = '<?xml version="' . $this->version . "\"?>\n";
+ $out .= $this->root->get();
+
+ return $out;
+ }
+
+ /**
+ * Get current namespace.
+ *
+ * @param string $name namespace
+ * @return string
+ *
+ * @access public
+ */
+ function &getName($name) {
+ return $this->root->get_element($this->namespace[$name]);
+ }
+
+ /**
+ * @deprecated
+ */
+ function &get_name($name) {
+ return $this->getName($name);
+ }
+
+ /**
+ * Register a namespace.
+ *
+ * @param string $name namespace
+ * @param string $path path
+ *
+ * @access public
+ */
+ function registerName($name, $path) {
+ $this->namespace[$name] = $path;
+ }
+
+ /**
+ * @deprecated
+ */
+ function register_name($name, $path) {
+ return $this->registerName($name, $path);
+ }
+}
+?>
--- /dev/null
+<?php
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 4 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Authors: Bernd Römer <berndr@bonn.edu> |
+// | Sebastian Bergmann <sb@sebastian-bergmann.de> |
+// | Christian Kühn <ck@chkuehn.de> (escape xml entities) |
+// +----------------------------------------------------------------------+
+//
+// $Id: Node.php,v 1.2 2004/08/27 21:26:38 cal Exp $
+//
+
+/**
+* PEAR::XML_Tree_Node
+*
+* @author Bernd Römer <berndr@bonn.edu>
+* @package XML_Tree
+* @version 1.0 16-Aug-2001
+*/
+class XML_Tree_Node {
+ /**
+ * Attributes of this node
+ *
+ * @var array
+ */
+ var $attributes;
+
+ /**
+ * Children of this node
+ *
+ * @var array
+ */
+ var $children;
+
+ /**
+ * Content
+ *
+ * @var string
+ */
+ var $content;
+
+ /**
+ * Name
+ *
+ * @var string
+ */
+ var $name;
+
+ /**
+ * Constructor
+ *
+ * @param string name
+ * @param string content
+ * @param array attributes
+ */
+ function XML_Tree_Node($name, $content = '', $attributes = array()) {
+ $this->attributes = $attributes;
+ $this->children = array();
+ $this->set_content($content);
+ $this->name = $name;
+ }
+
+ /**
+ * Adds a child node to this node.
+ *
+ * @param mixed child
+ * @param string content
+ * @param array attributes
+ * @return object reference to new child node
+ */
+ function &addChild($child, $content = '', $attributes = array()) {
+ $index = sizeof($this->children);
+
+ if (is_object($child)) {
+ if (strtolower(get_class($child)) == 'xml_tree_node') {
+ $this->children[$index] = $child;
+ }
+
+ if (strtolower(get_class($child)) == 'xml_tree' && isset($child->root)) {
+ $this->children[$index] = $child->root->get_element();
+ }
+ } else {
+ $this->children[$index] = new XML_Tree_Node($child, $content, $attributes);
+ }
+
+ return $this->children[$index];
+ }
+
+ /**
+ * @deprecated
+ */
+ function &add_child($child, $content = '', $attributes = array()) {
+ return $this->addChild($child, $content, $attributes);
+ }
+
+ /**
+ * clone node and all its children (recursive)
+ *
+ * @return object reference to the clone-node
+ */
+ function &clone() {
+ $clone=new XML_Tree_Node($this->name,$this->content,$this->attributes);
+
+ $max_child=count($this->children);
+ for($i=0;$i<$max_child;$i++) {
+ $clone->children[]=$this->children[$i]->clone();
+ }
+
+ /* for future use....
+ // clone all other vars
+ $temp=get_object_vars($this);
+ foreach($temp as $varname => $value)
+ if (!in_array($varname,array('name','content','attributes','children')))
+ $clone->$varname=$value;
+ */
+
+ return($clone);
+ }
+
+ /**
+ * inserts child ($child) to a specified child-position ($pos)
+ *
+ * @return inserted node
+ */
+ function &insertChild($path,$pos,&$child, $content = '', $attributes = array()) {
+ // direct insert of objects useing array_splice() faild :(
+ array_splice($this->children,$pos,0,'dummy');
+ if (is_object($child)) { // child offered is not instanziated
+ // insert a single node
+ if (strtolower(get_class($child)) == 'xml_tree_node') {
+ $this->children[$pos]=&$child;
+ }
+ // insert a tree i.e insert root-element
+ if (strtolower(get_class($child)) == 'xml_tree' && isset($child->root)) {
+ $this->children[$pos]=$child->root->get_element();
+ }
+ } else { // child offered is not instanziated
+ $this->children[$pos]=new XML_Tree_Node($child, $content, $attributes);
+ }
+ return($this);
+ }
+
+ /**
+ * @deprecated
+ */
+ function &insert_child($path,$pos,&$child, $content = '', $attributes = array()) {
+ return $this->insertChild($path,$pos,$child, $content, $attributes);
+ }
+
+ /**
+ * removes child ($pos)
+ *
+ * @param integer pos position of child in children-list
+ *
+ * @return removed node
+ */
+ function &removeChild($pos) {
+ // array_splice() instead of a simple unset() to maintain index-integrity
+ return(array_splice($this->children,$pos,1));
+ }
+
+ /**
+ * @deprecated
+ */
+ function &remove_child($pos) {
+ return $this->removeChild($pos);
+ }
+
+ /**
+ * Returns text representation of this node.
+ *
+ * @return string xml
+ */
+ function &get()
+ {
+ static $deep = -1;
+ static $do_ident = true;
+ $deep++;
+ if ($this->name !== null) {
+ $ident = str_repeat(' ', $deep);
+ if ($do_ident) {
+ $out = $ident . '<' . $this->name;
+ } else {
+ $out = '<' . $this->name;
+ }
+ foreach ($this->attributes as $name => $value) {
+ $out .= ' ' . $name . '="' . $value . '"';
+ }
+
+ $out .= '>' . $this->content;
+
+ if (sizeof($this->children) > 0) {
+ $out .= "\n";
+ foreach ($this->children as $child) {
+ $out .= $child->get();
+ }
+ } else {
+ $ident = '';
+ }
+ if ($do_ident) {
+ $out .= $ident . '</' . $this->name . ">\n";
+ } else {
+ $out .= '</' . $this->name . '>';
+ }
+ $do_ident = true;
+ } else {
+ $out = $this->content;
+ $do_ident = false;
+ }
+ $deep--;
+ return $out;
+ }
+
+ /**
+ * Gets an attribute by its name.
+ *
+ * @param string name
+ * @return string attribute
+ */
+ function getAttribute($name) {
+ return $this->attributes[strtolower($name)];
+ }
+
+ /**
+ * @deprecated
+ */
+ function get_attribute($name) {
+ return $this->getAttribute($name);
+ }
+
+ /**
+ * Gets an element by its 'path'.
+ *
+ * @param string path
+ * @return object element
+ */
+ function &getElement($path) {
+ if (sizeof($path) == 0) {
+ return $this;
+ }
+
+ $next = array_shift($path);
+
+ return $this->children[$next]->get_element($path);
+ }
+
+ /**
+ * @deprecated
+ */
+ function &get_element($path) {
+ return $this->getElement($path);
+ }
+
+ /**
+ * Sets an attribute.
+ *
+ * @param string name
+ * @param string value
+ */
+ function setAttribute($name, $value = '') {
+ $this->attributes[strtolower($name)] = $value;
+ }
+
+ /**
+ * @deprecated
+ */
+ function set_attribute($name, $value = '') {
+ return $this->setAttribute($name, $value);
+ }
+
+ /**
+ * Unsets an attribute.
+ *
+ * @param string name
+ */
+ function unsetAttribute($name) {
+ unset($this->attributes[strtolower($name)]);
+ }
+
+ /**
+ * @deprecated
+ */
+ function unset_attribute($name) {
+ return $this->unsetAttribute($name);
+ }
+
+ /**
+ *
+ *
+ */
+ function setContent(&$content)
+ {
+ # WHAT THE FUCK IS WRONG WITH PEOPLE?
+ #$this->content = $this->_xml_entities($content);
+ $this->content = $content;
+ }
+
+ function set_content(&$content)
+ {
+ return $this->setContent($content);
+ }
+
+ /**
+ * Escape XML entities.
+ *
+ * @param string xml
+ * @return string xml
+ * @access private
+ */
+ function _xml_entities($xml) {
+ $xml = str_replace(array('ü', 'Ü', 'ö',
+ 'Ö', 'ä', 'Ä',
+ 'ß'
+ ),
+ array('ü', 'Ü', 'ö',
+ 'Ö', 'ä', 'Ä',
+ 'ß'
+ ),
+ $xml
+ );
+
+ $xml = preg_replace(array("/\&([a-z\d\#]+)\;/i",
+ "/\&/",
+ "/\#\|\|([a-z\d\#]+)\|\|\#/i",
+ "/([^a-zA-Z\d\s\<\>\&\;\.\:\=\"\-\/\%\?\!\'\(\)\[\]\{\}\$\#\+\,\@_])/e"
+ ),
+ array("#||\\1||#",
+ "&",
+ "&\\1;",
+ "'&#'.ord('\\1').';'"
+ ),
+ $xml
+ );
+
+ return $xml;
+ }
+
+ /**
+ * Print text representation of XML tree.
+ */
+ function dump() {
+ echo $this->get();
+ }
+}
+?>