1: <?php
  2:   3:   4:   5:   6:   7:   8:   9:  10: 
 11: 
 12:  13:  14:  15:  16:  17:  18:  19:  20: 
 21: 
 22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33: 
 34: class XoopsXmlRpcParser extends SaxParser
 35: {
 36: 
 37:      38:  39:  40: 
 41:     protected $_param;
 42: 
 43:      44:  45:  46: 
 47:     protected $_methodName;
 48: 
 49:      50:  51:  52: 
 53:     protected $_tempName;
 54: 
 55:      56:  57:  58: 
 59:     protected $_tempValue;
 60: 
 61:      62:  63:  64: 
 65:     protected $_tempMember;
 66: 
 67:      68:  69:  70: 
 71:     protected $_tempStruct;
 72: 
 73:      74:  75:  76: 
 77:     protected $_tempArray;
 78: 
 79:      80:  81:  82: 
 83:     protected $_workingLevel = array();
 84: 
 85: 
 86:      87:  88:  89:  90:  91: 
 92:     public function __construct(&$input)
 93:     {
 94:         parent::__construct($input);
 95:         $this->addTagHandler(new RpcMethodNameHandler());
 96:         $this->addTagHandler(new RpcIntHandler());
 97:         $this->addTagHandler(new RpcDoubleHandler());
 98:         $this->addTagHandler(new RpcBooleanHandler());
 99:         $this->addTagHandler(new RpcStringHandler());
100:         $this->addTagHandler(new RpcDateTimeHandler());
101:         $this->addTagHandler(new RpcBase64Handler());
102:         $this->addTagHandler(new RpcNameHandler());
103:         $this->addTagHandler(new RpcValueHandler());
104:         $this->addTagHandler(new RpcMemberHandler());
105:         $this->addTagHandler(new RpcStructHandler());
106:         $this->addTagHandler(new RpcArrayHandler());
107:     }
108: 
109:     110: 111: 112: 
113:     public function setTempName($name)
114:     {
115:         $this->_tempName[$this->getWorkingLevel()] = $name;
116:     }
117: 
118:     119: 120: 
121:     public function getTempName()
122:     {
123:         return $this->_tempName[$this->getWorkingLevel()];
124:     }
125: 
126:     127: 128: 129: 
130:     public function setTempValue($value)
131:     {
132:         if (is_array($value)) {
133:             settype($this->_tempValue, 'array');
134:             foreach ($value as $k => $v) {
135:                 $this->_tempValue[$k] = $v;
136:             }
137:         } elseif (is_string($value)) {
138:             if (isset($this->_tempValue)) {
139:                 if (is_string($this->_tempValue)) {
140:                     $this->_tempValue .= $value;
141:                 }
142:             } else {
143:                 $this->_tempValue = $value;
144:             }
145:         } else {
146:             $this->_tempValue = $value;
147:         }
148:     }
149: 
150:     151: 152: 
153:     public function getTempValue()
154:     {
155:         return $this->_tempValue;
156:     }
157: 
158:     159: 160: 
161:     public function resetTempValue()
162:     {
163:         $this->_tempValue = null;
164:     }
165: 
166:     167: 168: 169: 170: 
171:     public function setTempMember($name, $value)
172:     {
173:         $this->_tempMember[$this->getWorkingLevel()][$name] = $value;
174:     }
175: 
176:     177: 178: 
179:     public function getTempMember()
180:     {
181:         return $this->_tempMember[$this->getWorkingLevel()];
182:     }
183: 
184:     185: 186: 
187:     public function resetTempMember()
188:     {
189:         $this->_tempMember[$this->getWorkingLevel()] = array();
190:     }
191: 
192:     193: 194: 
195:     public function setWorkingLevel()
196:     {
197:         array_push($this->_workingLevel, $this->getCurrentLevel());
198:     }
199: 
200:     201: 202: 
203:     public function getWorkingLevel()
204:     {
205:         return (count($this->_workingLevel) > 0)
206:             ? $this->_workingLevel[count($this->_workingLevel) - 1]
207:             : null;
208:     }
209: 
210:     211: 212: 
213:     public function releaseWorkingLevel()
214:     {
215:         array_pop($this->_workingLevel);
216:     }
217: 
218:     219: 220: 221: 
222:     public function setTempStruct(array $member)
223:     {
224:         $key = key($member);
225:         $this->_tempStruct[$this->getWorkingLevel()][$key] = $member[$key];
226:     }
227: 
228:     229: 230: 
231:     public function getTempStruct()
232:     {
233:         return $this->_tempStruct[$this->getWorkingLevel()];
234:     }
235: 
236:     237: 238: 
239:     public function resetTempStruct()
240:     {
241:         $this->_tempStruct[$this->getWorkingLevel()] = array();
242:     }
243: 
244:     245: 246: 247: 
248:     public function setTempArray($value)
249:     {
250:         $this->_tempArray[$this->getWorkingLevel()][] = $value;
251:     }
252: 
253:     254: 255: 
256:     public function getTempArray()
257:     {
258:         return $this->_tempArray[$this->getWorkingLevel()];
259:     }
260: 
261:     262: 263: 
264:     public function resetTempArray()
265:     {
266:         $this->_tempArray[$this->getWorkingLevel()] = array();
267:     }
268: 
269:     270: 271: 272: 
273:     public function setMethodName($methodName)
274:     {
275:         $this->_methodName = $methodName;
276:     }
277: 
278:     279: 280: 
281:     public function getMethodName()
282:     {
283:         return $this->_methodName;
284:     }
285: 
286:     287: 288: 289: 
290:     public function setParam($value)
291:     {
292:         $this->_param[] = $value;
293:     }
294: 
295:     296: 297: 
298:     public function getParam()
299:     {
300:         return $this->_param;
301:     }
302: }
303: 
304: 
305: class RpcMethodNameHandler extends XmlTagHandler
306: {
307: 
308:     309: 310: 
311:     public function getName()
312:     {
313:         return 'methodName';
314:     }
315: 
316:     317: 318: 319: 320: 
321:     public function handleCharacterData(SaxParser $parser, &$data)
322:     {
323:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
324:         $parser->setMethodName($data);
325:     }
326: }
327: 
328: class RpcIntHandler extends XmlTagHandler
329: {
330: 
331:     332: 333: 
334:     public function getName()
335:     {
336:         return array('int', 'i4');
337:     }
338: 
339:     340: 341: 342: 343: 
344:     public function handleCharacterData(SaxParser $parser, &$data)
345:     {
346:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
347:         $parser->setTempValue((int)($data));
348:     }
349: }
350: 
351: class RpcDoubleHandler extends XmlTagHandler
352: {
353: 
354:     355: 356: 
357:     public function getName()
358:     {
359:         return 'double';
360:     }
361: 
362:     363: 364: 365: 366: 
367:     public function handleCharacterData(SaxParser $parser, &$data)
368:     {
369:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
370:         $data = (float)$data;
371:         $parser->setTempValue($data);
372:     }
373: }
374: 
375: class RpcBooleanHandler extends XmlTagHandler
376: {
377: 
378:     379: 380: 
381:     public function getName()
382:     {
383:         return 'boolean';
384:     }
385: 
386:     387: 388: 389: 390: 
391:     public function handleCharacterData(SaxParser $parser, &$data)
392:     {
393:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
394:         $data = (boolean)$data;
395:         $parser->setTempValue($data);
396:     }
397: }
398: 
399: class RpcStringHandler extends XmlTagHandler
400: {
401: 
402:     403: 404: 
405:     public function getName()
406:     {
407:         return 'string';
408:     }
409: 
410:     411: 412: 413: 414: 
415:     public function handleCharacterData(SaxParser $parser, &$data)
416:     {
417:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
418:         $parser->setTempValue((string)($data));
419:     }
420: }
421: 
422: class RpcDateTimeHandler extends XmlTagHandler
423: {
424: 
425:     426: 427: 
428:     public function getName()
429:     {
430:         return 'dateTime.iso8601';
431:     }
432: 
433:     434: 435: 436: 437: 
438:     public function handleCharacterData(SaxParser $parser, &$data)
439:     {
440:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
441:         $matches = array();
442:         if (!preg_match("/^([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})$/", $data, $matches)) {
443:             $parser->setTempValue(time());
444:         } else {
445:             $parser->setTempValue(gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]));
446:         }
447:     }
448: }
449: 
450: class RpcBase64Handler extends XmlTagHandler
451: {
452: 
453:     454: 455: 
456:     public function getName()
457:     {
458:         return 'base64';
459:     }
460: 
461:     462: 463: 464: 465: 
466:     public function handleCharacterData(SaxParser $parser, &$data)
467:     {
468:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
469:         $parser->setTempValue(base64_decode($data));
470:     }
471: }
472: 
473: class RpcNameHandler extends XmlTagHandler
474: {
475: 
476:     477: 478: 
479:     public function getName()
480:     {
481:         return 'name';
482:     }
483: 
484:     485: 486: 487: 488: 
489:     public function handleCharacterData(SaxParser $parser, &$data)
490:     {
491:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
492:         switch ($parser->getParentTag()) {
493:             case 'member':
494:                 $parser->setTempName($data);
495:                 break;
496:             default:
497:                 break;
498:         }
499:     }
500: }
501: 
502: 
503: class RpcValueHandler extends XmlTagHandler
504: {
505: 
506:     507: 508: 
509:     public function getName()
510:     {
511:         return 'value';
512:     }
513: 
514:     515: 516: 517: 518: 
519:     public function handleCharacterData(SaxParser $parser, &$data)
520:     {
521:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
522:         switch ($parser->getParentTag()) {
523:             case 'member':
524:                 $parser->setTempValue($data);
525:                 break;
526:             case 'data':
527:             case 'array':
528:                 $parser->setTempValue($data);
529:                 break;
530:             default:
531:                 break;
532:         }
533:     }
534: 
535:     536: 537: 538: 539: 
540:     public function handleBeginElement(SaxParser $parser, &$attributes)
541:     {
542:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
543:         
544:     }
545: 
546:     547: 548: 549: 
550:     public function handleEndElement(SaxParser $parser)
551:     {
552:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
553:         switch ($parser->getCurrentTag()) {
554:             case 'member':
555:                 $parser->setTempMember($parser->getTempName(), $parser->getTempValue());
556:                 break;
557:             case 'array':
558:             case 'data':
559:                 $parser->setTempArray($parser->getTempValue());
560:                 break;
561:             default:
562:                 $parser->setParam($parser->getTempValue());
563:                 break;
564:         }
565:         $parser->resetTempValue();
566:     }
567: }
568: 
569: class RpcMemberHandler extends XmlTagHandler
570: {
571: 
572:     573: 574: 
575:     public function getName()
576:     {
577:         return 'member';
578:     }
579: 
580:     581: 582: 583: 584: 
585:     public function handleBeginElement(SaxParser $parser, &$attributes)
586:     {
587:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
588:         $parser->setWorkingLevel();
589:         $parser->resetTempMember();
590:     }
591: 
592:     593: 594: 595: 
596:     public function handleEndElement(SaxParser $parser)
597:     {
598:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
599:         $member = $parser->getTempMember();
600:         $parser->releaseWorkingLevel();
601:         $parser->setTempStruct($member);
602:     }
603: }
604: 
605: class RpcArrayHandler extends XmlTagHandler
606: {
607: 
608:     609: 610: 
611:     public function getName()
612:     {
613:         return 'array';
614:     }
615: 
616:     617: 618: 619: 620: 
621:     public function handleBeginElement(SaxParser $parser, &$attributes)
622:     {
623:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
624:         $parser->setWorkingLevel();
625:         $parser->resetTempArray();
626:     }
627: 
628:     629: 630: 631: 
632:     public function handleEndElement(SaxParser $parser)
633:     {
634:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
635:         $parser->setTempValue($parser->getTempArray());
636:         $parser->releaseWorkingLevel();
637:     }
638: }
639: 
640: class RpcStructHandler extends XmlTagHandler
641: {
642: 
643:     644: 645: 
646:     public function getName()
647:     {
648:         return 'struct';
649:     }
650: 
651:     652: 653: 654: 655: 
656:     public function handleBeginElement(SaxParser $parser, &$attributes)
657:     {
658:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
659:         $parser->setWorkingLevel();
660:         $parser->resetTempStruct();
661:     }
662: 
663:     664: 665: 666: 
667:     public function handleEndElement(SaxParser $parser)
668:     {
669:         if (!is_a($parser,'XoopsXmlRpcParser')) return;
670:         $parser->setTempValue($parser->getTempStruct());
671:         $parser->releaseWorkingLevel();
672:     }
673: }
674: