<?php

	include_once( PLOG_CLASS_PATH."class/object/object.class.php" );
	include_once( PLOG_CLASS_PATH."class/net/http/httpvars.class.php" );
	include_once( PLOG_CLASS_PATH."plugins/atom/class/xml/lib.xml.inc.php" );
	include_once( PLOG_CLASS_PATH."plugins/atom/class/xml/atom/atomFunc.php" );
	include_once( PLOG_CLASS_PATH."plugins/atom/class/xml/atom/atomDom.php" );
	include_once( PLOG_CLASS_PATH."plugins/atom/class/xml/atom/atomClasses.php" );
	include_once( PLOG_CLASS_PATH."plugins/atom/class/xml/atom/plogatomauthentication.class.php" );

	/**
	 * represents an Atom request
	 */
	class AtomRequest extends Object
	{
	
		var $_type;
		var $_query;
		var $_dom;
		var $_payload;
		var $_service;
		var $_atomDocument;
		var $_authenticated;
		var $_userName;
		var $_blogId;
		var $_articleId;
	
		function AtomRequest()
		{
			$this->Object();
			
			// assign some inocuous default values to our attributes
			$this->_requestPayload = "";
			$this->_dom = null;
			$this->_query = "";
			$this->_type = 0;
			$this->_service = null;
			$this->_atomDocument = null;
			$this->_userName = "";
			$this->_blogId = ATOM_NO_BLOG;
			$this->_articleId = ATOM_NO_ARTICLE;

			$this->_authenticated = $this->authenticateRequest();
			
			$this->_initialiseRestRequest();
			$this->parseRequest();
		}

		/**
		 * authenticates the request
		 */
		function authenticateRequest()
		{
			// first of all, authenticate the user via WSSE
			$auth = new PlogAtomAuthentication();
			$authenticated = $auth->authenticate();
			if( $authenticated )
				$this->_userName = $auth->getUsernameFromAuthentication();

			return $authenticated;
		}

		/**
		 * whether this request was correctly authenticated or not
		 *
		 * @return true if authenticated or false otherwise
		 */
		function isAuthenticated()
		{
			return $this->_authenticated;
		}
		
		/**
		 * @private
		 * Returns the right constant based on the REQUEST_METHOD string
		 *
		 * @return An integer
		 */
		function _getRequestTypeId( $methodString )
		{
			switch( $methodString ) {
				case "POST": $methodId = ATOM_REQUEST_POST; break;
				case "GET": $methodId = ATOM_REQUEST_GET; break;
				case "PUT": $methodId = ATOM_REQUEST_PUT; break;
				case "DELETE": $methodId = ATOM_REQUEST_DELETE; break;
			}
			
			return $methodId;
		}
		
		/*
		 * Doing a generic rest initialisation. On POST and PUT methods
		 * there will be an XML payload that needs to be captured.
		 *
		 * @private
		 */
		function _initialiseRestRequest() 
		{
		
			// get certain server-wide variables that we need
			$get =& HttpVars::getGet();
			$server =& HttpVars::getServer();

			$this->_query   = $get;
			$this->_type    = $this->_getRequestTypeId( $server["REQUEST_METHOD"] );
			if ($this->_type == ATOM_REQUEST_POST || $this->_type == ATOM_REQUEST_PUT ) {
				AtomLogger::Log( "AtomRequest: handling POST/PUT request" );
				$xmlstring = file_get_contents("php://input");
				AtomLogger::Log( "Contents of php://input:" );
				if (!empty($xmlstring)) {
					// ecto for windows likes to send the UTF-8 BOM in the first three bytes
					// of the message, but we don't like it so let's remove it
					if(substr($xmlstring, 0, 5) != "<?xml" ) {
						$xmlstring = substr($xmlstring,3,strlen($xmlstring));
					}
					// Create XML DOM from input
					$this->_dom = new XML();
					$this->_dom->parseXML($xmlstring);
				}
				$this->_payload = $xmlstring;
				AtomLogger::Log( $this->_payload );

				// now, extract the information from the Atom document
				$this->parseAtomDocument();
			}
		}		

		/**
		 * @private
		 * Receives a [valid] Atom document and using the DOM model, extracts the information
		 * we need. Based on code from isoTope
		 */
		function parseAtomDocument()
		{
			AtomLogger::Log( "Parsing the Atom document..." );
			$this->_atomDocument = createAtomEntry( $this->_dom );
			
			return true;		
		}
		
		/**
		 * returns true if there was any error with the request, most likely parsing the xml code
		 *
		 * @return True if there was an error or false otherwise
		 */
		function isAtomError()
		{
		    // we only expect content when using POST or PUT requests so otherwise, everything's fine  
		    if( $this->getType() == ATOM_REQUEST_POST || $this->getType() == ATOM_REQUEST_PUT ) {
		          if( $this->_atomDocument != null ) {
		              $result = $this->_atomDocument->isError;
		          }
		          else {
		              $result = true;
		          }
		    }
		    else
		          $result = false;
		            
            return $result;
		}
		
		/**
		 * returns the atom error message
		 *
		 * @return the error message generated
		 */
        function getAtomErrorMessage()
        {
            if( $this->_atomDocument != null )
                $error = $this->_atomDocument->errorMessage;
            else
                $error = "";
                
            return $error;
        }

		/**
		 * Returns the parsed-atom document
		 *
		 */
		function getAtomDocument()
		{
			return $this->_atomDocument;
		}
		
		/**
		 * whether it was GET, PUT, DELETE or POST
		 *
		 * @return Returns one of the following values: <ul>
		 * <li>ATOM_REQUEST_GET</li>
		 * <li>ATOM_REQUEST_POST</li>
		 * <li>ATOM_REQUEST_PUT</li>
		 * <li>ATOM_REQUEST_DELETE</li>		 		 		 
		 * </ul>
		 */
		function getType()
		{
			return $this->_type;
		}
		
		function getMimeType()
		{
		
		}
		
		function getRequestUri()
		{
		
		}
		
		/**
		 * returns the part in the url corresponding to the service type
		 *
		 * @return Returns a string indicating the service type, or null if there was
		 * no service defined
		 */		
		function getService()
		{
			return $this->_service;
		}
		
		/**
		 * parse the incoming request, using the PATH_INFO variable from php
		 *
		 * @return nothing
		 */
		function parseRequest()
		{
			// retrieve the PATH_INFO 
			$server = HttpVars::getServer();
			$path = $server["PATH_INFO"];
			
			// do some clean up here before we split the parts
			if( $path[0] == "/" ) 
			     $path = substr( $path, 1, strlen($path));
			
			// split the path in its parts
			$parts = explode( "/", $path );
			
			
			// the service is always the first part...
			$this->_service = $parts[0];
			// the blog id is the second
			$this->_blogId = $parts[1];
			// and the post id, if any, is the third
			$this->_articleId = $parts[2];
			
			AtomLogger::Log( "-- Incoming request: $path" );
			AtomLogger::Log( "   Service: ".$this->_service );
			AtomLogger::Log( "   Blog id: ".$this->_blogId );
			AtomLogger::Log( "   Article id: ".$this->_articleId );
			
			return true;
		}
		
		/**
		 * In case of PUT and POST requests, there will be an xml payload that
		 * we might need to inspect for debugging purposes, perhaps, so let's keep it...
		 *
		 * @return the XML payload that came with a PUT or POST request
		 */
		function getRequestPayload()
		{
			return $this->_payload;
		}

		/**
		 * returns the blog identifier to which this request is referring
		 *
		 * @return the blog identifier
		 */		
		function getBlogId()
		{
			return $this->_blogId;
		}

		/**
		 * returns the post identifier to which this request is referring
		 *
		 * @return the post identifier
		 */
		function getArticleId()
		{
			return $this->_articleId;
		}

		/**
		 * gets the username that came from the authentication layer
		 *
		 * @return A string with the username, if any
		 */
		function getUsernameFromAuthentication()
		{
			return $this->_userName;
		}
	}
?>