<?php

class StackPiece{
  var $position;
  var $name;
  var $prev;
  var $datanode = null;

  function StackPiece($position, $name, $prev=null){
    $this->position = $position;
    $this->name = $name;
    $this->prev = $prev;
  }
}


class AppData{
  var $depth;
  var $sp;
  var $currMessage;
  var $currElement;

  function AppData($msg=null){
    $this->depth = 0;
    if(isset($msg)){
      $this->currMessage = &$msg;
    }else{
      $this->currMessage = new Message();
    }
    $this->sp = null;
    $this->currElement = null;
  }
}

class AuthentXMLParser{
  var $appData;
  var $parser;
  var $parserInited = false;
  var $dataPrefix;

  function AuthentXMLParser($msg=null){
    $this->initParser();
    if(isset($msg)){
      $this->appData = new AppData(&$msg);
    }else{
      $this->appData = new AppData();
    }
    $this->dataPrefix = $this->appData->currMessage->dataPrefix;
  }

  function initParser(){
    if(!$this->parserInited)
    {
      $this->parser = xml_parser_create();

      xml_set_object($this->parser, &$this);
      xml_set_element_handler($this->parser, "startElement", "endElement");
      xml_set_character_data_handler($this->parser, "charHandler");
      //register_shutdown_function("$this->free");
      xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
      $this->parserInited = true;
    }
  }
  
  function free() {
    xml_parser_free($this->parser);
    $this->parserInited = false;
  }

  function reset(){
    $this->free();
    $this->initParser();
  }

  function startElement($parser, $name, $attrs){
    $this->appData->depth++;
    $sp = new StackPiece($this->appData->depth, $name); 
    $sp->prev = &$this->appData->currElement;
    $this->appData->currElement = &$sp;

    if(strstr($name, $this->dataPrefix) == $name){
      $strKey = substr($name, strlen($this->dataPrefix));
      $dn = new DataNode();
      //reset ($attrs);
      //while (list ($key1, $val1) = each ($attrs)) {
      $dn->attributes = $attrs;
      //}
      if(isset($this->appData->currElement->prev->datanode)){
	$this->appData->currElement->prev->datanode->childNodes[$strKey] = &$dn;
      }else{
	$this->appData->currMessage->data[$strKey] = &$dn;
      }

      $this->appData->currElement->datanode = &$dn;//this->appData->currMessage->data[$strKey];
    }
    
    if( strcmp($name,"result") == 0 ||
      strcmp($name,"report") == 0 ||
      strcmp($name,"poll") == 0 ||
      strcmp($name,"request") == 0 )
    {
      $this->appData->currMessage->type = $name;
    }
  }

  function endElement($parser, $name){
    $this->appData->depth--;
    $this->appData->currElement = $this->appData->currElement->prev;
  }

  function charHandler($parser, $text){
    $texttest = trim($text);
    if( strcmp($texttest, "\n") == 0 || strcmp($texttest, "\r\n") == 0 || strcmp($texttest, "") == 0){ 
      return; 
    }
    
    if(strstr($this->appData->currElement->name, $this->dataPrefix) == $this->appData->currElement->name){
      $strKey = substr($this->appData->currElement->name, strlen($this->dataPrefix));
      $dn = &$this->appData->currElement->datanode;
      if(!isset($dn)){
	$dn = new DataNode();
	if(isset($this->appData->currElement->datanode)){
	  $this->appData->currElement->datanode->childNodes[$strKey] = &$dn;
	}else{
	  $this->appData->currMessage->data[$strKey] = &$dn;
	}
      }
      if(isset($dn)){
	$dn->text = $text;
      }
    }else{
      $vars = get_object_vars($this->appData->currMessage);
      if(array_key_exists($this->appData->currElement->name,$vars)){
	$evalstr = "\$msgPlace = &\$this->appData->currMessage->".$this->appData->currElement->name.";";
	eval($evalstr);
	$msgPlace = $text;
      }

    }
  }

  function parse($xml) {
    $val = xml_parse($this->parser, $xml);
    if( $val == TRUE){
      //echo "Parsed";
      return $this->appData->currMessage;
    }else{
      echo "Error in Parsing was ".xml_error_string(xml_get_error_code($this->parser))."<br>Happened on Line: ".xml_get_current_line_number($this->parser)." at Column ".xml_get_current_column_number($this->parser).".<br>";
      return null;
    }
  }
}

