/phpgwapi/inc/class.soap_parser.inc.php
PHP | 383 lines | 295 code | 22 blank | 66 comment | 43 complexity | 7a2db3ca8415358daaec5f2b61376671 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-2-Clause, BSD-3-Clause, AGPL-3.0
- <?php
- /***************************************************************************
- * Expresso Livre *
- * http://www.expressolivre.org *
- * -------------------------------------------- *
- * This program is free software; you can redistribute it and/or modify it *
- * under the terms of the GNU General Public License as published by the *
- * Free Software Foundation; either version 2 of the License, or (at your *
- * option) any later version. *
- \**************************************************************************/
-
- class soap_parser
- {
- function soap_parser($xml='',$encoding='UTF-8')
- {
- global $soapTypes;
- $this->soapTypes = $soapTypes;
- $this->xml = $xml;
- $this->xml_encoding = $encoding;
- $this->root_struct = "";
- // options: envelope,header,body,method
- // determines where in the message we are (envelope,header,body,method)
- $this->status = '';
- $this->position = 0;
- $this->pos_stat = 0;
- $this->depth = 0;
- $this->default_namespace = '';
- $this->namespaces = array();
- $this->message = array();
- $this->fault = false;
- $this->fault_code = '';
- $this->fault_str = '';
- $this->fault_detail = '';
- $this->eval_str = '';
- $this->depth_array = array();
- $this->debug_flag = True;
- $this->debug_str = '';
- $this->previous_element = '';
- $this->entities = array (
- '&' => '&',
- '<' => '<',
- '>' => '>',
- "'" => ''',
- '"' => '"'
- );
- // Check whether content has been read.
- if(!empty($xml))
- {
- $this->debug('Entering soap_parser()');
- //$this->debug("DATA DUMP:\n\n$xml");
- // Create an XML parser.
- $this->parser = xml_parser_create($this->xml_encoding);
- // Set the options for parsing the XML data.
- //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
- xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
- // Set the object for the parser.
- xml_set_object($this->parser, &$this);
- // Set the element handlers for the parser.
- xml_set_element_handler($this->parser, 'start_element','end_element');
- xml_set_character_data_handler($this->parser,'character_data');
- xml_set_default_handler($this->parser, 'default_handler');
- // Parse the XML file.
- if(!xml_parse($this->parser,$xml,true))
- {
- // Display an error message.
- $this->debug(sprintf("XML error on line %d: %s",
- xml_get_current_line_number($this->parser),
- xml_error_string(xml_get_error_code($this->parser))));
- $this->fault = true;
- }
- else
- {
- // get final eval string
- $this->eval_str = "\$response = ".trim($this->build_eval($this->root_struct)).";";
- }
- xml_parser_free($this->parser);
- }
- else
- {
- $this->debug("xml was empty, didn't parse!");
- }
- }
- // loop through msg, building eval_str
- function build_eval($pos)
- {
- $this->debug("inside build_eval() for $pos: ".$this->message[$pos]["name"]);
- $eval_str = $this->message[$pos]['eval_str'];
- // loop through children, building...
- if($this->message[$pos]['children'] != '')
- {
- $this->debug('children string = '.$this->message[$pos]['children']);
- $children = explode('|',$this->message[$pos]['children']);
- $this->debug('it has '.count($children).' children');
- @reset($children);
- while(list($c,$child_pos) = @each($children))
- /* foreach($children as $c => $child_pos) */
- {
- //$this->debug("child pos $child_pos: ".$this->message[$child_pos]["name"]);
- if($this->message[$child_pos]['eval_str'] != '')
- {
- $this->debug('entering build_eval() for '.$this->message[$child_pos]['name'].", array pos $c, pos: $child_pos");
- $eval_str .= $this->build_eval($child_pos).', ';
- }
- }
- $eval_str = substr($eval_str,0,strlen($eval_str)-2);
- }
- // add current node's eval_str
- $eval_str .= $this->message[$pos]['end_eval_str'];
- return $eval_str;
- }
- // start-element handler
- function start_element($parser, $name, $attrs)
- {
- // position in a total number of elements, starting from 0
- // update class level pos
- $pos = $this->position++;
- // and set mine
- $this->message[$pos]['pos'] = $pos;
- // parent/child/depth determinations
- // depth = how many levels removed from root?
- // set mine as current global depth and increment global depth value
- $this->message[$pos]['depth'] = $this->depth++;
- // else add self as child to whoever the current parent is
- if($pos != 0)
- {
- $this->message[$this->parent]['children'] .= "|$pos";
- }
- // set my parent
- $this->message[$pos]['parent'] = $this->parent;
- // set self as current value for this depth
- $this->depth_array[$this->depth] = $pos;
- // set self as current parent
- $this->parent = $pos;
- // set status
- if(preg_match('/:Envelope$/',$name))
- {
- $this->status = 'envelope';
- }
- elseif(preg_match('/:Header$/',$name))
- {
- $this->status = 'header';
- }
- elseif(preg_match('/:Body$/',$name))
- {
- $this->status = 'body';
- // set method
- }
- elseif($this->status == 'body')
- {
- $this->status = 'method';
- if(preg_match('/:/',$name))
- {
- $this->root_struct_name = substr(strrchr($name,':'),1);
- }
- else
- {
- $this->root_struct_name = $name;
- }
- $this->root_struct = $pos;
- $this->message[$pos]['type'] = 'struct';
- }
- // set my status
- $this->message[$pos]['status'] = $this->status;
- // set name
- $this->message[$pos]['name'] = htmlspecialchars($name);
- // set attrs
- $this->message[$pos]['attrs'] = $attrs;
- // get namespace
- if(preg_match('/:/',$name))
- {
- $namespace = substr($name,0,strpos($name,':'));
- $this->message[$pos]['namespace'] = $namespace;
- $this->default_namespace = $namespace;
- }
- else
- {
- $this->message[$pos]['namespace'] = $this->default_namespace;
- }
- // loop through atts, logging ns and type declarations
- @reset($attrs);
- while (list($key,$value) = @each($attrs))
- /* foreach($attrs as $key => $value) */
- {
- // if ns declarations, add to class level array of valid namespaces
- if(preg_match('/xmlns:/',$key))
- {
- $namespaces[substr(strrchr($key,':'),1)] = $value;
- if($name == $this->root_struct_name)
- {
- $this->methodNamespace = $value;
- }
- }
- // if it's a type declaration, set type
- elseif($key == 'xsi:type')
- {
- // then get attname and set $type
- $type = substr(strrchr($value,':'),1);
- }
- }
- // set type if available
- if($type)
- {
- $this->message[$pos]['type'] = $type;
- }
- // debug
- //$this->debug("parsed $name start, eval = '".$this->message[$pos]["eval_str"]."'");
- }
- // end-element handler
- function end_element($parser, $name)
- {
- // position of current element is equal to the last value left in depth_array for my depth
- $pos = $this->depth_array[$this->depth];
- // bring depth down a notch
- $this->depth--;
-
- // get type if not set already
- if($this->message[$pos]['type'] == '')
- {
- // if($this->message[$pos]['cdata'] == '' && $this->message[$pos]['children'] != '')
- if($this->message[$pos]['children'] != '')
- {
- $this->message[$pos]['type'] = 'SOAPStruct';
- }
- else
- {
- $this->message[$pos]['type'] = 'string';
- }
- }
- // set eval str start if it has a valid type and is inside the method
- if($pos >= $this->root_struct)
- {
- $this->message[$pos]['eval_str'] .= "\n CreateObject(\"phpgwapi.soapval\",\"".htmlspecialchars($name)."\", \"".$this->message[$pos]["type"]."\" ";
- $this->message[$pos]['end_eval_str'] = ')';
- $this->message[$pos]['inval'] = 'true';
- /*
- if($this->message[$pos]["name"] == $this->root_struct_name){
- $this->message[$pos]["end_eval_str"] .= " ,\"$this->methodNamespace\"";
- }
- */
- if($this->message[$pos]['children'] != '')
- {
- $this->message[$pos]['eval_str'] .= ', array( ';
- $this->message[$pos]['end_eval_str'] .= ' )';
- }
- }
- // if i have no children and have cdata...then i must be a scalar value, so add my data to the eval_str
- if($this->status == 'method' && $this->message[$pos]['children'] == '')
- {
- // add cdata w/ no quotes if only int/float/dbl
- if($this->message[$pos]['type'] == 'string')
- {
- $this->message[$pos]['eval_str'] .= ", \"".$this->message[$pos]['cdata']."\"";
- }
- elseif($this->message[$pos]['type'] == 'int' || $this->message[$pos]['type'] == 'float' || $this->message[$pos]['type'] == 'double')
- {
- //$this->debug("adding cdata w/o quotes");
- $this->message[$pos]['eval_str'] .= ', '.trim($this->message[$pos]['cdata']);
- }
- elseif(is_string($this->message[$pos]['cdata']))
- {
- //$this->debug("adding cdata w/ quotes");
- $this->message[$pos]['eval_str'] .= ", \"".$this->message[$pos]['cdata']."\"";
- }
- }
- // if in the process of making a soap_val, close the parentheses and move on...
- if($this->message[$pos]['inval'] == 'true')
- {
- $this->message[$pos]['inval'] == 'false';
- }
- // if tag we are currently closing is the method wrapper
- if($pos == $this->root_struct)
- {
- $this->status = 'body';
- }
- elseif(preg_match('/:Body/',$name))
- {
- $this->status = 'header';
- }
- elseif(preg_match('/:Header/',$name))
- {
- $this->status = 'envelope';
- }
- // set parent back to my parent
- $this->parent = $this->message[$pos]['parent'];
- $this->debug("parsed $name end, type '".$this->message[$pos]['type']."'eval_str = '".trim($this->message[$pos]['eval_str'])."' and children = ".$this->message[$pos]['children']);
- }
- // element content handler
- function character_data($parser, $data)
- {
- $pos = $this->depth_array[$this->depth];
- $this->message[$pos]['cdata'] .= $data;
- //$this->debug("parsed ".$this->message[$pos]["name"]." cdata, eval = '$this->eval_str'");
- }
- // default handler
- function default_handler($parser, $data)
- {
- //$this->debug("DEFAULT HANDLER: $data");
- }
- // function to get fault code
- function fault()
- {
- if($this->fault)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- // have this return a soap_val object
- function get_response()
- {
- $this->debug("eval()ing eval_str: $this->eval_str");
- @eval("$this->eval_str");
- if($response)
- {
- $this->debug("successfully eval'd msg");
- return $response;
- }
- else
- {
- $this->debug('ERROR: did not successfully eval the msg');
- $this->fault = true;
- return CreateObject('phpgwapi.soapval',
- 'Fault',
- 'struct',
- array(
- CreateObject('phpgwapi.soapval',
- 'faultcode',
- 'string',
- 'SOAP-ENV:Server'
- ),
- CreateObject('phpgwapi.soapval',
- 'faultstring',
- 'string',
- "couldn't eval \"$this->eval_str\""
- )
- )
- );
- }
- }
- function debug($string)
- {
- if($this->debug_flag)
- {
- $this->debug_str .= "$string\n";
- }
- }
- function decode_entities($text)
- {
- @reset($this->entities);
- while(list($entity,$encoded) = @each($this->entities))
- /* foreach($this->entities as $entity => $encoded) */
- {
- $text = str_replace($encoded,$entity,$text);
- }
- return $text;
- }
- }
- ?>