2001-07-16 08:05:33 +02:00
< ? php
class soap_parser
{
2001-07-30 05:40:08 +02:00
function soap_parser ( $xml = '' , $encoding = 'UTF-8' )
2001-07-16 08:05:33 +02:00
{
global $soapTypes ;
$this -> soapTypes = $soapTypes ;
$this -> xml = $xml ;
2001-07-30 05:40:08 +02:00
$this -> xml_encoding = $encoding ;
2001-07-16 08:05:33 +02:00
$this -> root_struct = " " ;
// options: envelope,header,body,method
2001-07-30 05:40:08 +02:00
// determines where in the message we are (envelope,header,body,method)
2001-07-16 08:05:33 +02:00
$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 ();
2001-07-28 22:24:32 +02:00
$this -> debug_flag = True ;
2001-07-16 08:05:33 +02:00
$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 " );
2001-08-02 10:59:08 +02:00
@ reset ( $children );
while ( list ( $c , $child_pos ) = @ each ( $children ))
/* foreach($children as $c => $child_pos) */
2001-07-16 08:05:33 +02:00
{
//$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 ( ereg ( " :Envelope $ " , $name ))
{
$this -> status = " envelope " ;
}
elseif ( ereg ( " :Header $ " , $name ))
{
$this -> status = " header " ;
}
elseif ( ereg ( " :Body $ " , $name ))
{
$this -> status = " body " ;
// set method
}
elseif ( $this -> status == " body " )
{
$this -> status = " method " ;
if ( ereg ( " : " , $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 ( ereg ( " : " , $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
2001-08-02 10:59:08 +02:00
@ reset ( $attrs );
while ( list ( $key , $value ) = @ each ( $attrs ))
/* foreach($attrs as $key => $value) */
2001-07-16 08:05:33 +02:00
{
// if ns declarations, add to class level array of valid namespaces
if ( ereg ( " 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 " ] == " " )
{
2001-07-30 05:40:08 +02:00
// if($this->message[$pos]["cdata"] == "" && $this->message[$pos]["children"] != "")
if ( $this -> message [ $pos ][ " children " ] != " " )
2001-07-16 08:05:33 +02:00
{
$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 ( ereg ( " :Body " , $name ))
{
$this -> status = " header " ;
}
elseif ( ereg ( " :Header " , $name ))
{
$this -> status = " envelope " ;
}
// set parent back to my parent
$this -> parent = $this -> message [ $pos ][ " parent " ];
2001-07-30 05:40:08 +02:00
$this -> debug ( " parsed $name end, type ' " . $this -> message [ $pos ][ " type " ] . " 'eval_str = ' " . trim ( $this -> message [ $pos ][ " eval_str " ]) . " ' and children = " . $this -> message [ $pos ][ " children " ]);
2001-07-16 08:05:33 +02:00
}
// 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 )
{
2001-08-02 10:59:08 +02:00
@ reset ( $this -> entities );
while ( list ( $entity , $encoded ) = @ each ( $this -> entities ))
/* foreach($this->entities as $entity => $encoded) */
2001-07-16 08:05:33 +02:00
{
$text = str_replace ( $encoded , $entity , $text );
}
return $text ;
}
}
?>