source: trunk/phpgwapi/inc/class.soap_parser.inc.php @ 2

Revision 2, 10.3 KB checked in by niltonneto, 17 years ago (diff)

Removida todas as tags usadas pelo CVS ($Id, $Source).
Primeira versão no CVS externo.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1<?php
2
3        class soap_parser
4        {
5                function soap_parser($xml='',$encoding='UTF-8')
6                {
7                        global $soapTypes;
8
9                        $this->soapTypes = $soapTypes;
10                        $this->xml = $xml;
11                        $this->xml_encoding = $encoding;
12                        $this->root_struct = "";
13                        // options: envelope,header,body,method
14                        // determines where in the message we are (envelope,header,body,method)
15                        $this->status = '';
16                        $this->position = 0;
17                        $this->pos_stat = 0;
18                        $this->depth = 0;
19                        $this->default_namespace = '';
20                        $this->namespaces = array();
21                        $this->message = array();
22                        $this->fault = false;
23                        $this->fault_code = '';
24                        $this->fault_str = '';
25                        $this->fault_detail = '';
26                        $this->eval_str = '';
27                        $this->depth_array = array();
28                        $this->debug_flag = True;
29                        $this->debug_str = '';
30                        $this->previous_element = '';
31
32                        $this->entities = array (
33                                '&' => '&amp;',
34                                '<' => '&lt;',
35                                '>' => '&gt;',
36                                "'" => '&apos;',
37                                '"' => '&quot;'
38                        );
39
40                        // Check whether content has been read.
41                        if(!empty($xml))
42                        {
43                                $this->debug('Entering soap_parser()');
44                                //$this->debug("DATA DUMP:\n\n$xml");
45                                // Create an XML parser.
46                                $this->parser = xml_parser_create($this->xml_encoding);
47                                // Set the options for parsing the XML data.
48                                //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
49                                xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
50                                // Set the object for the parser.
51                                xml_set_object($this->parser, &$this);
52                                // Set the element handlers for the parser.
53                                xml_set_element_handler($this->parser, 'start_element','end_element');
54                                xml_set_character_data_handler($this->parser,'character_data');
55                                xml_set_default_handler($this->parser, 'default_handler');
56
57                                // Parse the XML file.
58                                if(!xml_parse($this->parser,$xml,true))
59                                {
60                                        // Display an error message.
61                                        $this->debug(sprintf("XML error on line %d: %s",
62                                                xml_get_current_line_number($this->parser),
63                                                xml_error_string(xml_get_error_code($this->parser))));
64                                        $this->fault = true;
65                                }
66                                else
67                                {
68                                        // get final eval string
69                                        $this->eval_str = "\$response = ".trim($this->build_eval($this->root_struct)).";";
70                                }
71                                xml_parser_free($this->parser);
72                        }
73                        else
74                        {
75                                $this->debug("xml was empty, didn't parse!");
76                        }
77                }
78
79                // loop through msg, building eval_str
80                function build_eval($pos)
81                {
82                        $this->debug("inside build_eval() for $pos: ".$this->message[$pos]["name"]);
83                        $eval_str = $this->message[$pos]['eval_str'];
84                        // loop through children, building...
85                        if($this->message[$pos]['children'] != '')
86                        {
87                                $this->debug('children string = '.$this->message[$pos]['children']);
88                                $children = explode('|',$this->message[$pos]['children']);
89                                $this->debug('it has '.count($children).' children');
90                                @reset($children);
91                                while(list($c,$child_pos) = @each($children))
92                                /* foreach($children as $c => $child_pos) */
93                                {
94                                        //$this->debug("child pos $child_pos: ".$this->message[$child_pos]["name"]);
95                                        if($this->message[$child_pos]['eval_str'] != '')
96                                        {
97                                                $this->debug('entering build_eval() for '.$this->message[$child_pos]['name'].", array pos $c, pos: $child_pos");
98                                                $eval_str .= $this->build_eval($child_pos).', ';
99                                        }
100                                }
101                                $eval_str = substr($eval_str,0,strlen($eval_str)-2);
102                        }
103                        // add current node's eval_str
104                        $eval_str .= $this->message[$pos]['end_eval_str'];
105                        return $eval_str;
106                }
107
108                // start-element handler
109                function start_element($parser, $name, $attrs)
110                {
111                        // position in a total number of elements, starting from 0
112                        // update class level pos
113                        $pos = $this->position++;
114                        // and set mine
115                        $this->message[$pos]['pos'] = $pos;
116
117                        // parent/child/depth determinations
118
119                        // depth = how many levels removed from root?
120                        // set mine as current global depth and increment global depth value
121                        $this->message[$pos]['depth'] = $this->depth++;
122
123                        // else add self as child to whoever the current parent is
124                        if($pos != 0)
125                        {
126                                $this->message[$this->parent]['children'] .= "|$pos";
127                        }
128                        // set my parent
129                        $this->message[$pos]['parent'] = $this->parent;
130                        // set self as current value for this depth
131                        $this->depth_array[$this->depth] = $pos;
132                        // set self as current parent
133                        $this->parent = $pos;
134
135                        // set status
136                        if(ereg(":Envelope$",$name))
137                        {
138                                $this->status = 'envelope';
139                        }
140                        elseif(ereg(":Header$",$name))
141                        {
142                                $this->status = 'header';
143                        }
144                        elseif(ereg(":Body$",$name))
145                        {
146                                $this->status = 'body';
147                        // set method
148                        }
149                        elseif($this->status == 'body')
150                        {
151                                $this->status = 'method';
152                                if(ereg(':',$name))
153                                {
154                                        $this->root_struct_name = substr(strrchr($name,':'),1);
155                                }
156                                else
157                                {
158                                        $this->root_struct_name = $name;
159                                }
160                                $this->root_struct = $pos;
161                                $this->message[$pos]['type'] = 'struct';
162                        }
163                        // set my status
164                        $this->message[$pos]['status'] = $this->status;
165
166                        // set name
167                        $this->message[$pos]['name'] = htmlspecialchars($name);
168                        // set attrs
169                        $this->message[$pos]['attrs'] = $attrs;
170                        // get namespace
171                        if(ereg(":",$name))
172                        {
173                                $namespace = substr($name,0,strpos($name,':'));
174                                $this->message[$pos]['namespace'] = $namespace;
175                                $this->default_namespace = $namespace;
176                        }
177                        else
178                        {
179                                $this->message[$pos]['namespace'] = $this->default_namespace;
180                        }
181                        // loop through atts, logging ns and type declarations
182                        @reset($attrs);
183                        while (list($key,$value) = @each($attrs))
184                        /* foreach($attrs as $key => $value) */
185                        {
186                                // if ns declarations, add to class level array of valid namespaces
187                                if(ereg('xmlns:',$key))
188                                {
189                                        $namespaces[substr(strrchr($key,':'),1)] = $value;
190                                        if($name == $this->root_struct_name)
191                                        {
192                                                $this->methodNamespace = $value;
193                                        }
194                                }
195                                // if it's a type declaration, set type
196                                elseif($key == 'xsi:type')
197                                {
198                                        // then get attname and set $type
199                                        $type = substr(strrchr($value,':'),1);
200                                }
201                        }
202
203                        // set type if available
204                        if($type)
205                        {
206                                $this->message[$pos]['type'] = $type;
207                        }
208
209                        // debug
210                        //$this->debug("parsed $name start, eval = '".$this->message[$pos]["eval_str"]."'");
211                }
212
213                // end-element handler
214                function end_element($parser, $name)
215                {
216                        // position of current element is equal to the last value left in depth_array for my depth
217                        $pos = $this->depth_array[$this->depth];
218                        // bring depth down a notch
219                        $this->depth--;
220               
221                        // get type if not set already
222                        if($this->message[$pos]['type'] == '')
223                        {
224//                              if($this->message[$pos]['cdata'] == '' && $this->message[$pos]['children'] != '')
225                                if($this->message[$pos]['children'] != '')
226                                {
227                                        $this->message[$pos]['type'] = 'SOAPStruct';
228                                }
229                                else
230                                {
231                                        $this->message[$pos]['type'] = 'string';
232                                }
233                        }
234
235                        // set eval str start if it has a valid type and is inside the method
236                        if($pos >= $this->root_struct)
237                        {
238                                $this->message[$pos]['eval_str'] .= "\n CreateObject(\"phpgwapi.soapval\",\"".htmlspecialchars($name)."\", \"".$this->message[$pos]["type"]."\" ";
239                                $this->message[$pos]['end_eval_str'] = ')';
240                                $this->message[$pos]['inval'] = 'true';
241                                /*
242                                if($this->message[$pos]["name"] == $this->root_struct_name){
243                                        $this->message[$pos]["end_eval_str"] .= " ,\"$this->methodNamespace\"";
244                                }
245                                */
246                                if($this->message[$pos]['children'] != '')
247                                {
248                                        $this->message[$pos]['eval_str'] .= ', array( ';
249                                        $this->message[$pos]['end_eval_str'] .= ' )';
250                                }
251                        }
252
253                        // if i have no children and have cdata...then i must be a scalar value, so add my data to the eval_str
254                        if($this->status == 'method' && $this->message[$pos]['children'] == '')
255                        {
256                                // add cdata w/ no quotes if only int/float/dbl
257                                if($this->message[$pos]['type'] == 'string')
258                                {
259                                        $this->message[$pos]['eval_str'] .= ", \"".$this->message[$pos]['cdata']."\"";
260                                }
261                                elseif($this->message[$pos]['type'] == 'int' || $this->message[$pos]['type'] == 'float' || $this->message[$pos]['type'] == 'double')
262                                {
263                                        //$this->debug("adding cdata w/o quotes");
264                                        $this->message[$pos]['eval_str'] .= ', '.trim($this->message[$pos]['cdata']);
265                                }
266                                elseif(is_string($this->message[$pos]['cdata']))
267                                {
268                                        //$this->debug("adding cdata w/ quotes");
269                                        $this->message[$pos]['eval_str'] .= ", \"".$this->message[$pos]['cdata']."\"";
270                                }
271                        }
272                        // if in the process of making a soap_val, close the parentheses and move on...
273                        if($this->message[$pos]['inval'] == 'true')
274                        {
275                                $this->message[$pos]['inval'] == 'false';
276                        }
277                        // if tag we are currently closing is the method wrapper
278                        if($pos == $this->root_struct)
279                        {
280                                $this->status = 'body';
281                        }
282                        elseif(ereg(':Body',$name))
283                        {
284                                $this->status = 'header';
285                        }
286                        elseif(ereg(':Header',$name))
287                        {
288                                $this->status = 'envelope';
289                        }
290                        // set parent back to my parent
291                        $this->parent = $this->message[$pos]['parent'];
292                        $this->debug("parsed $name end, type '".$this->message[$pos]['type']."'eval_str = '".trim($this->message[$pos]['eval_str'])."' and children = ".$this->message[$pos]['children']);
293                }
294
295                // element content handler
296                function character_data($parser, $data)
297                {
298                        $pos = $this->depth_array[$this->depth];
299                        $this->message[$pos]['cdata'] .= $data;
300                        //$this->debug("parsed ".$this->message[$pos]["name"]." cdata, eval = '$this->eval_str'");
301                }
302
303                // default handler
304                function default_handler($parser, $data)
305                {
306                        //$this->debug("DEFAULT HANDLER: $data");
307                }
308
309                // function to get fault code
310                function fault()
311                {
312                        if($this->fault)
313                        {
314                                return true;
315                        }
316                        else
317                        {
318                                return false;
319                        }
320                }
321
322                // have this return a soap_val object
323                function get_response()
324                {
325                        $this->debug("eval()ing eval_str: $this->eval_str");
326                        @eval("$this->eval_str");
327                        if($response)
328                        {
329                                $this->debug("successfully eval'd msg");
330                                return $response;
331                        }
332                        else
333                        {
334                                $this->debug('ERROR: did not successfully eval the msg');
335                                $this->fault = true;
336                                return CreateObject('phpgwapi.soapval',
337                                        'Fault',
338                                        'struct',
339                                        array(
340                                                CreateObject('phpgwapi.soapval',
341                                                        'faultcode',
342                                                        'string',
343                                                        'SOAP-ENV:Server'
344                                                ),
345                                                CreateObject('phpgwapi.soapval',
346                                                        'faultstring',
347                                                        'string',
348                                                        "couldn't eval \"$this->eval_str\""
349                                                )
350                                        )
351                                );
352                        }
353                }
354
355                function debug($string)
356                {
357                        if($this->debug_flag)
358                        {
359                                $this->debug_str .= "$string\n";
360                        }
361                }
362
363                function decode_entities($text)
364                {
365                        @reset($this->entities);
366                        while(list($entity,$encoded) = @each($this->entities))
367                        /* foreach($this->entities as $entity => $encoded) */
368                        {
369                                $text = str_replace($encoded,$entity,$text);
370                        }
371                        return $text;
372                }
373        }
374?>
Note: See TracBrowser for help on using the repository browser.