1: <?php
2: // $Id: xmlrpcparser.php,v 1.1 2007/05/15 02:34:53 minahito Exp $
3: // ------------------------------------------------------------------------ //
4: // XOOPS - PHP Content Management System //
5: // Copyright (c) 2000 XOOPS.org //
6: // <http://www.xoops.org/> //
7: // ------------------------------------------------------------------------ //
8: // This program is free software; you can redistribute it and/or modify //
9: // it under the terms of the GNU General Public License as published by //
10: // the Free Software Foundation; either version 2 of the License, or //
11: // (at your option) any later version. //
12: // //
13: // You may not change or alter any portion of this comment or credits //
14: // of supporting developers from this source code or any supporting //
15: // source code which is considered copyrighted (c) material of the //
16: // original comment or credit authors. //
17: // //
18: // This program is distributed in the hope that it will be useful, //
19: // but WITHOUT ANY WARRANTY; without even the implied warranty of //
20: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
21: // GNU General Public License for more details. //
22: // //
23: // You should have received a copy of the GNU General Public License //
24: // along with this program; if not, write to the Free Software //
25: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //
26: // ------------------------------------------------------------------------ //
27: // Author: Kazumi Ono (AKA onokazu) //
28: // URL: http://www.myweb.ne.jp/, http://www.xoops.org/, http://jp.xoops.org/ //
29: // Project: The XOOPS Project //
30: // ------------------------------------------------------------------------- //
31:
32: if (!defined('XOOPS_ROOT_PATH')) exit();
33:
34: require_once XOOPS_ROOT_PATH.'/class/xml/saxparser.php';
35: require_once XOOPS_ROOT_PATH.'/class/xml/xmltaghandler.php';
36:
37: /**
38: * Class RSS Parser
39: *
40: * This class offers methods to parse RSS Files
41: *
42: * @link http://www.xoops.org/ Latest release of this class
43: * @package XOOPS
44: * @copyright Copyright (c) 2001 xoops.org. All rights reserved.
45: * @author Kazumi Ono <onokazu@xoops.org>
46: * @version 1.6 ($Date: 2007/05/15 02:34:53 $) $Revision: 1.1 $
47: * @access public
48: */
49:
50: class XoopsXmlRpcParser extends SaxParser
51: {
52:
53: /**
54: *
55: *
56: *
57: *
58: * @access private
59: * @var array
60: */
61: var $_param;
62:
63: /**
64: *
65: *
66: *
67: *
68: * @access private
69: * @var string
70: */
71: var $_methodName;
72:
73: /**
74: *
75: *
76: *
77: *
78: * @access private
79: * @var array
80: */
81: var $_tempName;
82:
83: /**
84: *
85: *
86: *
87: *
88: * @access private
89: * @var array
90: */
91: var $_tempValue;
92:
93: /**
94: *
95: *
96: *
97: *
98: * @access private
99: * @var array
100: */
101: var $_tempMember;
102:
103: /**
104: *
105: *
106: *
107: *
108: * @access private
109: * @var array
110: */
111: var $_tempStruct;
112:
113: /**
114: *
115: *
116: *
117: *
118: * @access private
119: * @var array
120: */
121: var $_tempArray;
122:
123: /**
124: *
125: *
126: *
127: *
128: * @access private
129: * @var array
130: */
131: var $_workingLevel = array();
132:
133:
134: /**
135: * Constructor of the class
136: *
137: *
138: *
139: *
140: * @access
141: * @author
142: * @see
143: */
144: function XoopsXmlRpcParser(&$input)
145: {
146: $this->SaxParser($input);
147: $this->addTagHandler(new RpcMethodNameHandler());
148: $this->addTagHandler(new RpcIntHandler());
149: $this->addTagHandler(new RpcDoubleHandler());
150: $this->addTagHandler(new RpcBooleanHandler());
151: $this->addTagHandler(new RpcStringHandler());
152: $this->addTagHandler(new RpcDateTimeHandler());
153: $this->addTagHandler(new RpcBase64Handler());
154: $this->addTagHandler(new RpcNameHandler());
155: $this->addTagHandler(new RpcValueHandler());
156: $this->addTagHandler(new RpcMemberHandler());
157: $this->addTagHandler(new RpcStructHandler());
158: $this->addTagHandler(new RpcArrayHandler());
159: }
160:
161: /**
162: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
163: *
164: * @access
165: * @author
166: * @param
167: * @return
168: * @see
169: */
170: function setTempName($name)
171: {
172: $this->_tempName[$this->getWorkingLevel()] = $name;
173: }
174:
175: /**
176: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
177: *
178: * @access
179: * @author
180: * @param
181: * @return
182: * @see
183: */
184: function getTempName()
185: {
186: return $this->_tempName[$this->getWorkingLevel()];
187: }
188:
189: /**
190: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
191: *
192: * @access
193: * @author
194: * @param
195: * @return
196: * @see
197: */
198: function setTempValue($value)
199: {
200: if (is_array($value)) {
201: settype($this->_tempValue, 'array');
202: foreach ($value as $k => $v) {
203: $this->_tempValue[$k] = $v;
204: }
205: } elseif (is_string($value)) {
206: if (isset($this->_tempValue)) {
207: if (is_string($this->_tempValue)) {
208: $this->_tempValue .= $value;
209: }
210: } else {
211: $this->_tempValue = $value;
212: }
213: } else {
214: $this->_tempValue = $value;
215: }
216: }
217:
218: /**
219: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
220: *
221: * @access
222: * @author
223: * @param
224: * @return
225: * @see
226: */
227: function getTempValue()
228: {
229: return $this->_tempValue;
230: }
231:
232: /**
233: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
234: *
235: * @access
236: * @author
237: * @param
238: * @return
239: * @see
240: */
241: function resetTempValue()
242: {
243: unset($this->_tempValue);
244: }
245:
246: /**
247: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
248: *
249: * @access
250: * @author
251: * @param
252: * @return
253: * @see
254: */
255: function setTempMember($name, $value)
256: {
257: $this->_tempMember[$this->getWorkingLevel()][$name] = $value;
258: }
259:
260: /**
261: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
262: *
263: * @access
264: * @author
265: * @param
266: * @return
267: * @see
268: */
269: function getTempMember()
270: {
271: return $this->_tempMember[$this->getWorkingLevel()];
272: }
273:
274: /**
275: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
276: *
277: * @access
278: * @author
279: * @param
280: * @return
281: * @see
282: */
283: function resetTempMember()
284: {
285: $this->_tempMember[$this->getCurrentLevel()] = array();
286: }
287:
288: /**
289: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
290: *
291: * @access
292: * @author
293: * @param
294: * @return
295: * @see
296: */
297: function setWorkingLevel()
298: {
299: array_push($this->_workingLevel, $this->getCurrentLevel());
300: }
301:
302: /**
303: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
304: *
305: * @access
306: * @author
307: * @param
308: * @return
309: * @see
310: */
311: function getWorkingLevel()
312: {
313: return $this->_workingLevel[count($this->_workingLevel) - 1];
314: }
315:
316: /**
317: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
318: *
319: * @access
320: * @author
321: * @param
322: * @return
323: * @see
324: */
325: function releaseWorkingLevel()
326: {
327: array_pop($this->_workingLevel);
328: }
329:
330: /**
331: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
332: *
333: * @access
334: * @author
335: * @param
336: * @return
337: * @see
338: */
339: function setTempStruct($member)
340: {
341: $key = key($member);
342: $this->_tempStruct[$this->getWorkingLevel()][$key] = $member[$key];
343: }
344:
345: /**
346: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
347: *
348: * @access
349: * @author
350: * @param
351: * @return
352: * @see
353: */
354: function getTempStruct()
355: {
356: return $this->_tempStruct[$this->getWorkingLevel()];
357: }
358:
359: /**
360: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
361: *
362: * @access
363: * @author
364: * @param
365: * @return
366: * @see
367: */
368: function resetTempStruct()
369: {
370: $this->_tempStruct[$this->getCurrentLevel()] = array();
371: }
372:
373: /**
374: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
375: *
376: * @access
377: * @author
378: * @param
379: * @return
380: * @see
381: */
382: function setTempArray($value)
383: {
384: $this->_tempArray[$this->getWorkingLevel()][] = $value;
385: }
386:
387: /**
388: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
389: *
390: * @access
391: * @author
392: * @param
393: * @return
394: * @see
395: */
396: function getTempArray()
397: {
398: return $this->_tempArray[$this->getWorkingLevel()];
399: }
400:
401: /**
402: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
403: *
404: * @access
405: * @author
406: * @param
407: * @return
408: * @see
409: */
410: function resetTempArray()
411: {
412: $this->_tempArray[$this->getCurrentLevel()] = array();
413: }
414:
415: /**
416: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
417: *
418: * @access
419: * @author
420: * @param
421: * @return
422: * @see
423: */
424: function setMethodName($methodName)
425: {
426: $this->_methodName = $methodName;
427: }
428:
429: /**
430: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
431: *
432: * @access
433: * @author
434: * @param
435: * @return
436: * @see
437: */
438: function getMethodName()
439: {
440: return $this->_methodName;
441: }
442:
443: /**
444: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
445: *
446: * @access
447: * @author
448: * @param
449: * @return
450: * @see
451: */
452: function setParam($value)
453: {
454: $this->_param[] = $value;
455: }
456:
457: /**
458: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
459: *
460: * @access
461: * @author
462: * @param
463: * @return
464: * @see
465: */
466: function &getParam()
467: {
468: return $this->_param;
469: }
470: }
471:
472:
473: class RpcMethodNameHandler extends XmlTagHandler
474: {
475:
476: /**
477: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
478: *
479: * @access
480: * @author
481: * @param
482: * @return
483: * @see
484: */
485: function getName()
486: {
487: return 'methodName';
488: }
489:
490: /**
491: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
492: *
493: * @access
494: * @author
495: * @param
496: * @return
497: * @see
498: */
499: function handleCharacterData(&$parser, &$data)
500: {
501: $parser->setMethodName($data);
502: }
503: }
504:
505: class RpcIntHandler extends XmlTagHandler
506: {
507:
508: /**
509: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
510: *
511: * @access
512: * @author
513: * @param
514: * @return
515: * @see
516: */
517: function getName()
518: {
519: return array('int', 'i4');
520: }
521:
522: /**
523: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
524: *
525: * @access
526: * @author
527: * @param
528: * @return
529: * @see
530: */
531: function handleCharacterData(&$parser, &$data)
532: {
533: $parser->setTempValue(intval($data));
534: }
535: }
536:
537: class RpcDoubleHandler extends XmlTagHandler
538: {
539:
540: /**
541: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
542: *
543: * @access
544: * @author
545: * @param
546: * @return
547: * @see
548: */
549: function getName()
550: {
551: return 'double';
552: }
553:
554: /**
555: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
556: *
557: * @access
558: * @author
559: * @param
560: * @return
561: * @see
562: */
563: function handleCharacterData(&$parser, &$data)
564: {
565: $data = (float)$data;
566: $parser->setTempValue($data);
567: }
568: }
569:
570: class RpcBooleanHandler extends XmlTagHandler
571: {
572:
573: /**
574: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
575: *
576: * @access
577: * @author
578: * @param
579: * @return
580: * @see
581: */
582: function getName()
583: {
584: return 'boolean';
585: }
586:
587: /**
588: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
589: *
590: * @access
591: * @author
592: * @param
593: * @return
594: * @see
595: */
596: function handleCharacterData(&$parser, &$data)
597: {
598: $data = (boolean)$data;
599: $parser->setTempValue($data);
600: }
601: }
602:
603: class RpcStringHandler extends XmlTagHandler
604: {
605:
606: /**
607: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
608: *
609: * @access
610: * @author
611: * @param
612: * @return
613: * @see
614: */
615: function getName()
616: {
617: return 'string';
618: }
619:
620: /**
621: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
622: *
623: * @access
624: * @author
625: * @param
626: * @return
627: * @see
628: */
629: function handleCharacterData(&$parser, &$data)
630: {
631: $parser->setTempValue(strval($data));
632: }
633: }
634:
635: class RpcDateTimeHandler extends XmlTagHandler
636: {
637:
638: /**
639: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
640: *
641: * @access
642: * @author
643: * @param
644: * @return
645: * @see
646: */
647: function getName()
648: {
649: return 'dateTime.iso8601';
650: }
651:
652: /**
653: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
654: *
655: * @access
656: * @author
657: * @param
658: * @return
659: * @see
660: */
661: function handleCharacterData(&$parser, &$data)
662: {
663: $matches = array();
664: if (!preg_match("/^([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})$/", $data, $matches)) {
665: $parser->setTempValue(time());
666: } else {
667: $parser->setTempValue(gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]));
668: }
669: }
670: }
671:
672: class RpcBase64Handler extends XmlTagHandler
673: {
674:
675: /**
676: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
677: *
678: * @access
679: * @author
680: * @param
681: * @return
682: * @see
683: */
684: function getName()
685: {
686: return 'base64';
687: }
688:
689: /**
690: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
691: *
692: * @access
693: * @author
694: * @param
695: * @return
696: * @see
697: */
698: function handleCharacterData(&$parser, &$data)
699: {
700: $parser->setTempValue(base64_decode($data));
701: }
702: }
703:
704: class RpcNameHandler extends XmlTagHandler
705: {
706:
707: /**
708: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
709: *
710: * @access
711: * @author
712: * @param
713: * @return
714: * @see
715: */
716: function getName()
717: {
718: return 'name';
719: }
720:
721: /**
722: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
723: *
724: * @access
725: * @author
726: * @param
727: * @return
728: * @see
729: */
730: function handleCharacterData(&$parser, &$data)
731: {
732: switch ($parser->getParentTag()) {
733: case 'member':
734: $parser->setTempName($data);
735: break;
736: default:
737: break;
738: }
739: }
740: }
741:
742:
743: class RpcValueHandler extends XmlTagHandler
744: {
745:
746: /**
747: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
748: *
749: * @access
750: * @author
751: * @param
752: * @return
753: * @see
754: */
755: function getName()
756: {
757: return 'value';
758: }
759:
760: /**
761: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
762: *
763: * @access
764: * @author
765: * @param
766: * @return
767: * @see
768: */
769: function handleCharacterData(&$parser, &$data)
770: {
771: switch ($parser->getParentTag()) {
772: case 'member':
773: $parser->setTempValue($data);
774: break;
775: case 'data':
776: case 'array':
777: $parser->setTempValue($data);
778: break;
779: default:
780: break;
781: }
782: }
783:
784: /**
785: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
786: *
787: * @access
788: * @author
789: * @param
790: * @return
791: * @see
792: */
793: function handleBeginElement(&$parser, &$attributes)
794: {
795: //$parser->resetTempValue();
796: }
797:
798: /**
799: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
800: *
801: * @access
802: * @author
803: * @param
804: * @return
805: * @see
806: */
807: function handleEndElement(&$parser)
808: {
809: switch ($parser->getCurrentTag()) {
810: case 'member':
811: $parser->setTempMember($parser->getTempName(), $parser->getTempValue());
812: break;
813: case 'array':
814: case 'data':
815: $parser->setTempArray($parser->getTempValue());
816: break;
817: default:
818: $parser->setParam($parser->getTempValue());
819: break;
820: }
821: $parser->resetTempValue();
822: }
823: }
824:
825: class RpcMemberHandler extends XmlTagHandler
826: {
827:
828: /**
829: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
830: *
831: * @access
832: * @author
833: * @param
834: * @return
835: * @see
836: */
837: function getName()
838: {
839: return 'member';
840: }
841:
842: /**
843: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
844: *
845: * @access
846: * @author
847: * @param
848: * @return
849: * @see
850: */
851: function handleBeginElement(&$parser, &$attributes)
852: {
853: $parser->setWorkingLevel();
854: $parser->resetTempMember();
855: }
856:
857: /**
858: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
859: *
860: * @access
861: * @author
862: * @param
863: * @return
864: * @see
865: */
866: function handleEndElement(&$parser)
867: {
868: $member =& $parser->getTempMember();
869: $parser->releaseWorkingLevel();
870: $parser->setTempStruct($member);
871: }
872: }
873:
874: class RpcArrayHandler extends XmlTagHandler
875: {
876:
877: /**
878: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
879: *
880: * @access
881: * @author
882: * @param
883: * @return
884: * @see
885: */
886: function getName()
887: {
888: return 'array';
889: }
890:
891: /**
892: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
893: *
894: * @access
895: * @author
896: * @param
897: * @return
898: * @see
899: */
900: function handleBeginElement(&$parser, &$attributes)
901: {
902: $parser->setWorkingLevel();
903: $parser->resetTempArray();
904: }
905:
906: /**
907: * This Method starts the parsing of the specified RDF File. The File can be a local or a remote File.
908: *
909: * @access
910: * @author
911: * @param
912: * @return
913: * @see
914: */
915: function handleEndElement(&$parser)
916: {
917: $parser->setTempValue($parser->getTempArray());
918: $parser->releaseWorkingLevel();
919: }
920: }
921:
922: class RpcStructHandler extends XmlTagHandler
923: {
924:
925: /**
926: *
927: *
928: * @access
929: * @author
930: * @param
931: * @return
932: * @see
933: */
934: function getName()
935: {
936: return 'struct';
937: }
938:
939: /**
940: *
941: *
942: * @access
943: * @author
944: * @param
945: * @return
946: * @see
947: */
948: function handleBeginElement(&$parser, &$attributes)
949: {
950: $parser->setWorkingLevel();
951: $parser->resetTempStruct();
952: }
953:
954: /**
955: *
956: *
957: * @access
958: * @author
959: * @param
960: * @return
961: * @see
962: */
963: function handleEndElement(&$parser)
964: {
965: $parser->setTempValue($parser->getTempStruct());
966: $parser->releaseWorkingLevel();
967: }
968: }
969: ?>