import
[web.mtrack] / inc / lib / Auth / Yadis / XML.php
1 <?php
2
3 /**
4  * XML-parsing classes to wrap the domxml and DOM extensions for PHP 4
5  * and 5, respectively.
6  *
7  * @package OpenID
8  */
9
10 /**
11  * The base class for wrappers for available PHP XML-parsing
12  * extensions.  To work with this Yadis library, subclasses of this
13  * class MUST implement the API as defined in the remarks for this
14  * class.  Subclasses of Auth_Yadis_XMLParser are used to wrap
15  * particular PHP XML extensions such as 'domxml'.  These are used
16  * internally by the library depending on the availability of
17  * supported PHP XML extensions.
18  *
19  * @package OpenID
20  */
21 class Auth_Yadis_XMLParser {
22     /**
23      * Initialize an instance of Auth_Yadis_XMLParser with some
24      * XML and namespaces.  This SHOULD NOT be overridden by
25      * subclasses.
26      *
27      * @param string $xml_string A string of XML to be parsed.
28      * @param array $namespace_map An array of ($ns_name => $ns_uri)
29      * to be registered with the XML parser.  May be empty.
30      * @return boolean $result True if the initialization and
31      * namespace registration(s) succeeded; false otherwise.
32      */
33     function init($xml_string, $namespace_map)
34     {
35         if (!$this->setXML($xml_string)) {
36             return false;
37         }
38
39         foreach ($namespace_map as $prefix => $uri) {
40             if (!$this->registerNamespace($prefix, $uri)) {
41                 return false;
42             }
43         }
44
45         return true;
46     }
47
48     /**
49      * Register a namespace with the XML parser.  This should be
50      * overridden by subclasses.
51      *
52      * @param string $prefix The namespace prefix to appear in XML tag
53      * names.
54      *
55      * @param string $uri The namespace URI to be used to identify the
56      * namespace in the XML.
57      *
58      * @return boolean $result True if the registration succeeded;
59      * false otherwise.
60      */
61     function registerNamespace($prefix, $uri)
62     {
63         // Not implemented.
64     }
65
66     /**
67      * Set this parser object's XML payload.  This should be
68      * overridden by subclasses.
69      *
70      * @param string $xml_string The XML string to pass to this
71      * object's XML parser.
72      *
73      * @return boolean $result True if the initialization succeeded;
74      * false otherwise.
75      */
76     function setXML($xml_string)
77     {
78         // Not implemented.
79     }
80
81     /**
82      * Evaluate an XPath expression and return the resulting node
83      * list.  This should be overridden by subclasses.
84      *
85      * @param string $xpath The XPath expression to be evaluated.
86      *
87      * @param mixed $node A node object resulting from a previous
88      * evalXPath call.  This node, if specified, provides the context
89      * for the evaluation of this xpath expression.
90      *
91      * @return array $node_list An array of matching opaque node
92      * objects to be used with other methods of this parser class.
93      */
94     function &evalXPath($xpath, $node = null)
95     {
96         // Not implemented.
97     }
98
99     /**
100      * Return the textual content of a specified node.
101      *
102      * @param mixed $node A node object from a previous call to
103      * $this->evalXPath().
104      *
105      * @return string $content The content of this node.
106      */
107     function content($node)
108     {
109         // Not implemented.
110     }
111
112     /**
113      * Return the attributes of a specified node.
114      *
115      * @param mixed $node A node object from a previous call to
116      * $this->evalXPath().
117      *
118      * @return array $attrs An array mapping attribute names to
119      * values.
120      */
121     function attributes($node)
122     {
123         // Not implemented.
124     }
125 }
126
127 /**
128  * This concrete implementation of Auth_Yadis_XMLParser implements
129  * the appropriate API for the 'domxml' extension which is typically
130  * packaged with PHP 4.  This class will be used whenever the 'domxml'
131  * extension is detected.  See the Auth_Yadis_XMLParser class for
132  * details on this class's methods.
133  *
134  * @package OpenID
135  */
136 class Auth_Yadis_domxml extends Auth_Yadis_XMLParser {
137     function Auth_Yadis_domxml()
138     {
139         $this->xml = null;
140         $this->doc = null;
141         $this->xpath = null;
142         $this->errors = array();
143     }
144
145     function setXML($xml_string)
146     {
147         $this->xml = $xml_string;
148         $this->doc = @domxml_open_mem($xml_string, DOMXML_LOAD_PARSING,
149                                       $this->errors);
150
151         if (!$this->doc) {
152             return false;
153         }
154
155         $this->xpath = $this->doc->xpath_new_context();
156
157         return true;
158     }
159
160     function registerNamespace($prefix, $uri)
161     {
162         return xpath_register_ns($this->xpath, $prefix, $uri);
163     }
164
165     function &evalXPath($xpath, $node = null)
166     {
167         if ($node) {
168             $result = @$this->xpath->xpath_eval($xpath, $node);
169         } else {
170             $result = @$this->xpath->xpath_eval($xpath);
171         }
172
173         if (!$result) {
174             $n = array();
175             return $n;
176         }
177
178         if (!$result->nodeset) {
179             $n = array();
180             return $n;
181         }
182
183         return $result->nodeset;
184     }
185
186     function content($node)
187     {
188         if ($node) {
189             return $node->get_content();
190         }
191     }
192
193     function attributes($node)
194     {
195         if ($node) {
196             $arr = $node->attributes();
197             $result = array();
198
199             if ($arr) {
200                 foreach ($arr as $attrnode) {
201                     $result[$attrnode->name] = $attrnode->value;
202                 }
203             }
204
205             return $result;
206         }
207     }
208 }
209
210 /**
211  * This concrete implementation of Auth_Yadis_XMLParser implements
212  * the appropriate API for the 'dom' extension which is typically
213  * packaged with PHP 5.  This class will be used whenever the 'dom'
214  * extension is detected.  See the Auth_Yadis_XMLParser class for
215  * details on this class's methods.
216  *
217  * @package OpenID
218  */
219 class Auth_Yadis_dom extends Auth_Yadis_XMLParser {
220     function Auth_Yadis_dom()
221     {
222         $this->xml = null;
223         $this->doc = null;
224         $this->xpath = null;
225         $this->errors = array();
226     }
227
228     function setXML($xml_string)
229     {
230         $this->xml = $xml_string;
231         $this->doc = new DOMDocument;
232
233         if (!$this->doc) {
234             return false;
235         }
236
237         if (!@$this->doc->loadXML($xml_string)) {
238             return false;
239         }
240
241         $this->xpath = new DOMXPath($this->doc);
242
243         if ($this->xpath) {
244             return true;
245         } else {
246             return false;
247         }
248     }
249
250     function registerNamespace($prefix, $uri)
251     {
252         return $this->xpath->registerNamespace($prefix, $uri);
253     }
254
255     function &evalXPath($xpath, $node = null)
256     {
257         if ($node) {
258             $result = @$this->xpath->query($xpath, $node);
259         } else {
260             $result = @$this->xpath->query($xpath);
261         }
262
263         $n = array();
264
265         if (!$result) {
266             return $n;
267         }
268
269         for ($i = 0; $i < $result->length; $i++) {
270             $n[] = $result->item($i);
271         }
272
273         return $n;
274     }
275
276     function content($node)
277     {
278         if ($node) {
279             return $node->textContent;
280         }
281     }
282
283     function attributes($node)
284     {
285         if ($node) {
286             $arr = $node->attributes;
287             $result = array();
288
289             if ($arr) {
290                 for ($i = 0; $i < $arr->length; $i++) {
291                     $node = $arr->item($i);
292                     $result[$node->nodeName] = $node->nodeValue;
293                 }
294             }
295
296             return $result;
297         }
298     }
299 }
300
301 global $__Auth_Yadis_defaultParser;
302 $__Auth_Yadis_defaultParser = null;
303
304 /**
305  * Set a default parser to override the extension-driven selection of
306  * available parser classes.  This is helpful in a test environment or
307  * one in which multiple parsers can be used but one is more
308  * desirable.
309  *
310  * @param Auth_Yadis_XMLParser $parser An instance of a
311  * Auth_Yadis_XMLParser subclass.
312  */
313 function Auth_Yadis_setDefaultParser(&$parser)
314 {
315     global $__Auth_Yadis_defaultParser;
316     $__Auth_Yadis_defaultParser =& $parser;
317 }
318
319 function Auth_Yadis_getSupportedExtensions()
320 {
321     return array(
322                  'dom' => array('classname' => 'Auth_Yadis_dom',
323                        'libname' => array('dom.so', 'dom.dll')),
324                  'domxml' => array('classname' => 'Auth_Yadis_domxml',
325                        'libname' => array('domxml.so', 'php_domxml.dll')),
326                  );
327 }
328
329 /**
330  * Returns an instance of a Auth_Yadis_XMLParser subclass based on
331  * the availability of PHP extensions for XML parsing.  If
332  * Auth_Yadis_setDefaultParser has been called, the parser used in
333  * that call will be returned instead.
334  */
335 function &Auth_Yadis_getXMLParser()
336 {
337     global $__Auth_Yadis_defaultParser;
338
339     if (isset($__Auth_Yadis_defaultParser)) {
340         return $__Auth_Yadis_defaultParser;
341     }
342
343     $p = null;
344     $classname = null;
345
346     $extensions = Auth_Yadis_getSupportedExtensions();
347
348     // Return a wrapper for the resident implementation, if any.
349     foreach ($extensions as $name => $params) {
350         if (!extension_loaded($name)) {
351             foreach ($params['libname'] as $libname) {
352                 if (@dl($libname)) {
353                     $classname = $params['classname'];
354                 }
355             }
356         } else {
357             $classname = $params['classname'];
358         }
359         if (isset($classname)) {
360             $p = new $classname();
361             return $p;
362         }
363     }
364
365     if (!isset($p)) {
366         trigger_error('No XML parser was found', E_USER_ERROR);
367     } else {
368         Auth_Yadis_setDefaultParser($p);
369     }
370
371     return $p;
372 }
373
374 ?>