1<?php
2/**
3 *  * @version 1.61
4 * @author  Simon Willison
5 * @date    11th July 2003
6 * @link    http://scripts.incutio.com/xmlrpc/
7 * @link    http://scripts.incutio.com/xmlrpc/manual.php
8 * @license Artistic License http://www.opensource.org/licenses/artistic-license.php
9 *
10 * Modified for DokuWiki
11 * @author  Andreas Gohr <andi@splitbrain.org>
12 * @author Magnus Wolf <mwolf2706@googlemail.com>
13 */
14
15require_once('./IJR_Error.php');
16
17class IJR_Message {
18    var $message;
19    var $messageType;  // methodCall / methodResponse / fault
20    var $faultCode;
21    var $faultString;
22    var $methodName;
23    var $params;
24    // Current variable stacks
25    var $_arraystructs = array();   // The stack used to keep track of the current array/struct
26    var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array
27    var $_currentStructName = array();  // A stack as well
28    var $_param;
29    var $_value;
30    var $_currentTag;
31    var $_currentTagContents;
32    // The XML parser
33    var $_parser;
34    function IJR_Message ($message) {
35        $this->message = $message;
36    }
37    function parse() {
38        $this->message = preg_replace('/<\?xml(.*)?\?'.'>/', '', $this->message);
39        $this->message = str_replace('&lt;', '&#60;', $this->message);
40        $this->message = str_replace('&gt;', '&#62;', $this->message);
41        $this->message = str_replace('&amp;', '&#38;', $this->message);
42        $this->message = str_replace('&apos;', '&#39;', $this->message);
43        $this->message = str_replace('&quot;', '&#34;', $this->message);
44        if (trim($this->message) == '') {
45            return false;
46        }
47        $this->_parser = xml_parser_create();
48        xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false);
49        xml_set_object($this->_parser, $this);
50        xml_set_element_handler($this->_parser, 'tag_open', 'tag_close');
51        xml_set_character_data_handler($this->_parser, 'cdata');
52        if (!xml_parse($this->_parser, $this->message)) {
53            return false;
54        }
55        xml_parser_free($this->_parser);
56        if ($this->messageType == 'fault') {
57            $this->faultCode = $this->params[0]['faultCode'];
58            $this->faultString = $this->params[0]['faultString'];
59        }
60        return true;
61    }
62    function tag_open($parser, $tag, $attr) {
63        $this->currentTag = $tag;
64        $this->_currentTagContents = '';
65        switch($tag) {
66            case 'methodCall':
67            case 'methodResponse':
68            case 'fault':
69                $this->messageType = $tag;
70                break;
71            case 'data':    // data is to all intents and puposes more interesting than array
72                $this->_arraystructstypes[] = 'array';
73                $this->_arraystructs[] = array();
74                break;
75            case 'struct':
76                $this->_arraystructstypes[] = 'struct';
77                $this->_arraystructs[] = array();
78                break;
79        }
80    }
81    function cdata($parser, $cdata) {
82        $this->_currentTagContents .= $cdata;
83    }
84    function tag_close($parser, $tag) {
85        $valueFlag = false;
86        switch($tag) {
87            case 'int':
88            case 'i4':
89                $value = (int)trim($this->_currentTagContents);
90                $this->_currentTagContents = '';
91                $valueFlag = true;
92                break;
93            case 'double':
94                $value = (double)trim($this->_currentTagContents);
95                $this->_currentTagContents = '';
96                $valueFlag = true;
97                break;
98            case 'string':
99                $value = (string)$this->_currentTagContents;
100                $this->_currentTagContents = '';
101                $valueFlag = true;
102                break;
103            case 'dateTime.iso8601':
104                $value = new IJR_Date(trim($this->_currentTagContents));
105                $this->_currentTagContents = '';
106                $valueFlag = true;
107                break;
108            case 'value':
109                if (trim($this->_currentTagContents) != '') {
110                    $value = (string)$this->_currentTagContents;
111                    $this->_currentTagContents = '';
112                    $valueFlag = true;
113                }
114                break;
115            case 'boolean':
116                $value = (boolean)trim($this->_currentTagContents);
117                $this->_currentTagContents = '';
118                $valueFlag = true;
119                break;
120            case 'base64':
121                $value = base64_decode($this->_currentTagContents);
122                $this->_currentTagContents = '';
123                $valueFlag = true;
124                break;
125            case 'data':
126            case 'struct':
127                $value = array_pop($this->_arraystructs);
128                array_pop($this->_arraystructstypes);
129                $valueFlag = true;
130                break;
131            case 'member':
132                array_pop($this->_currentStructName);
133                break;
134            case 'name':
135                $this->_currentStructName[] = trim($this->_currentTagContents);
136                $this->_currentTagContents = '';
137                break;
138            case 'methodName':
139                $this->methodName = trim($this->_currentTagContents);
140                $this->_currentTagContents = '';
141                break;
142        }
143        if ($valueFlag) {
144            if (count($this->_arraystructs) > 0) {
145                if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') {
146                    $this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value;
147                } else {
148                    $this->_arraystructs[count($this->_arraystructs)-1][] = $value;
149                }
150            } else {
151                $this->params[] = $value;
152            }
153        }
154    }
155}