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