diff --git a/core/amf/app/Actions.php b/core/amf/app/Actions.php new file mode 100755 index 0000000..dc92526 --- /dev/null +++ b/core/amf/app/Actions.php @@ -0,0 +1,240 @@ +targetURI; + + if (strpos($target, "http://") === false && strpos($target, "https://") === false) { // check for a http link which means web service + $lpos = strrpos($target, "."); + if ($lpos === false) { + //Check to see if this is in fact a RemotingMessage + $body = $amfbody->getValue(); + $handled = false; + + $messageType = $body[0]->_explicitType; + if($messageType == 'flex.messaging.messages.RemotingMessage') + { + $handled = true; + + //Fix for AMF0 mixed array bug in Flex 2 + if(isset($body[0]->body['length'])) + { + unset($body[0]->body['length']); + } + + $amfbody->setValue($body[0]->body); + $amfbody->setSpecialHandling("RemotingMessage"); + $amfbody->setMetadata("clientId", $body[0]->clientId); + $amfbody->setMetadata("messageId", $body[0]->messageId); + + $GLOBALS['amfphp']['lastMessageId'] = $body[0]->messageId; + + $methodname = $body[0]->operation; + $classAndPackage = $body[0]->source; + $lpos = strrpos($classAndPackage, "."); + if($lpos !== FALSE) + { + $classname = substr($classAndPackage, $lpos + 1); + } + else + { + $classname = $classAndPackage; + } + $uriclasspath = str_replace('.','/',$classAndPackage) . '.php'; + $classpath = $baseClassPath . $uriclasspath; + } + elseif($messageType == "flex.messaging.messages.CommandMessage") + { + if($body[0]->operation == 5) + { + $handled = true; + $amfbody->setSpecialHandling("Ping"); + $amfbody->setMetadata("clientId", $body[0]->clientId); + $amfbody->setMetadata("messageId", $body[0]->messageId); + $amfbody->noExec = true; + } + } + + if(!$handled) + { + $uriclasspath = "amfphp/Amf3Broker.php"; + $classpath = $baseClassPath . "amfphp/Amf3Broker.php"; + $classname = "Amf3Broker"; + $methodname = "handleMessage"; + } + } else { + $methodname = substr($target, $lpos + 1); + $trunced = substr($target, 0, $lpos); + $lpos = strrpos($trunced, "."); + if ($lpos === false) { + $classname = $trunced; + if ($classname == "PageAbleResult" && $methodname == 'getRecords') { + $val = $amfbody->getValue(); + $id = $val[0]; + $keys = explode("=", $id); + $currset = intval($keys[1]); + + $set = $_SESSION['amfphp_recordsets'][$currset]; + + $uriclasspath = $set['class']; + $classpath = $baseClassPath . $set['class']; + $methodname = $set['method']; + + $classname = substr(strrchr('/' . $set['class'], '/'), 1, -4); + + //Now set args for body + $amfbody->setValue(array_merge($set['args'], array($val[1], $val[2]))); + + //Tell amfbody that this is a dynamic paged resultset + $amfbody->setSpecialHandling('pageFetch'); + } + else if($classname == "PageAbleResult" && $methodname == 'release') + { + $amfbody->setSpecialHandling('pageRelease'); + $amfbody->noExec = true; + } + else { + $uriclasspath = $trunced . ".php"; + $classpath = $baseClassPath . $trunced . ".php"; + } + } else { + $classname = substr($trunced, $lpos + 1); + $classpath = $baseClassPath . str_replace(".", "/", $trunced) . ".php"; // removed to strip the basecp out of the equation here + $uriclasspath = str_replace(".", "/", $trunced) . ".php"; // removed to strip the basecp out of the equation here + } + } + } else { // This is a web service and is unsupported + trigger_error("Web services are not supported in this release", E_USER_ERROR); + } + + $amfbody->classPath = $classpath; + $amfbody->uriClassPath = $uriclasspath; + $amfbody->className = $classname; + $amfbody->methodName = $methodname; + + return true; +} + +/** + * ExecutionAction executes the required methods + */ +function executionAction (&$amfbody) +{ + $specialHandling = $amfbody->getSpecialHandling(); + + if (!$amfbody->isSpecialHandling() || $amfbody->isSpecialHandling(array('describeService', 'pageFetch', 'RemotingMessage'))) + { + $construct = &$amfbody->getClassConstruct(); + $method = $amfbody->methodName; + $args = $amfbody->getValue(); + + if($specialHandling == 'describeService') + { + include_once(AMFPHP_BASE . "util/DescribeService.php"); + $ds = new DescribeService(); + $results = $ds->describe($construct, $amfbody->className); + } + else if($specialHandling == 'pageFetch') + { + $args[count($args) - 2] = $args[count($args) - 2] - 1; + + $dataset = Executive::doMethodCall($amfbody, $construct, $method, $args); + $results = array("cursor" => $args[count($args) - 2] + 1, + "data" => $dataset); + $amfbody->setMetadata('type', '__DYNAMIC_PAGE__'); + } + else + { + /* + if(isset($construct->methodTable[$method]['pagesize'])) + { + //Check if counting method was overriden + if(isset($construct->methodTable[$method]['countMethod'])) + { + $counter = $construct->methodTable[$method]['countMethod']; + } + else + { + $counter = $method . '_count'; + } + + $dataset = Executive::doMethodCall($amfbody, $construct, $method, $args); // do the magic + $count = Executive::doMethodCall($amfbody, $construct, $counter, $args); + + //Include the wrapper + $results = array('class' => $amfbody->uriClassPath, + 'method' => $amfbody->methodName, + 'count' => $count, + "args" => $args, + "data" => $dataset); + $amfbody->setMetadata('type', '__DYNAMIC_PAGEABLE_RESULTSET__'); + $amfbody->setMetadata('pagesize', $construct->methodTable[$method]['pagesize']); + */ + //} + //else + //{ + //The usual + $time = microtime_float(); + $results = Executive::doMethodCall($amfbody, $construct, $method, $args); // do the magic + global $amfphp; + $amfphp['callTime'] += microtime_float() - $time; + //} + } + + if($results !== '__amfphp_error') + { + if($specialHandling == 'RemotingMessage') + { + + $wrapper = new AcknowledgeMessage($amfbody->getMetadata("messageId"), + $amfbody->getMetadata("clientId")); + $wrapper->body = $results; + $amfbody->setResults($wrapper); + } + else + { + $amfbody->setResults($results); + } + + $amfbody->responseURI = $amfbody->responseIndex . "/onResult"; + } + return false; + } + elseif($specialHandling == 'Ping') + { + $wrapper = new AcknowledgeMessage($amfbody->getMetadata("messageId"), + $amfbody->getMetadata("clientId")); + $amfbody->setResults($wrapper); + $amfbody->responseURI = $amfbody->responseIndex . "/onResult"; + } + else if($specialHandling == 'pageRelease') + { + //Ignore PageAbleResult.release + $amfbody->setResults(true); + $amfbody->setMetaData('type', 'boolean'); + $amfbody->responseURI = $amfbody->responseIndex . "/onResult"; + return false; + } + return true; +} +?> \ No newline at end of file diff --git a/core/amf/app/Filters.php b/core/amf/app/Filters.php new file mode 100755 index 0000000..9f58923 --- /dev/null +++ b/core/amf/app/Filters.php @@ -0,0 +1,210 @@ +rawData); // deserialize the data + } + else + { + include_once(AMFPHP_BASE . "amf/io/AMFDeserializer.php"); + include_once(AMFPHP_BASE . "amf/io/AMFSerializer.php"); + $deserializer = new AMFDeserializer($amf->rawData); // deserialize the data + } + + $deserializer->deserialize($amf); // run the deserializer + + //Add some headers + $headers = $amf->_headerTable; + if(isset($headers) && is_array($headers)) + { + foreach($headers as $key => $value) + { + Headers::setHeader($value->name, $value->value); + } + } + + //Set as a describe service + $describeHeader = $amf->getHeader(AMFPHP_SERVICE_BROWSER_HEADER); + + if ($describeHeader !== false) { + if($GLOBALS['amfphp']['disableDescribeService']) + { + //Exit + trigger_error("Service description not allowed", E_USER_ERROR); + die(); + } + $bodyCopy = &$amf->getBodyAt(0); + $bodyCopy->setSpecialHandling('describeService'); + $bodyCopy->noExec = true; + } +} + +/** + * AuthenticationFilter looks at the credential headers, starts sessions, etc. + */ +function authenticationFilter (&$amf) { + $authHeader = $amf->getHeader(AMFPHP_CREDENTIALS_HEADER); + + if ($authHeader !== false && $authHeader->value !== AMFPHP_CLEARED_CREDENTIALS) { + //In PHP5, objects are always pass-by-ref, hence this branch + if(AMFPHP_PHP5) + { + $bodyCopy = clone($amf->getBodyAt(0)); + } + else + { + $bodyCopy = $amf->getBodyAt(0); + } + + $uri = $bodyCopy->targetURI; + $lpos = strrpos($uri, "."); + $cp = substr($uri, 0, $lpos + 1) . "_authenticate"; + $bodyCopy->targetURI = $cp; + $bodyCopy->setSpecialHandling('auth'); + $val = $authHeader->value; + $bodyCopy->setValue($val); + $amf->addBodyAt(0, $bodyCopy); + + //Make it so that the data will stop being transmitted + $clearHeader = array('name' => 'Credentials', 'mustUnderstand' => false, + 'data' => AMFPHP_CLEARED_CREDENTIALS); + $outHeader = new MessageHeader("RequestPersistentHeader", true, $clearHeader); + $amf->addOutgoingHeader($outHeader); + } + + $sessionName = @ini_get('session.name'); + if($sessionName == "" || $sessionName == NULL) + { + //Fix for godaddy not allowing ini_get + $sessionName = "PHPSESSID"; + } + session_start(); + $session_id = session_id(); + if(!strpos($_SERVER['QUERY_STRING'], $session_id) !== FALSE) + { + /** + Instead of trying to guess if using https, + just use AppendTogGatewayUrl instead + of ReplaceGatewayUrl + */ + if(strrpos($_SERVER['QUERY_STRING'], "?") !== FALSE) + { + $joint = "&"; + } + else + { + $joint = "?"; + } + $outHeader = new MessageHeader("AppendToGatewayUrl", false, $joint . $sessionName . "=" . $session_id); + $amf->addOutgoingHeader($outHeader); + } +} + +/** + * Executes each of the bodys + */ +function batchProcessFilter(&$amf) +{ + $bodycount = $amf->numBody(); + + for ($i = 0; $i < $bodycount; $i++) { + $bodyObj = &$amf->getBodyAt($i); + $actions = $GLOBALS['amfphp']['actions']; + foreach($actions as $key => $action) + { + $results = $action($bodyObj); + if($results === false) + { + break; + } + } + } + + $bodycount = $amf->numBody(); + + for ($i = 0; $i < $bodycount; $i++) { + $bodyObj = &$amf->getBodyAt($i); + if($bodyObj->getSpecialHandling() == 'auth' && $bodyObj->getResults() === NULL) + { + $amf->removeBodyAt($i); + break; + } + } +} + +/** + * Adds debugging information to outgoing packet + */ +function debugFilter (&$amf) { + //Add trace headers before outputting + if(!$GLOBALS['amfphp']['isFlashComm'] && !$GLOBALS['amfphp']['disableTrace']) + { + $headerresults = array(); // create a result array + $headerresults[0] = array(); // create a sub array in results (CF seems to do this, don't know why) + + if(count(NetDebug::getTraceStack()) != 0) + { + $ts = NetDebug::getTraceStack(); + $headerresults[0][] = new TraceHeader($ts); + } + if(Headers::getHeader("serviceBrowser") == true) + { + global $amfphp; + $amfphp['totalTime'] = microtime_float() - $amfphp['startTime']; + $headerresults[0][] = new ProfilingHeader(); + } + + //Get the last body in the stack + if(count($headerresults[0]) > 0) + { + $body = &$amf->getBodyAt($amf->numBody() - 1); + + $headers = new MessageBody(NULL, $body->responseIndex, NULL); // create a new amf body + $headers->responseURI = $body->responseIndex . "/onDebugEvents"; // set the response uri of this body + + $headers->setResults($headerresults); // set the results. + $amf->addBodyAt(0, $headers); + } + } +} + +/** + * Serializes the object + */ +function serializationFilter (&$amf) { + if($GLOBALS['amfphp']['native'] === true && function_exists('amf_decode')) + { + $serializer = new AMFBaseSerializer(); // Create a serailizer around the output stream + } + else + { + $serializer = new AMFSerializer(); // Create a serailizer around the output stream + } + $result = $serializer->serialize($amf); // serialize the data + $amf->outputStream = $result; +} +?> \ No newline at end of file diff --git a/core/amf/app/Gateway.php b/core/amf/app/Gateway.php new file mode 100755 index 0000000..ac6edf0 --- /dev/null +++ b/core/amf/app/Gateway.php @@ -0,0 +1,410 @@ +exec = new Executive(); + $this->filters = array(); + $this->actions = array(); + $this->registerFilterChain(); + $this->registerActionChain(); + } + + /** + * Create the chain of filters + * Subclass gateway and overwrite to create a custom gateway + */ + function registerFilterChain() + { + //filters + $this->filters['deserial'] = 'deserializationFilter'; + $this->filters['auth'] = 'authenticationFilter'; + $this->filters['batch'] = 'batchProcessFilter'; + $this->filters['debug'] = 'debugFilter'; + $this->filters['serialize'] = 'serializationFilter'; + } + + /** + * Create the chain of actions + * Subclass gateway and overwrite to create a custom gateway + */ + function registerActionChain() + { + $this->actions['adapter'] = 'adapterAction'; + $this->actions['class'] = 'classLoaderAction'; + $this->actions['security'] = 'securityAction'; + $this->actions['exec'] = 'executionAction'; + } + + /** + * The service method runs the gateway application. It turns the gateway 'on'. You + * have to call the service method as the last line of the gateway script after all of the + * gateway configuration properties have been set. + * + * Right now the service method also includes a very primitive debugging mode that + * just dumps the raw amf input and output to files. This may change in later versions. + * The debugging implementation is NOT thread safe so be aware of file corruptions that + * may occur in concurrent environments. + */ + + function service() { + + //Set the parameters for the charset handler + CharsetHandler::setMethod($this->_charsetMethod); + CharsetHandler::setPhpCharset($this->_charsetPhp); + CharsetHandler::setSqlCharset($this->_charsetSql); + + //Attempt to call charset handler to catch any uninstalled extensions + $ch = new CharsetHandler('flashtophp'); + $ch->transliterate('?'); + + $ch2 = new CharsetHandler('sqltophp'); + $ch2->transliterate('?'); + + $GLOBALS['amfphp']['actions'] = $this->actions; + + if (!isset($GLOBALS['HTTP_RAW_POST_DATA'])){ + $GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents('php://input'); + } + + if(isset($GLOBALS["HTTP_RAW_POST_DATA"]) && $GLOBALS["HTTP_RAW_POST_DATA"] != "") + { + //Start NetDebug + NetDebug::initialize(); + + error_reporting($GLOBALS['amfphp']['errorLevel']); + + //Enable loose mode if requested + if($this->_looseMode) + { + ob_start(); + } + + $amf = new AMFObject($GLOBALS["HTTP_RAW_POST_DATA"]); // create the amf object + + if($this->incomingMessagesFolder != NULL) + { + $mt = microtime(); + $pieces = explode(' ', $mt); + file_put_contents($this->incomingMessagesFolder . + 'in.' . $pieces[1] . '.' . substr($pieces[0], 2) . ".amf", + $GLOBALS["HTTP_RAW_POST_DATA"]); + } + + foreach($this->filters as $key => $filter) + { + $filter($amf); // invoke the first filter in the chain + } + + $output = $amf->outputStream; // grab the output stream + + //Clear the current output buffer if requested + if($this->_looseMode) + { + ob_end_clean(); + } + + //Send content length header + //Thanks to Alec Horley for pointing out the necessity + //of this for FlashComm support + header(AMFPHP_CONTENT_TYPE); // define the proper header + + if(Headers::getHeader('serviceBrowser') == true) + { + //Add the total time header + $toAddPos = strpos($output, "\301\260\0\0\1\0\0\0"); + $time = (int) ((microtime_float() - $GLOBALS['amfphp']['startTime'])*1000); + $b = pack("d", $time); // pack the bytes + if (AMFPHP_BIG_ENDIAN) { // if we are a big-endian processor + $r = strrev($b); + } else { // add the bytes to the output + $r = $b; + } + $output = substr($output, 0, $toAddPos) . $r . substr($output, $toAddPos + 8); + } + + //Send expire header, apparently helps for SSL + //Thanks to Gary Rogers for that + //And also to Lucas Filippi from openAMF list + //And to Robert Reinhardt who appears to be the first who + //documented the bug + //Finally to Gary who appears to have find a solution which works even more reliably + $dateStr = date("D, j M Y ") . date("H:i:s", strtotime("-2 days")); + header("Expires: $dateStr GMT"); + header("Pragma: no-store"); + header("Cache-Control: no-store"); + + //else don't send any special headers at all + + if($this->outgoingMessagesFolder != NULL) + { + $mt = microtime(); + $pieces = explode(' ', $mt); + file_put_contents($this->outgoingMessagesFolder . + 'out.' . $pieces[1] . '.' . substr($pieces[0], 2) . ".amf", $output); + } + + $doCompress = false; + $outputCompression = @ini_get("zlib.output_compression"); + if(!$outputCompression) + { + if(strlen($output) > $this->_gzipCompressionThreshold && + extension_loaded("zlib") && + strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE && + $this->_enableGzipCompression) + { + $doCompress = true; + ob_start(); + ob_start('ob_gzhandler'); + } + else + { + header("Content-length: " . strlen($output)); + } + } + + print($output); // flush the binary data + + if($doCompress) + { + ob_end_flush(); + header("Content-length: " . ob_get_length()); + ob_end_flush(); + } + } + else + { + echo("

amfphp and this gateway are installed correctly. You may now connect " . + "to this gateway from Flash.

"); + + if(function_exists("amf_decode")) + { + echo("

AMF C Extension is loaded " . + ($GLOBALS['amfphp']['native'] ? "and enabled." : "but disabled") . + "

"); + } + echo "

Note: If you're reading an " . + "old tutorial, it will tell you that you should see a download ". + "window instead of this message. This confused people so this is " . + "the new behaviour starting from amfphp 1.2.

" . + "View the amfphp documentation

" . + "

Load the service browser

"; + echo "
";
+		}
+	}
+	
+	/**
+	 * Setter for error handling
+	 * 
+	 * @param the error handling level
+	 */
+	function setErrorHandling($level)
+	{
+		$GLOBALS['amfphp']['errorLevel'] = $level;
+	}
+	
+	/**
+	 * Sets the base path for loading service methods.
+	 * 
+	 * Call this method to define the directory to look for service classes in.
+	 * Relative or full paths are acceptable
+	 * 
+	 * @param string $path The path the the service class directory
+	 */
+	function setClassPath($value) {
+		$path = realpath($value . '/') . '/';
+		$GLOBALS['amfphp']['classPath'] = $path;
+	}
+	
+	/**
+	 * Sets the base path for loading service methods.
+	 * 
+	 * Call this method to define the directory to look for service classes in.
+	 * Relative or full paths are acceptable
+	 * 
+	 * @param string $path The path the the service class directory
+	 */
+	function setClassMappingsPath($value) {
+		$path = realpath($value . '/') . '/';
+		$GLOBALS['amfphp']['customMappingsPath'] = $path;
+	}
+	
+	/**
+	 * Sets the loose mode. This will enable outbut buffering
+	 * And flushing and set error_reporting to 0. The point is if set to true, a few
+	 * of the usual NetConnection.BadVersion error should disappear
+	 * Like if you try to echo directly from your function, if you are issued a 
+	 * warning and such. Errors should still be logged to the error log though.
+	 *
+	 * @example In gateway.php, before $gateway->service(), use $gateway->setLooseMode(true) 
+	 * @param bool $mode Enable or disable loose mode
+	 */
+	function setLooseMode($paramLoose = true) {
+		$this->_looseMode = $paramLoose;
+	} 
+	
+	function enableGzipCompression($threshold = 30100)
+	{
+		$this->_enableGzipCompression = true;
+		$this->_gzipCompressionThreshold = $threshold;
+	}
+	
+	/**
+	 * Sets the charset handler. 
+	 * The charset handler handles reencoding from and to a specific charset
+	 * for PHP and SQL resources.
+	 *
+	 * @param $method The method used for reencoding, either "none", "iconv" or "runtime"
+	 * @param $php The internal encoding that is assumed for PHP (typically ISO-8859-1)
+	 * @param $sql The internal encoding that is assumed for SQL resources
+	 */
+	function setCharsetHandler($method = "none", $php, $sql) {
+		$this->_charsetMethod = $method;
+		$this->_charsetPhp = $php;
+		$this->_charsetSql = $sql;
+	} 
+	
+	/**
+	 * disableTrace will ignore any calls to NetDebug::trace
+	 * 
+	 * @param bool $bool Whether to disable tracing
+	 */
+	function disableDebug($value = true) {
+		$GLOBALS['amfphp']['disableDebug'] = $value;
+	} 
+	
+	/**
+	 * Disable native extension will disable the native C extension
+	 */
+	function disableNativeExtension()
+	{
+		$GLOBALS['amfphp']['native'] = false;
+	}
+	
+	/**
+	 * Log incoming messages to the specified folder
+	 */
+	function logIncomingMessages($folder = NULL)
+	{
+		$this->incomingMessagesFolder = realpath($folder) . '/';
+	}
+	
+	/**
+	 * Log outgoing messages to the specified folder
+	 */
+	function logOutgoingMessages($folder = NULL)
+	{
+		$this->outgoingMessagesFolder = realpath($folder) . '/';
+	}
+
+	/**
+	 * Dumps data to a file
+	 * 
+	 * @param string $filepath The location of the dump file
+	 * @param string $data The data to insert into the dump file
+	 */
+	function _saveRawDataToFile($filepath, $data) {
+		if (!$handle = fopen($filepath, 'w')) {
+			exit;
+		} 
+		if (!fwrite($handle, $data)) {
+			exit;
+		} 
+		fclose($handle);
+	}
+
+	/**
+	 * Appends data to a file
+	 * 
+	 * @param string $filepath The location of the dump file
+	 * @param string $data The data to append to the dump file
+	 */
+	function _appendRawDataToFile($filepath, $data) {
+		$handle = fopen($filepath, 'a');
+		fwrite($handle, $data);
+		fclose($handle);
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/core/amf/io/AMFBaseDeserializer.php b/core/amf/io/AMFBaseDeserializer.php
new file mode 100755
index 0000000..53aabe6
--- /dev/null
+++ b/core/amf/io/AMFBaseDeserializer.php
@@ -0,0 +1,400 @@
+isBigEndian = AMFPHP_BIG_ENDIAN;
+		$this->current_byte = 0;
+		$this->raw_data = $rd;  // store the stream in this object
+		$this->content_length = strlen($this->raw_data); // grab the total length of this stream
+		$this->charsetHandler = new CharsetHandler('flashtophp');
+		$this->storedStrings = array();
+		$this->storedObjects = array();
+		$this->storedDefinitions = array();
+		$this->native = $GLOBALS['amfphp']['native'] && function_exists('amf_decode');
+		$this->decodeFlags = (AMFPHP_BIG_ENDIAN*2) | 4;
+	} 
+
+	/**
+	 * deserialize invokes this class to transform the raw data into valid object
+	 * 
+	 * @param object $amfdata The object to put the deserialized data in
+	 */
+	function deserialize (&$amfdata) {
+		$time = microtime_float();
+		$this->amfdata = &$amfdata;
+		$this->readHeader(); // read the binary header
+		$this->readBody(); // read the binary body
+		if($this->decodeFlags & 1 == 1)
+		{
+			//AMF3 mode
+			$GLOBALS['amfphp']['encoding'] = "amf3";
+		}
+		global $amfphp;
+		$amfphp['decodeTime'] = microtime_float() - $time;
+	} 
+	/**
+	 * returns the built AMFObject from the deserialization operation
+	 * 
+	 * @return object The deserialized AMFObject
+	 */
+	function getAMFObject() {
+		return $this->amfdata;
+	} 
+	
+	/**
+	 * Decode callback is triggered when an object is encountered on decode
+	 */
+	function decodeCallback($event, $arg)
+	{
+		if($event == 1) //Object
+		{
+		   $type =$arg;
+		   return $this->mapClass($type);
+		}
+		else if($event == 2) //Object post decode
+		{
+		   $obj = $arg;
+		   if(method_exists($obj, 'init'))
+		   {
+		       $obj->init();
+		   }
+		   return $obj;
+		} 
+		else if($event == 3) //XML post-decode
+		{
+			return $arg;
+		}
+		else if($event == 4) //Serializable post-decode
+		{
+			if($type == 'flex.messaging.io.ArrayCollection' || $type == 'flex.messaging.io.ObjectProxy')
+			{
+			    return;
+			}
+			else
+			{
+			   trigger_error("Unable to read externalizable data type " . $type, E_USER_ERROR);
+			   return "error";
+			}
+		}
+		else if($event == 5) //ByteArray post decode
+		{
+			return new ByteArray($arg);
+		}
+	}
+
+	/**
+	 * readHeader converts that header section of the amf message into php obects.
+	 * Header information typically contains meta data about the message.
+	 */
+	function readHeader() {
+
+		$topByte = $this->readByte(); // ignore the first two bytes --  version or something
+		$secondByte = $this->readByte(); //0 for Flash,
+										 //1 for FlashComm                   
+		//Disable debug events for FlashComm
+		$GLOBALS['amfphp']['isFlashComm'] = $secondByte == 1;
+		
+		//If firstByte != 0, then the AMF data is corrupted, for example the transmission 
+		//
+		if(!($topByte == 0 || $topByte == 3))
+		{
+			trigger_error("Malformed AMF message, connection may have dropped");
+			exit();
+		}
+		$this->header_count = $this->readInt(); //  find the total number of header elements
+		while ($this->header_count--) { // loop over all of the header elements
+			$name = $this->readUTF();
+			$required = $this->readByte() == 1; // find the must understand flag
+			//$length   = $this->readLong(); // grab the length of  the header element
+			$this->current_byte += 4; // grab the length of the header element
+			if($this->native)
+			{
+			    $content = amf_decode($this->raw_data, $this->decodeFlags, $this->current_byte, array(& $this, "decodeCallback"));
+			}
+			else
+			{
+			    $type = $this->readByte();  // grab the type of the element
+			    $content = $this->readData($type); // turn the element into real data
+			}
+			
+			$this->amfdata->addHeader(new MessageHeader($name, $required, $content)); // save the name/value into the headers array
+		}
+
+	} 
+
+	/**
+	 * readBody converts the payload of the message into php objects.
+	 */
+	function readBody() {
+		$this->body_count = $this->readInt(); // find the total number  of body elements
+		while ($this->body_count--) { // loop over all of the body elements
+			
+			$this->amf0storedObjects = array();
+			$this->storedStrings = array();
+			$this->storedObjects = array();
+			$this->storedDefinitions = array();
+			
+			$target = $this->readUTF();
+			$response = $this->readUTF(); //    the response that the client understands
+			
+			//$length = $this->readLong(); // grab the length of    the body element
+			$this->current_byte += 4;
+			
+			if($this->native)
+			   $data = amf_decode($this->raw_data, $this->decodeFlags, $this->current_byte, array(& $this, "decodeCallback"));
+			else
+			{
+			   $type = $this->readByte();  // grab the type of the element
+			   $data = $this->readData($type); // turn the element into real data
+			}
+			
+			$this->amfdata->addBody(new MessageBody($target, $response, $data)); // add the body element to the body object
+			
+		} 
+	} 
+	
+	/********************************************************************************
+	 *                       This used to be in AmfInputStream
+	 ********************************************************************************
+
+	/**
+	 * readByte grabs the next byte from the data stream and returns it.
+	 * 
+	 * @return int The next byte converted into an integer
+	 */
+	function readByte() {
+		return ord($this->raw_data[$this->current_byte++]); // return the next byte
+	}
+
+	/**
+	 * readInt grabs the next 2 bytes and returns the next two bytes, shifted and combined
+	 * to produce the resulting integer
+	 * 
+	 * @return int The resulting integer from the next 2 bytes
+	 */
+	function readInt() {
+		return ((ord($this->raw_data[$this->current_byte++]) << 8) |
+			ord($this->raw_data[$this->current_byte++])); // read the next 2 bytes, shift and add
+	} 
+
+	/**
+	 * readUTF first grabs the next 2 bytes which represent the string length.
+	 * Then it grabs the next (len) bytes of the resulting string.
+	 * 
+	 * @return string The utf8 decoded string
+	 */
+	function readUTF() {
+		$length = $this->readInt(); // get the length of the string (1st 2 bytes)
+		//BUg fix:: if string is empty skip ahead
+		if($length == 0)
+		{
+			return "";
+		}
+		else
+		{
+			$val = substr($this->raw_data, $this->current_byte, $length); // grab the string
+			$this->current_byte += $length; // move the seek head to the end of the string
+			return $this->charsetHandler->transliterate($val); // return the string
+		}
+	} 
+	
+	/**
+	 * readLong grabs the next 4 bytes shifts and combines them to produce an integer
+	 * 
+	 * @return int The resulting integer from the next 4 bytes
+	 */
+	function readLong() {
+		return ((ord($this->raw_data[$this->current_byte++]) << 24) |
+			(ord($this->raw_data[$this->current_byte++]) << 16) |
+			(ord($this->raw_data[$this->current_byte++]) << 8) |
+			ord($this->raw_data[$this->current_byte++])); // read the next 4 bytes, shift and add
+	} 
+
+	/**
+	 * readDouble reads the floating point value from the bytes stream and properly orders
+	 * the bytes depending on the system architecture.
+	 * 
+	 * @return float The floating point value of the next 8 bytes
+	 */
+	function readDouble() {
+		$bytes = substr($this->raw_data, $this->current_byte, 8);
+		$this->current_byte += 8;
+		if ($this->isBigEndian) {
+			 $bytes = strrev($bytes);
+		} 
+		$zz = unpack("dflt", $bytes); // unpack the bytes
+		return $zz['flt']; // return the number from the associative array
+	} 
+
+	/**
+	 * readLongUTF first grabs the next 4 bytes which represent the string length.
+	 * Then it grabs the next (len) bytes of the resulting in the string
+	 * 
+	 * @return string The utf8 decoded string
+	 */
+	function readLongUTF() {
+		$length = $this->readLong(); // get the length of the string (1st 4 bytes)
+		$val = substr($this->raw_data, $this->current_byte, $length); // grab the string
+		$this->current_byte += $length; // move the seek head to the end of the string
+		return $this->charsetHandler->transliterate($val); // return the string
+	} 
+    
+    function mapClass($typeIdentifier)
+    {
+		//Check out if class exists
+		if($typeIdentifier == "")
+		{
+			return NULL;
+		}
+		$clazz = NULL;
+		$mappedClass = str_replace('.', '/', $typeIdentifier);
+		
+		if($typeIdentifier == "flex.messaging.messages.CommandMessage")
+		{
+			return new CommandMessage();
+		}
+		if($typeIdentifier == "flex.messaging.messages.RemotingMessage")
+		{
+			return new RemotingMessage();
+		}
+		
+		if(isset($GLOBALS['amfphp']['incomingClassMappings'][$typeIdentifier]))
+		{
+			$mappedClass = str_replace('.', '/', $GLOBALS['amfphp']['incomingClassMappings'][$typeIdentifier]);
+		}
+		
+		$include = FALSE;
+		if(file_exists($GLOBALS['amfphp']['customMappingsPath'] . $mappedClass . '.php'))
+		{
+			$include = $GLOBALS['amfphp']['customMappingsPath'] . $mappedClass . '.php';
+		}
+		elseif(file_exists($GLOBALS['amfphp']['customMappingsPath'] . $mappedClass . '.class.php'))
+		{
+			$include = $GLOBALS['amfphp']['customMappingsPath'] . $mappedClass . '.class.php';
+		}
+		
+		if($include !== FALSE)
+		{
+			include_once($include);
+			$lastPlace = strrpos('/' . $mappedClass, '/');
+			$classname = substr($mappedClass, $lastPlace);
+			if(class_exists($classname))
+			{
+				$clazz = new $classname;
+			}
+		}
+		
+		return $clazz; // return the object
+    }
+} 
+
+?>
\ No newline at end of file
diff --git a/core/amf/io/AMFBaseSerializer.php b/core/amf/io/AMFBaseSerializer.php
new file mode 100755
index 0000000..e404d51
--- /dev/null
+++ b/core/amf/io/AMFBaseSerializer.php
@@ -0,0 +1,327 @@
+isBigEndian = AMFPHP_BIG_ENDIAN;
+		$this->outBuffer = ""; // the buffer
+		$this->charsetHandler = new CharsetHandler('phptoflash');
+		$this->rsCharsetHandler = new CharsetHandler('sqltoflash');
+		$this->resourceObjects = $GLOBALS['amfphp']['adapterMappings'];
+		$this->native = $GLOBALS['amfphp']['native'] && function_exists('amf_decode');
+		$this->encodeFlags = (AMFPHP_BIG_ENDIAN?2:0) | 
+							  ($GLOBALS['amfphp']['encoding'] == 'amf3' ? 1:0);
+	} 
+
+	/**
+	 * serialize is the run method of the class.  When serialize is called
+	 * the AMFObject passed in is read and converted into the amf binary
+	 * representing the PHP data represented.
+	 * 
+	 * @param object $d the AMFObject to serialize
+	 */
+	function serialize(&$amfout) {
+		$encodeCallback = array(&$this,"encodeCallback");
+		$this->writeInt(0); //  write the version ???
+		$count = $amfout->numOutgoingHeader();
+		$this->writeInt($count); // write header count
+		for ($i = 0; $i < $count; $i++) {
+			//write headers
+			$header = &$amfout->getOutgoingHeaderAt($i);
+			$this->writeUTF($header->name);
+			$this->writeByte(0);
+			$tempBuf = $this->outBuffer;
+			$this->outBuffer = "";
+			if($this->native)
+			    $this->outBuffer .= amf_encode($header->value,$this->encodeFlags, $encodeCallback);
+			else
+			    $this->writeData($header->value);
+			$tempBuf2 = $this->outBuffer;
+			$this->outBuffer = $tempBuf;
+			$this->writeLong(strlen($tempBuf2));
+			$this->outBuffer .= $tempBuf2;
+		} 
+		$count = $amfout->numBody();
+		$this->writeInt($count); // write the body  count
+		for ($i = 0; $i < $count; $i++) {
+			//write body
+			$this->amf0StoredObjects = array();
+			$this->storedStrings = array();
+			$this->storedObjects = array();
+			$this->encounteredStrings = 0;
+			$this->storedDefinitions = 0;
+			$body = &$amfout->getBodyAt($i);
+			$this->currentBody = & $body;
+			$this->writeUTF($body->responseURI); // write the responseURI header
+			$this->writeUTF($body->responseTarget); //  write null, haven't found another use for this
+			$tempBuf = $this->outBuffer;
+			$this->outBuffer = "";
+			
+			if($this->native)
+			    $this->outBuffer .= amf_encode($body->getResults(),$this->encodeFlags, $encodeCallback);
+			else
+			    $this->writeData($body->getResults());
+
+			$tempBuf2 = $this->outBuffer;
+			$this->outBuffer = $tempBuf;
+			$this->writeLong(strlen($tempBuf2));
+			$this->outBuffer .= $tempBuf2;
+		} 
+		
+		return $this->outBuffer;
+	} 
+	
+	function encodeCallback($value)
+	{
+		///print_r($value);
+		if(is_object($value))
+		{
+			$className = strtolower(get_class($value));
+			if(AMFPHP_PHP5 && $className == 'domdocument')
+			{
+				return array($this->cleanXml($value->saveXml()),1);
+			}
+			else if(array_key_exists($className, $GLOBALS['amfphp']['adapterMappings']))
+			{
+				$subtype = $GLOBALS['amfphp']['adapterMappings'][strtolower($className)];
+				
+				$classname = $subtype . "Adapter"; // full class name
+				$includeFile = include_once(AMFPHP_BASE . "shared/adapters/" . $classname . ".php"); // try to load the recordset library from the sql folder
+				if (!$includeFile) {
+					trigger_error("The recordset filter class " . $classname . " was not found", E_USER_ERROR);
+				} 
+				$recordSet = new $classname($value); // returns formatted recordset
+				return array(
+					array("__amf_recordset__" => 2,
+						 "rows" => $recordSet->rows,
+						 "columns" => $recordSet->columns),
+				5);
+			}
+			else if(AMFPHP_PHP5 == 0 && $className == 'domdocument')
+			{
+				return array($this->cleanXml($value->dump_mem()),1);
+			}
+			else if($className == 'simplexmlelement')
+			{
+				return array($this->cleanXml($value->asXML()),1);
+			}
+			elseif($className == 'bytearray' && $this->encodeFlags & 1 == 1)
+			{
+				return array($value->data, 7);
+			}
+			else
+			{
+				$className = $this->getClassName($value);
+				return array($value,3,$className);
+			}
+		}
+		else
+		{
+			//A resource
+			$type = get_resource_type($value);
+			list($type, $subtype) = $this->sanitizeType($type);
+			$classname = $subtype . "Adapter"; // full class name
+			$includeFile = include_once(AMFPHP_BASE . "shared/adapters/" . $classname . ".php"); // try to load the recordset library from the sql folder
+			if (!$includeFile) {
+				trigger_error("The recordset filter class " . $classname . " was not found", E_USER_ERROR);
+			} 
+			$recordSet = new $classname($value); // returns formatted recordset
+			return array(
+				array("__amf_recordset__" => 2,
+						 "rows" => $recordSet->rows,
+						 "columns" => $recordSet->columns), 
+				5);
+		}
+	}
+	
+	function cleanXml($d)
+	{
+		return preg_replace('/\>(\n|\r|\r\n| |\t)*\<',trim($d));
+	}
+	
+	/**********************************************************************************
+	 *                      This code used to be in AMFOutputStream
+	 ********************************************************************************/
+
+	/**
+	 * writeByte writes a singe byte to the output stream
+	 * 0-255 range
+	 * 
+	 * @param int $b An int that can be converted to a byte
+	 */
+	function writeByte($b) {
+		$this->outBuffer .= pack("c", $b); // use pack with the c flag
+	} 
+
+	/**
+	 * writeInt takes an int and writes it as 2 bytes to the output stream
+	 * 0-65535 range
+	 * 
+	 * @param int $n An integer to convert to a 2 byte binary string
+	 */
+	function writeInt($n) {
+		$this->outBuffer .= pack("n", $n); // use pack with the n flag
+	} 
+
+	/**
+	 * writeLong takes an int, float or double and converts it to a 4 byte binary string and
+	 * adds it to the output buffer
+	 * 
+	 * @param long $l A long to convert to a 4 byte binary string
+	 */
+	function writeLong($l) {
+		$this->outBuffer .= pack("N", $l); // use pack with the N flag
+	} 
+
+	/**
+	 * writeUTF takes and input string, writes the length as an int and then
+	 * appends the string to the output buffer
+	 * 
+	 * @param string $s The string less than 65535 characters to add to the stream
+	 */
+	function writeUTF($s) {
+		$os = $this->charsetHandler->transliterate($s);
+		$this->writeInt(strlen($os)); // write the string length - max 65535
+		$this->outBuffer .= $os; // write the string chars
+	} 
+	
+	/**
+	 * writeBinary takes and input string, writes the length as an int and then
+	 * appends the string to the output buffer
+	 * 
+	 * @param string $s The string less than 65535 characters to add to the stream
+	 */
+	function writeBinary($s) {
+		$this->outBuffer .= $s; // write the string chars
+	} 
+
+	/**
+	 * writeLongUTF will write a string longer than 65535 characters.
+	 * It works exactly as writeUTF does except uses a long for the length
+	 * flag.
+	 * 
+	 * @param string $s A string to add to the byte stream
+	 */
+	function writeLongUTF($s) {
+		$os = $this->charsetHandler->transliterate($s);
+		$this->writeLong(strlen($os));
+		$this->outBuffer .= $os; // write the string chars
+	} 
+
+	/**
+	 * writeDouble takes a float as the input and writes it to the output stream.
+	 * Then if the system is big-endian, it reverses the bytes order because all
+	 * doubles passed via remoting are passed little-endian.
+	 * 
+	 * @param double $d The double to add to the output buffer
+	 */
+	function writeDouble($d) {
+		$b = pack("d", $d); // pack the bytes
+		if ($this->isBigEndian) { // if we are a big-endian processor
+			$r = strrev($b);
+		} else { // add the bytes to the output
+			$r = $b;
+		} 
+		
+		$this->outBuffer .= $r;
+	} 
+	
+	function sanitizeType($type)
+	{
+		$subtype = -1;
+		$type = strtolower($type);
+		if($type == NULL || trim($type) == "")
+		{
+			$type = -1;
+		}
+		
+		if(strpos($type, ' ') !== false)
+		{
+			$str = explode(' ', $type);
+			if(in_array($str[1], array("result", 'resultset', "recordset", "statement")))
+			{
+				$type = "__RECORDSET__";
+				$subtype = $str[0];
+			}
+		}
+		return array($type, $subtype);
+	} 
+	
+	function getClassName(&$d)
+	{
+		$classname = get_class($d);
+		if(strtolower($classname) == 'stdclass' && !isset($d->_explicitType) )
+		{
+			return "";
+		}
+		
+		if(isset($d->_explicitType))
+		{
+			$type = $d->_explicitType;
+			unset($d->_explicitType);
+			return $type;
+		}
+		
+		if(isset($GLOBALS['amfphp']['outgoingClassMappings'][strtolower($classname)]))
+		{
+			return $GLOBALS['amfphp']['outgoingClassMappings'][strtolower($classname)];
+		}
+		
+		if(class_exists("ReflectionClass")) //Another way of doing things, by Renaun Erickson
+		{
+		    $reflectionClass = new ReflectionClass( $classname );
+		    $fileName = $reflectionClass->getFileName();
+		   
+		    $basePath = $GLOBALS['amfphp']['customMappingsPath'];
+		    if( $basePath == "" )
+		        $basePath = getcwd();
+		
+		    // Handle OS filesystem differences
+		    if( DIRECTORY_SEPARATOR == "\\" && ( strpos( $basePath, DIRECTORY_SEPARATOR ) === false ) )
+		        $basePath = str_replace( "/", DIRECTORY_SEPARATOR, $basePath );
+		    
+		    if(strpos($fileName, $basePath) === FALSE)
+		    {
+		    	return $classname;
+		    }
+		    $fullClassName = substr( $fileName, strpos( $fileName, $basePath ) );
+		    $fullClassName = substr( $fullClassName, strlen( $basePath ) );
+		    $fullClassName = substr( $fullClassName, 0, strlen( $fullClassName ) - 4 );
+		    $fullClassName = str_replace( DIRECTORY_SEPARATOR, '.', $fullClassName );
+		
+		    return $fullClassName;
+		}
+		return $classname;
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/amf/io/AMFDeserializer.php b/core/amf/io/AMFDeserializer.php
new file mode 100755
index 0000000..2acaa0c
--- /dev/null
+++ b/core/amf/io/AMFDeserializer.php
@@ -0,0 +1,644 @@
+amf0storedObjects[] = & $ret;
+		$key = $this->readUTF(); // grab the key
+		for ($type = $this->readByte(); $type != 9; $type = $this->readByte()) {
+			$val = $this->readData($type); // grab the value
+			$ret[$key] = $val; // save the name/value pair in the array
+			$key = $this->readUTF(); // get the next name
+		}
+		return $ret; // return the array
+	} 
+	
+	/**
+	 * readMixedObject reads the name/value properties of the amf message and converts
+	 * numeric looking keys to numeric keys
+	 * 
+	 * @return array The php array with the object data
+	 */
+	function readMixedObject() {
+		$ret = array(); // init the array
+		$this->amf0storedObjects[] = & $ret;
+		$key = $this->readUTF(); // grab the key
+		for ($type = $this->readByte(); $type != 9; $type = $this->readByte()) {
+			$val = $this->readData($type); // grab the value
+			if(is_numeric($key))
+			{
+				$key = (float) $key;
+			}
+			$ret[$key] = $val; // save the name/value pair in the array
+			$key = $this->readUTF(); // get the next name
+		}
+		return $ret; // return the array
+	} 
+
+	/**
+	 * readArray turns an all numeric keyed actionscript array into a php array.
+	 * 
+	 * @return array The php array
+	 */
+	function readArray() {
+		$ret = array(); // init the array object
+		$this->amf0storedObjects[] = & $ret;
+		$length = $this->readLong(); // get the length  of the array
+		for ($i = 0; $i < $length; $i++) { // loop over all of the elements in the data
+			$type = $this->readByte();  // grab the type for each element
+			$ret[] = $this->readData($type); // grab each element
+		} 
+		return $ret; // return the data
+		
+	} 
+
+	/**
+	 * readMixedArray turns an array with numeric and string indexes into a php array
+	 * 
+	 * @return array The php array with mixed indexes
+	 */
+	function readMixedArray() {
+		//$length   = $this->readLong(); // get the length  property set by flash
+		$this->current_byte += 4;
+		return $this->readMixedObject(); // return the body of mixed array
+	} 
+
+	/**
+	 * readCustomClass reads the amf content associated with a class instance which was registered
+	 * with Object.registerClass.  In order to preserve the class name an additional property is assigned
+	 * to the object "_explicitType".  This property will be overwritten if it existed within the class already.
+	 * 
+	 * @return object The php representation of the object
+	 */
+	function readCustomClass() {
+		$typeIdentifier = str_replace('..', '', $this->readUTF());
+		$obj = $this->mapClass($typeIdentifier);
+		$isObject = true;
+		if($obj == NULL)
+		{
+			$obj = array();
+			$isObject = false;
+		}
+		$this->amf0storedObjects[] = & $obj;
+		$key = $this->readUTF(); // grab the key
+		for ($type = $this->readByte(); $type != 9; $type = $this->readByte()) {
+			$val = $this->readData($type); // grab the value
+			if($isObject)
+			{
+				$obj->$key = $val; // save the name/value pair in the array
+			}
+			else
+			{
+				$obj[$key] = $val; // save the name/value pair in the array
+			}
+			$key = $this->readUTF(); // get the next name
+		}
+		if(!$isObject)
+		{
+			$obj['_explicitType'] = $typeIdentifier;
+		}
+		return $obj; // return the array
+	} 
+
+	/**
+	 * readDate reads a date from the amf message and returns the time in ms.
+	 * This method is still under development.
+	 * 
+	 * @return long The date in ms.
+	 */
+	function readDate() {
+		$ms = $this->readDouble();  // date in milliseconds from 01/01/1970
+		$int = $this->readInt(); // nasty way to get timezone
+		if ($int > 720) {
+			$int = - (65536 - $int);
+		} 
+		$int *= -60;
+		//$int *= 1000;
+		//$min = $int % 60;
+		//$timezone = "GMT " . - $hr . ":" . abs($min);
+		// end nastiness
+		
+		//We store the last timezone found in date fields in the request
+		//FOr most purposes, it's expected that the timezones
+		//don't change from one date object to the other (they change per client though)
+		DateWrapper::setTimezone($int);
+		return $ms; 
+	}
+
+	/**
+	 * readReference replaces the old readFlushedSO. It treats where there
+	 * are references to other objects. Currently it does not resolve the
+	 * object as this would involve a serious amount of overhead, unless
+	 * you have a genius idea
+	 * 
+	 * @return String 
+	 */
+	function readReference() {
+		$reference = $this->readInt();
+		return $this->amf0storedObjects[$reference];
+	} 
+	
+	function readAny()
+	{
+	     if($this->native)
+	         return amfphp_decode($this->raw_data, $this->decodeFlags, $this->current_byte, array(& $this, "decodeCallback"));
+	     else
+	     {
+	 		$type = $this->readByte();  // grab the type of the element
+	 		return $this->readData($type); // turn the element into real data
+	     }
+	}
+
+	/**
+	 * readData is the main switch for mapping a type code to an actual
+	 * implementation for deciphering it.
+	 * 
+	 * @param mixed $type The $type integer
+	 * @return mixed The php version of the data in the message block
+	 */
+	function readData($type) {
+		switch ($type) {
+			case 0: // number
+				$data = $this->readDouble();
+				break;
+			case 1: // boolean
+				$data = $this->readByte() == 1;
+				break;
+			case 2: // string
+				$data = $this->readUTF();
+				break;
+			case 3: // object Object
+				$data = $this->readObject();
+				break;
+			case 5: // null
+				$data = null;
+				break;
+			case 6: // undefined
+				$data = null;
+				break;
+			case 7: // Circular references are returned here
+				$data = $this->readReference();
+				break;
+			case 8: // mixed array with numeric and string keys
+				$data = $this->readMixedArray();
+				break;
+			case 10: // array
+				$data = $this->readArray();
+				break;
+			case 11: // date
+				$data = $this->readDate();
+				break;
+			case 12: // string, strlen(string) > 2^16
+				$data = $this->readLongUTF();
+				break;
+			case 13: // mainly internal AS objects
+				$data = null;
+				break;
+			case 15: // XML
+				$data = $this->readLongUTF();
+				break;
+			case 16: // Custom Class
+				$data = $this->readCustomClass();
+				break;
+			case 17: //AMF3-specific
+				$GLOBALS['amfphp']['encoding'] = "amf3";
+				$data = $this->readAmf3Data();
+				break;
+			default: // unknown case
+				trigger_error("Found unhandled type with code: $type");
+				exit();
+				break;
+		} 
+		return $data;
+	} 
+	
+	/********************************************************************************
+	 *                       This is the AMF3 specific stuff
+	 ********************************************************************************/
+	function readAmf3Data()
+	{
+		$type = $this->readByte();
+		switch($type)
+		{
+			case 0x00 : return null; //undefined
+			case 0x01 : return null; //null
+			case 0x02 : return false; //boolean false
+			case 0x03 : return true;  //boolean true
+			case 0x04 : return $this->readAmf3Int();
+			case 0x05 : return $this->readDouble();
+			case 0x06 : return $this->readAmf3String();
+			case 0x07 : return $this->readAmf3XmlString();
+			case 0x08 : return $this->readAmf3Date();
+			case 0x09 : return $this->readAmf3Array();
+			case 0x0A : return $this->readAmf3Object();
+			case 0x0B : return $this->readAmf3XmlString();
+			case 0x0C : return $this->readAmf3ByteArray();
+			default: trigger_error("undefined Amf3 type encountered: " . $type, E_USER_ERROR);
+		}
+	}
+	
+	/// 
+	/// Handle decoding of the variable-length representation
+	/// which gives seven bits of value per serialized byte by using the high-order bit 
+	/// of each byte as a continuation flag.
+	/// 
+	/// 
+	function readAmf3Int()
+	{
+		$int = $this->readByte();
+		if($int < 128)
+			return $int;
+		else
+		{
+			$int = ($int & 0x7f) << 7;
+			$tmp = $this->readByte();
+			if($tmp < 128)
+			{
+				return $int | $tmp;
+			}
+			else
+			{
+				$int = ($int | ($tmp & 0x7f)) << 7;
+				$tmp = $this->readByte();
+				if($tmp < 128)
+				{
+					return $int | $tmp;
+				}
+				else
+				{
+					$int = ($int | ($tmp & 0x7f)) << 8;
+					$tmp = $this->readByte();
+					$int |= $tmp;
+					
+	            	// Check if the integer should be negative
+	            	if (($int & 0x10000000) != 0) {
+	            		// and extend the sign bit
+	            		$int |= 0xe0000000;
+	            	}
+	            	return $int;
+				}
+			}
+		}
+	}
+
+    function readAmf3Date() 
+    {
+        $dateref = $this->readAmf3Int();
+        if (($dateref & 0x01) == 0) {
+            $dateref = $dateref >> 1;
+            if ($dateref>=count($this->storedObjects)) {
+                trigger_error('Undefined date reference: ' . $dateref, E_USER_ERROR);
+                return false;
+            }
+            return $this->storedObjects[$dateref];
+        }
+        //$timeOffset = ($dateref >> 1) * 6000 * -1;
+        $ms = $this->readDouble();
+
+        //$date = $ms-$timeOffset;
+        $date = $ms;
+        
+        $this->storedObjects[] = & $date;
+        return $date;
+    }
+
+    /**
+     * readString 
+     * 
+     * @return string 
+     */
+    function readAmf3String() {
+
+        $strref = $this->readAmf3Int();
+
+        if (($strref & 0x01) == 0) {
+            $strref = $strref >> 1;
+            if ($strref >= count($this->storedStrings)) {
+                trigger_error('Undefined string reference: ' . $strref, E_USER_ERROR);
+                return false;
+            }
+            return $this->storedStrings[$strref];
+        } else {
+            $strlen = $strref >> 1; 
+            $str = "";
+            if ($strlen > 0) 
+            {
+            	$str = $this->readBuffer($strlen);
+            	$this->storedStrings[] = $str;
+            }
+            return $str;
+        }
+
+    }
+
+	function readAmf3XmlString()
+	{
+		$handle = $this->readAmf3Int();
+		$inline = (($handle & 1) != 0 ); $handle = $handle >> 1;
+		if( $inline )
+		{
+			$xml = $this->readBuffer($handle);
+			$this->storedStrings[] = $xml;
+		}
+		else
+		{
+			$xml = $this->storedObjects[$handle];
+		}
+		return $xml;
+	}
+
+	function readAmf3ByteArray()
+	{
+		$handle = $this->readAmf3Int();
+		$inline = (($handle & 1) != 0 );$handle = $handle >> 1;
+		if( $inline )
+		{
+			$ba = new ByteArray($this->readBuffer($handle));
+			$this->storedObjects[] = $ba;
+		}
+		else
+		{
+			$ba = $this->storedObjects[$handle];
+		}
+		return $ba;
+	}
+
+	function readAmf3Array()
+	{
+		$handle = $this->readAmf3Int();
+		$inline = (($handle & 1)  != 0 ); $handle = $handle >> 1;
+		if( $inline )
+		{
+			$hashtable = array();
+			$this->storedObjects[] = & $hashtable;
+			$key = $this->readAmf3String();
+			while( $key != "" )
+			{
+				$value = $this->readAmf3Data();
+				$hashtable[$key] = $value;
+				$key = $this->readAmf3String();
+			}
+
+			for($i = 0; $i < $handle; $i++)
+			{
+				//Grab the type for each element.
+				$value = $this->readAmf3Data();
+				$hashtable[$i] = $value;
+			}
+			return $hashtable;
+		}
+		else
+		{
+			return $this->storedObjects[$handle];
+		}
+	}
+
+	function readAmf3Object()
+	{
+		$handle = $this->readAmf3Int();
+		$inline = (($handle & 1) != 0 ); $handle = $handle >> 1;
+		
+		if( $inline )
+		{
+			//an inline object
+			$inlineClassDef = (($handle & 1) != 0 );$handle = $handle >> 1;
+			if( $inlineClassDef )
+			{
+				//inline class-def
+				$typeIdentifier = $this->readAmf3String();
+				$typedObject = !is_null($typeIdentifier) && $typeIdentifier != "";
+				//flags that identify the way the object is serialized/deserialized
+				$externalizable = (($handle & 1) != 0 );$handle = $handle >> 1;
+				$dynamic = (($handle & 1) != 0 );$handle = $handle >> 1;
+				$classMemberCount = $handle;
+				
+				$classMemberDefinitions = array();
+				for($i = 0; $i < $classMemberCount; $i++)
+				{
+					$classMemberDefinitions[] = $this->readAmf3String();
+				}
+				//string mappedTypeName = typeIdentifier;
+				//if( applicationContext != null )
+				//	mappedTypeName = applicationContext.GetMappedTypeName(typeIdentifier);
+
+				$classDefinition = array("type" => $typeIdentifier, "members" => $classMemberDefinitions,
+										"externalizable" => $externalizable, "dynamic" => $dynamic);
+				$this->storedDefinitions[] = $classDefinition;
+			}
+			else
+			{
+				//a reference to a previously passed class-def
+				$classDefinition = $this->storedDefinitions[$handle];
+			}
+		}
+		else
+		{
+			//an object reference
+			return $this->storedObjects[$handle];
+		}		
+		
+		
+		$type = $classDefinition['type'];
+		$obj = $this->mapClass($type);
+		
+		$isObject = true;
+		if($obj == NULL)
+		{
+			$obj = array();
+			$isObject = false;
+		}
+
+		//Add to references as circular references may search for this object
+		$this->storedObjects[] = & $obj;
+
+		if( $classDefinition['externalizable'] )
+		{
+			if($type == 'flex.messaging.io.ArrayCollection')
+			{
+				$obj = $this->readAmf3Data();
+			}
+			else if($type == 'flex.messaging.io.ObjectProxy')
+			{
+				$obj = $this->readAmf3Data();
+			}
+			else
+			{
+				trigger_error("Unable to read externalizable data type " . $type, E_USER_ERROR);
+			}
+		}
+		else
+		{
+			$members = $classDefinition['members'];
+			$memberCount = count($members);
+			for($i = 0; $i < $memberCount; $i++)
+			{
+				$val = $this->readAmf3Data();
+				$key = $members[$i];
+				if($isObject)
+				{
+					$obj->$key = $val;
+				}
+				else
+				{
+					$obj[$key] = $val;
+				}
+			}
+
+			if($classDefinition['dynamic']/* && obj is ASObject*/)
+			{
+				$key = $this->readAmf3String();
+				while( $key != "" )
+				{
+					$value = $this->readAmf3Data();
+					if($isObject)
+					{
+						$obj->$key = $value;
+					}
+					else
+					{
+						$obj[$key] = $value;
+					}
+					$key = $this->readAmf3String();
+				}
+			}
+			
+			if($type != '' && !$isObject)
+			{
+				$obj['_explicitType'] = $type;
+			}
+		}
+		
+		if($isObject && method_exists($obj, 'init'))
+		{
+			$obj->init();
+		}
+		
+		return $obj;
+	}
+    
+    /**
+     * Taken from SabreAMF
+     */
+    function readBuffer($len)
+    {
+    	$data = substr($this->raw_data,$this->current_byte,$len);
+    	$this->current_byte += $len;
+    	return $data;
+    }
+} 
+
+?>
\ No newline at end of file
diff --git a/core/amf/io/AMFSerializer.php b/core/amf/io/AMFSerializer.php
new file mode 100755
index 0000000..fffafb4
--- /dev/null
+++ b/core/amf/io/AMFSerializer.php
@@ -0,0 +1,1048 @@
+writeByte(1); // write the boolean flag
+		$this->writeByte($d); // write  the boolean byte
+	} 
+
+	/**
+	 * writeString writes the string code (0x02) and the UTF8 encoded
+	 * string to the output stream.
+	 * Note: strings are truncated to 64k max length. Use XML as type 
+	 * to send longer strings
+	 * 
+	 * @param string $d The string data
+	 */
+	function writeString($d) {
+		$count = strlen($d);
+		if($count < 65536)
+		{
+			$this->writeByte(2);
+			$this->writeUTF($d);
+		}
+		else
+		{
+			$this->writeByte(12);
+			$this->writeLongUTF($d);
+		}
+	}
+	
+	/**
+	 * writeXML writes the xml code (0x0F) and the XML string to the output stream
+	 * Note: strips whitespace
+	 * @param string $d The XML string
+	 */
+	function writeXML($d) {
+		if(!$this->writeReferenceIfExists($d))
+		{
+			$this->writeByte(15);
+			$this->writeLongUTF(preg_replace('/\>(\n|\r|\r\n| |\t)*\<',trim($d)));
+		}
+	} 
+
+	/**
+	 * writeData writes the date code (0x0B) and the date value to the output stream
+	 * 
+	 * @param date $d The date value
+	 */
+	function writeDate($d) {
+		$this->writeByte(11); // write  date code
+		$this->writeDouble($d); //  write date (milliseconds from 1970)
+		/**
+		 * write timezone
+		 * ?? this is wierd -- put what you like and it pumps it back into flash at the current GMT ??
+		 * have a look at the amf it creates...
+		 */
+		$this->writeInt(0);
+	}
+
+	/**
+	 * writeNumber writes the number code (0x00) and the numeric data to the output stream
+	 * All numbers passed through remoting are floats.
+	 * 
+	 * @param int $d The numeric data
+	 */
+	function writeNumber($d) {
+		$this->writeByte(0); // write the number code
+		$this->writeDouble(floatval($d)); // write  the number as a double
+	} 
+
+	/**
+	 * writeNull writes the null code (0x05) to the output stream
+	 */
+	function writeNull() {
+		$this->writeByte(5); // null is only a  0x05 flag
+	} 
+
+	/**
+	 * writeArray first deterines if the PHP array contains all numeric indexes
+	 * or a mix of keys.  Then it either writes the array code (0x0A) or the
+	 * object code (0x03) and then the associated data.
+	 * 
+	 * @param array $d The php array
+	 */
+	function writeArray($d) 
+	{
+		if($this->writeReferenceIfExists($d))
+		{
+			return;
+		}
+		
+		$numeric = array(); // holder to store the numeric keys
+		$string = array(); // holder to store the string keys
+		$len = count($d); // get the total number of entries for the array
+		$largestKey = -1;
+		foreach($d as $key => $data) { // loop over each element
+			if (is_int($key) && ($key >= 0)) { // make sure the keys are numeric
+				$numeric[$key] = $data; // The key is an index in an array
+				$largestKey = max($largestKey, $key);
+			} else {
+				$string[$key] = $data; // The key is a property of an object
+			} 
+		} 
+		$num_count = count($numeric); // get the number of numeric keys
+		$str_count = count($string); // get the number of string keys
+
+		if ( ($num_count > 0 && $str_count > 0) || 
+			 ($num_count > 0 && $largestKey != $num_count - 1)) { // this is a mixed array
+			
+			$this->writeByte(8); // write the mixed array code
+			$this->writeLong($num_count); // write  the count of items in the array
+			$this->writeObjectFromArray($numeric + $string); // write the numeric and string keys in the mixed array
+		} else if ($num_count > 0) { // this is just an array
+			
+			$num_count = count($numeric); // get the new count
+			
+			$this->writeByte(10); // write  the array code
+			$this->writeLong($num_count); // write  the count of items in the array
+			for($i = 0 ; $i < $num_count ; $i++) { // write all of the array elements
+				$this->writeData($numeric[$i]);
+			} 
+		} else if($str_count > 0) { // this is an object
+			$this->writeByte(3); // this is an  object so write the object code
+			$this->writeObjectFromArray($string); // write the object name/value pairs
+		} else { //Patch submitted by Jason Justman
+			
+			$this->writeByte(10); // make this  an array still
+			$this->writeInt(0); //  give it 0 elements
+			$this->writeInt(0); //  give it an element pad, this looks like a bug in Flash,
+											//but keeps the next alignment proper
+		}
+	}
+	
+	function writeReferenceIfExists($d)
+	{
+		if(count($this->amf0StoredObjects) >= MAX_STORED_OBJECTS)
+		{
+			return false;
+		}
+		if(is_array($d))
+		{
+			$this->amf0StoredObjects[] = "";
+			return false;
+		}
+		if(($key = patched_array_search($d, $this->amf0StoredObjects, true)) !== FALSE)
+		{
+			$this->writeReference($key);
+			return true;
+		}
+		else
+		{
+			$this->amf0StoredObjects[] = & $d;
+			return false;
+		}
+	}
+	
+	function writeReference($num)
+	{
+		$this->writeByte(0x07);
+		$this->writeInt($num);
+	}
+	
+	/**
+	 * Write a plain numeric array without anything fancy
+	 */
+	function writePlainArray($d)
+	{
+		if(!$this->writeReferenceIfExists($d))
+		{
+			$num_count = count($d);
+			$this->writeByte(10); // write  the mixed array code
+			$this->writeLong($num_count); // write  the count of items in the array
+			for($i = 0 ; $i < $num_count ; $i++) { // write all of the array elements
+				$this->writeData($d[$i]);
+			}
+		} 
+	}
+
+	/**
+	 * writeObject handles writing a php array with string or mixed keys.  It does
+	 * not write the object code as that is handled by the writeArray and this method
+	 * is shared with the CustomClass writer which doesn't use the object code.
+	 * 
+	 * @param array $d The php array with string keys
+	 */
+	function writeObjectFromArray($d) {
+		foreach($d as $key => $data) { // loop over each element
+			$this->writeUTF($key);  // write the name of the object
+			$this->writeData($data); // write the value of the object
+		} 
+		$this->writeInt(0); //  write the end object flag 0x00, 0x00, 0x09
+		$this->writeByte(9);
+	} 
+	
+	/**
+	 * writeObject handles writing a php array with string or mixed keys.  It does
+	 * not write the object code as that is handled by the writeArray and this method
+	 * is shared with the CustomClass writer which doesn't use the object code.
+	 * 
+	 * @param array $d The php array with string keys
+	 */
+	function writeAnonymousObject($d) {
+		if(!$this->writeReferenceIfExists($d))
+		{
+			$this->writeByte(3);
+			$objVars = (array) $d;
+			foreach($d as $key => $data) { // loop over each element
+				if($key[0] != "\0")
+				{
+					$this->writeUTF($key);  // write the name of the object
+					$this->writeData($data); // write the value of the object
+				}
+			} 
+			$this->writeInt(0); //  write the end object flag 0x00, 0x00, 0x09
+			$this->writeByte(9);
+		}
+	} 
+
+	/**
+	 * writePHPObject takes an instance of a class and writes the variables defined
+	 * in it to the output stream.
+	 * To accomplish this we just blanket grab all of the object vars with get_object_vars
+	 * 
+	 * @param object $d The object to serialize the properties
+	 */
+	function writeTypedObject($d) {
+		if($this->writeReferenceIfExists($d))
+		{
+			return;
+		}
+		
+		$this->writeByte(16); // write  the custom class code
+		$classname = $this->getClassName($d);
+		
+		$this->writeUTF($classname); // write the class name
+		if(AMFPHP_PHP5)
+		{
+			$objVars = $d;
+		}
+		else
+		{
+			$objVars = (array) $d;
+		}
+		foreach($objVars as $key => $data) { // loop over each element
+			if($key[0] != "\0")
+			{
+				$this->writeUTF($key);  // write the name of the object
+				$this->writeData($data); // write the value of the object
+			}
+		} 
+		$this->writeInt(0); //  write the end object flag 0x00, 0x00, 0x09
+		$this->writeByte(9);
+	} 
+
+	/**
+	 * writeRecordSet is the abstracted method to write a custom class recordset object.
+	 * Any recordset from any datasource can be written here, it just needs to be properly formatted
+	 * beforehand.
+	 *
+	 * This was unrolled with at the expense of readability for a 
+	 * 10 fold increase in speed in large recordsets
+	 * 
+	 * @param object $rs The formatted RecordSet object
+	 */
+	 
+	function writeRecordSet(&$rs) 
+	{
+		//Low-level everything here to make things faster
+		//This is the bottleneck of AMFPHP, hence the attention in making things faster
+		if($this->writeReferenceIfExists($rs))
+		{
+			return;
+		}
+		
+		$ob = "";
+		$data = $rs->rows;
+		
+		if($GLOBALS['amfphp']['encoding'] == 'amf0')
+		{
+			
+			$this->writeByte(16); // write  the custom class code
+			$this->writeUTF("RecordSet"); // write  the class name
+			$this->writeUTF("serverInfo");
+			
+			//Start writing inner object
+			$this->writeByte(3); // this is an  object so write the object code
+			
+			//Write total count
+			$this->writeUTF("totalCount");
+			$this->writeNumber($rs->getRowCount());
+			
+			//Write initial data
+			$this->writeUTF("initialData");
+			
+			//Inner numeric array
+			$colnames = $rs->columns;
+			
+			$num_count = count($rs->rows);
+			$this->writeByte(10); // write  the mixed array code
+			$this->writeLong($num_count); // write  the count of items in the array
+	
+			//Allow recordsets to create their own serialized data, which is faster
+			//since the recordset array is traversed only once
+			$numcols = count($colnames);
+			
+			$ob = "";
+			$be = $this->isBigEndian;
+			$fc = pack('N', $numcols);
+			
+			for($i = 0 ; $i < $num_count ; $i++) 
+			{ 
+				// write all of the array elements
+				$ob .= "\12" . $fc;
+
+				for($j = 0; $j < $numcols; $j++) { // write all of the array elements
+					
+					$d = $data[$i][$j];
+					if (is_string($d)) 
+					{ // type as string
+						$os = $this->rsCharsetHandler->transliterate($d);
+						//string flag, string length, and string
+						$ob .= "\2" . pack('n', strlen($os)) . $os;
+					}
+					elseif (is_float($d) || is_int($d)) 
+					{ // type as double
+						$ob .= "\0";
+						$b = pack('d', $d); // pack the bytes
+						if ($be) { // if we are a big-endian processor
+							$r = strrev($b);
+						} else { // add the bytes to the output
+							$r = $b;
+						} 
+						$ob .= $r;
+					} 
+					elseif (is_bool($d)) 
+					{ //type as bool
+						$ob .= "\1";
+						$ob .= pack('c', $d);
+					} 
+					elseif (is_null($d)) 
+					{ // null
+						$ob .= "\5";
+					} 
+				} 
+			}
+			$this->outBuffer .= $ob;
+	
+			//Write cursor
+			$this->writeUTF("cursor");
+			$this->writeNumber(1);
+			
+			//Write service name
+			$this->writeUTF("serviceName");
+			$this->writeString("PageAbleResult");
+			
+			//Write column names
+			$this->writeUTF("columnNames");
+			$this->writePlainArray($colnames, 'string');
+			
+			//Write version number
+			$this->writeUTF("version");
+			$this->writeNumber(1);
+			
+			//Write id
+			$this->writeUTF("id");
+			$this->writeString($rs->getID());
+			
+			//End inner serverInfo object
+			$this->writeInt(0); //  write the end object flag 0x00, 0x00, 0x09
+			$this->writeByte(9);
+			
+			//End outer recordset object
+			$this->writeInt(0); //  write the end object flag 0x00, 0x00, 0x09
+			$this->writeByte(9);
+			
+			$this->paging = -1;
+		}
+		else
+		{	
+			$numObjects= 0;
+			$this->writeAmf3ArrayCollectionPreamble();
+			
+			//Amf3 array code
+			$this->writeByte(0x09);
+			$numObjects++;
+			
+			$numRows = count($rs->rows);
+			$toPack = 2*$numRows + 1;
+			
+			//Write the number of rows
+			$this->writeAmf3Int($toPack);
+			
+			//No string keys in this array
+			$this->writeByte(0x01);
+			
+			$numCols = count($rs->columns);
+			
+			$columnStringOffsets = array();
+			if($numRows > 0)
+			{
+				$j = 0;
+				$colNames = array();
+				$rows = $rs->rows;
+				
+				foreach ($rows as $key => $line) {
+					
+					//Usually we don't use class defs in the serializer since we don't 
+					//have sealed objects in php, but for recordsets we do use them
+					//since they are well suited for what we have to do (the same keys
+					//across all objects)
+					if($key == 0)
+					{
+						$this->outBuffer .= "\12";
+						$this->writeAmf3Int($numCols << 4 | 3);
+						$this->outBuffer .= "\1";
+						foreach($rs->columns as $key => $val)
+						{
+							$this->writeAmf3String($val);
+						}
+						$defOffset = $this->getAmf3Int(
+							($this->storedDefinitions) << 2 | 1
+							);
+						$this->storedDefinitions++;
+					}
+					else
+					{
+						$this->outBuffer .= "\12" . $defOffset;
+					}
+					$numObjects++;
+					
+					for($i = 0; $i < $numCols; $i++)
+					{
+						//Write the col name
+						$value = $line[$i];
+						if(is_string($value))
+						{
+							$this->outBuffer .= "\6";
+							$value = $this->rsCharsetHandler->transliterate($value);
+							$this->writeAmf3String($value, true);
+						}
+						elseif(is_int($value)) 
+						{ //int
+							$this->writeAmf3Number($value);
+						} 
+						elseif(is_float($value))
+						{ //double
+							$this->outBuffer .= "\5";
+							$b = pack("d", $value); // pack the bytes
+							if ($this->isBigEndian) { // if we are a big-endian processor
+								$r = strrev($b);
+							} else { // add the bytes to the output
+								$r = $b;
+							} 
+							
+							$this->outBuffer .= $r;
+						}
+						elseif(is_bool($value))
+						{
+							$this->outBuffer .= $value ? "\3" : "\2";
+						}
+						else
+						{
+							$this->outBuffer .= "\1"; //null
+						}
+					}
+					//End object
+				}
+			}
+			
+			//Add fake objects to make sure the object counter still works
+			for($i = 0; $i < $numObjects; $i++)
+			{
+				$this->storedObjects[] = "";
+			}
+		}
+	}
+
+	/**
+	 * writeData checks to see if the type was declared and then either
+	 * auto negotiates the type or relies on the user defined type to
+	 * serialize the data into amf
+	 *
+	 * Note that autoNegotiateType was eliminated in order to tame the 
+	 * call stack which was getting huge and was causing leaks
+	 *
+	 * manualType allows the developer to explicitly set the type of
+	 * the returned data.  The returned data is validated for most of the
+	 * cases when possible.  Some datatypes like xml and date have to
+	 * be returned this way in order for the Flash client to correctly serialize them
+	 * 
+	 * recordsets appears top on the list because that will probably be the most
+	 * common hit in this method.  Followed by the
+	 * datatypes that have to be manually set.  Then the auto negotiatable types last.
+	 * The order may be changed for optimization.
+	 * 
+	 * @param mixed $d The data
+	 * @param string $type The optional type
+	 */
+	function writeData(& $d) {
+		if (is_int($d) || is_float($d)) 
+		{ // double
+			$this->writeNumber($d);
+			return;
+		} 
+		elseif (is_string($d)) 
+		{ // string
+			$this->writeString($d);
+			return;
+		} 
+		elseif (is_bool($d)) 
+		{ // boolean
+			$this->writeBoolean($d);
+			return;
+		} 
+		elseif (is_null($d)) 
+		{ // null
+			$this->writeNull();
+			return;
+		} 
+		elseif ($GLOBALS['amfphp']['encoding'] == 'amf3')
+		{
+			$this->writeByte(0x11);
+			$this->writeAmf3Data($d);
+			return;
+		}
+		elseif (is_array($d)) 
+		{ // array
+			$this->writeArray($d);
+			return;
+		} 
+		elseif (is_resource($d)) 
+		{ // resource
+			$type = get_resource_type($d);
+			list($type, $subtype) = $this->sanitizeType($type);
+		} 
+		elseif (is_object($d))
+		{
+			$className = strtolower(get_class($d));
+			if(array_key_exists($className, $this->resourceObjects))
+			{
+				$type = "__RECORDSET__";
+				$subtype = $this->resourceObjects[strtolower(get_class($d))];
+			}
+			else if(AMFPHP_PHP5 && $className == 'domdocument')
+			{
+				$this->writeXML($d->saveXml());
+				return;
+			}
+			else if(!AMFPHP_PHP5 && $className == 'domdocument')
+			{
+				$this->writeXML($d->dump_mem());
+				return;
+			}
+			elseif($className == "simplexmlelement")
+			{
+				$this->writeXML($d->asXML());
+				return;
+			}
+			else if($className == 'stdclass' && !isset($d->_explicitType))
+			{
+				$this->writeAnonymousObject($d);
+				return;
+			}
+			elseif(is_a($d, 'ArrayAccess') || is_a($d, 'ArrayObject'))
+			{
+				$this->writeArray($d);
+				return;
+			}
+			else
+			{
+				$this->writeTypedObject($d);
+				return;
+			}
+		}
+		else
+		{
+			$type = gettype($d);
+		}
+		
+		switch ($type) {
+			case "__RECORDSET__" :
+				$classname = $subtype . "Adapter"; // full class name
+				$includeFile = include_once(AMFPHP_BASE . "shared/adapters/" . $classname . ".php"); // try to load the recordset library from the sql folder
+				if (!$includeFile) {
+					trigger_error("The recordset filter class " . $classname . " was not found", E_USER_ERROR);
+				} 
+				$recordSet = new $classname($d); // returns formatted recordset
+				$this->writeRecordSet($recordSet); // writes the recordset formatted for Flash
+				break;
+			default: 
+				// non of the above so lets assume its a Custom Class thats defined in the client
+				$this->writeTypedObject($unsanitizedType, $d);
+				// trigger_error("Unsupported Datatype");
+				break;
+		} 
+	}
+	
+	/********************************************************************************
+	 *                             AMF3 related code
+	 *******************************************************************************/
+	
+	function writeAmf3Data(& $d)
+	{
+		if (is_int($d)) 
+		{ //int
+			$this->writeAmf3Number($d);
+			return;
+		} 
+		elseif(is_float($d))
+		{ //double
+			$this->outBuffer .= "\5";
+			$this->writeDouble($d);
+			return;
+		}
+		elseif (is_string($d)) 
+		{ // string
+			$this->outBuffer .= "\6";
+			$this->writeAmf3String($d);
+			return;
+		} 
+		elseif (is_bool($d)) 
+		{ // boolean
+			$this->writeAmf3Bool($d);
+			return;
+		} 
+		elseif (is_null($d)) 
+		{ // null
+			$this->writeAmf3Null();
+			return;
+		} 
+		elseif (is_array($d)) 
+		{ // array
+			$this->writeAmf3Array($d);
+			return;
+		} 
+		elseif (is_resource($d)) 
+		{ // resource
+			$type = get_resource_type($d);
+			list($type, $subtype) = $this->sanitizeType($type);
+		} 
+		elseif (is_object($d))
+		{
+			$className = strtolower(get_class($d));
+			if(array_key_exists($className, $this->resourceObjects))
+			{
+				$type = "__RECORDSET__";
+				$subtype = $this->resourceObjects[strtolower(get_class($d))];
+			}
+			else if(AMFPHP_PHP5 && $className == 'domdocument')
+			{
+				$this->writeAmf3Xml($d->saveXml());
+				return;
+			}
+			else if(!AMFPHP_PHP5 && $className == 'domdocument')
+			{
+				$this->writeAmf3Xml($d->dump_mem());
+				return;
+			}
+			elseif($className == "simplexmlelement")
+			{
+				$this->writeAmf3Xml($d->asXML());
+				return;
+			}
+			elseif($className == 'bytearray')
+			{
+				$this->writeAmf3ByteArray($d->data);
+				return;
+			}
+			elseif(is_a($d, 'ArrayAccess') || is_a($d, 'ArrayObject'))
+			{
+				$this->writeAmf3Array($d, true);
+				return;
+			}
+			else
+			{
+				$this->writeAmf3Object($d);
+				return;
+			}
+		}
+		else
+		{
+			$type = gettype($d);
+		}
+		
+		switch ($type) {
+			case "__RECORDSET__" :
+				$classname = $subtype . "Adapter"; // full class name
+				$includeFile = include_once(AMFPHP_BASE . "shared/adapters/" . $classname . ".php"); // try to load the recordset library from the sql folder
+				if (!$includeFile) {
+					trigger_error("The recordset filter class " . $classname . " was not found");
+				} 
+				$GLOBALS['amfphp']['stringOffset'] = count($this->storedStrings);
+				$recordSet = new $classname($d); // returns formatted recordset
+				
+				$this->writeRecordSet($recordSet); // writes the recordset formatted for Flash
+				break;
+			default: 
+				// non of the above so lets assume its a Custom Class thats defined in the client
+				//$this->writeTypedObject($unsanitizedType, $d);
+				trigger_error("Unsupported Datatype: " . $type);
+				break;
+		} 
+	}
+	
+	/**
+	 * Write an ArrayCollection
+	 */
+	function writeAmf3ArrayCollectionPreamble()
+	{
+		$this->writeByte(0x0a);
+		$this->writeByte(0x07);
+		$this->writeAmf3String("flex.messaging.io.ArrayCollection");
+		$this->storedDefinitions++;
+		$this->storedObjects[] = "";
+	}
+
+	function writeAmf3Null()
+	{
+		//Write the null code (0x1) to the output stream.
+		$this->outBuffer .= "\1";
+	}
+
+	function writeAmf3Bool($d)
+	{
+		$this->outBuffer .= $d ? "\3" : "\2";
+	}
+	
+	function writeAmf3Int($d)
+	{
+		//Sign contraction - the high order bit of the resulting value must match every bit removed from the number
+		//Clear 3 bits 
+		$d &= 0x1fffffff;
+		if($d < 0x80)
+		{
+			$this->outBuffer .= chr($d);
+		}
+		elseif($d < 0x4000)
+		{
+			$this->outBuffer .= chr($d >> 7 & 0x7f | 0x80) . chr($d & 0x7f);
+		}
+		elseif($d < 0x200000)
+		{
+			$this->outBuffer .= chr($d >> 14 & 0x7f | 0x80) . chr($d >> 7 & 0x7f | 0x80) . chr($d & 0x7f);
+		} 
+		else
+		{
+			$this->outBuffer .= chr($d >> 22 & 0x7f | 0x80) . chr($d >> 15 & 0x7f | 0x80) . 
+				   chr($d >> 8 & 0x7f | 0x80) . chr($d & 0xff);
+		}
+	}
+
+	function writeAmf3String($d, $raw = false)
+	{
+		if( $d == "" )
+		{
+			//Write 0x01 to specify the empty ctring
+			$this->outBuffer .= "\1";
+		}
+		else
+		{
+			if( !isset($this->storedStrings[$d]))
+			{
+				if(strlen($d) < 64)
+				{
+					$this->storedStrings[$d] = $this->encounteredStrings;
+				}
+				if(!$raw)
+				{
+					$d = $this->charsetHandler->transliterate($d);
+				}
+				
+				$handle = strlen($d);
+				$this->writeAmf3Int($handle*2 + 1);
+				$this->outBuffer .= $d;
+				$this->encounteredStrings++;
+				return $this->encounteredStrings - 1;
+			}
+			else
+			{
+				$key = $this->storedStrings[$d];
+				$handle = $key << 1;
+				$this->writeAmf3Int($handle);
+				return $key;
+			}
+		}
+	}
+
+	function writeAmf3Array($d, $arrayCollectionable = false)
+	{
+		//Circular referencing is disabled in arrays
+		//Because if the array contains only primitive values,
+		//Then === will say that the two arrays are strictly equal
+		//if they contain the same values, even if they are really distinct
+		//if(($key = patched_array_search($d, $this->storedObjects, TRUE)) === FALSE )
+		//{
+			if(count($this->storedObjects) < MAX_STORED_OBJECTS)
+			{
+				$this->storedObjects[] = & $d;
+			}
+			
+			$numeric = array(); // holder to store the numeric keys
+			$string = array(); // holder to store the string keys
+			$len = count($d); // get the total number of entries for the array
+			$largestKey = -1;
+			foreach($d as $key => $data) { // loop over each element
+				if (is_int($key) && ($key >= 0)) { // make sure the keys are numeric
+					$numeric[$key] = $data; // The key is an index in an array
+					$largestKey = max($largestKey, $key);
+				} else {
+					$string[$key] = $data; // The key is a property of an object
+				} 
+			} 
+			$num_count = count($numeric); // get the number of numeric keys
+			$str_count = count($string); // get the number of string keys
+
+			if (($str_count > 0 && $num_count == 0)  || 
+			    ($num_count > 0 && $largestKey != $num_count - 1)) { // this is a mixed array
+				$this->writeAmf3ObjectFromArray($numeric + $string); // write the numeric and string keys in the mixed array
+			} else { // this is just an array
+				if($arrayCollectionable)
+				{
+					$this->writeAmf3ArrayCollectionPreamble();
+				}
+				
+				$num_count = count($numeric);
+				
+				$this->outBuffer .= "\11";
+				$handle = $num_count * 2 + 1;
+				$this->writeAmf3Int($handle);
+				
+				foreach($string as $key => $val)
+				{
+					$this->writeAmf3String($key);
+					$this->writeAmf3Data($val);
+				}
+				$this->writeAmf3String(""); //End start hash
+				
+				for($i = 0; $i < $num_count; $i++)
+				{
+					$this->writeAmf3Data($numeric[$i]);
+				}
+			}
+		//}
+		//else
+		//{
+		//	$handle = $key << 1;
+		//	$this->outBuffer .= "\11";
+		//	$this->writeAmf3Int($handle);
+		//}
+	}
+	
+	function writeAmf3ObjectFromArray($d)
+	{
+		//Type this as a dynamic object
+		$this->outBuffer .= "\12\13\1";
+		
+		foreach($d as $key => $val)
+		{
+			$this->writeAmf3String($key);
+			$this->writeAmf3Data($val);
+		}
+		//Now we close the open object
+		$this->outBuffer .= "\1";
+	}
+
+	/*
+	public void WriteAMF3DateTime(DateTime value)
+	{
+		if( !_objectReferences.Contains(value) )
+		{
+			_objectReferences.Add(value, _objectReferences.Count);
+			int handle = 1;
+			WriteAMF3IntegerData(handle);
+
+			// Write date (milliseconds from 1970).
+			DateTime timeStart = new DateTime(1970, 1, 1, 0, 0, 0);
+
+			string timezoneCompensation = System.Configuration.ConfigurationSettings.AppSettings["timezoneCompensation"];
+			if( timezoneCompensation != null && ( timezoneCompensation.ToLower() == "auto" ) )
+			{
+				value = value.ToUniversalTime();
+			}
+			
+			TimeSpan span = value.Subtract(timeStart);
+			long milliSeconds = (long)span.TotalMilliseconds;
+			long date = BitConverter.DoubleToInt64Bits((double)milliSeconds);
+			this.WriteLong(date);
+		}
+		else
+		{
+			int handle = (int)_objectReferences[value];
+			handle = handle << 1;
+			WriteAMF3IntegerData(handle);
+		}
+	}
+	*/
+	
+	function getAmf3Int($d)
+	{
+		$d &= 0x1fffffff;
+		if($d < 0x80)
+		{
+			return chr($d);
+		}
+		elseif($d < 0x4000)
+		{
+			return chr($d >> 7 & 0x7f | 0x80) . chr($d & 0x7f);
+		}
+		elseif($d < 0x200000)
+		{
+			return chr($d >> 14 & 0x7f | 0x80) . chr($d >> 7 & 0x7f | 0x80) . chr($d & 0x7f);
+		} 
+		else
+		{
+			return chr($d >> 22 & 0x7f | 0x80) . chr($d >> 15 & 0x7f | 0x80) . 
+				   chr($d >> 8 & 0x7f | 0x80) . chr($d & 0xff);
+		}
+	}
+
+	function writeAmf3Number($d)
+	{
+		if($d >= -268435456 && $d <= 268435455)//check valid range for 29bits
+		{
+			$this->outBuffer .= "\4";
+			$this->writeAmf3Int($d);
+		}
+		else
+		{
+			//overflow condition would occur upon int conversion
+			$this->outBuffer .= "\5";
+			$this->writeDouble($d);
+		}
+	}
+
+	function writeAmf3Xml($d)
+	{
+		$d = preg_replace('/\>(\n|\r|\r\n| |\t)*\<',trim($d));
+		$this->writeByte(0x07);
+		$this->writeAmf3String($d);
+	}
+	
+	function writeAmf3ByteArray($d)
+	{
+		$this->writeByte(0x0C);
+		$this->writeAmf3String($d, true);
+	}
+
+	function writeAmf3Object($d)
+	{
+		//Write the object tag
+		$this->outBuffer .= "\12";
+		if( ($key = patched_array_search($d, $this->storedObjects, TRUE)) === FALSE && $key === FALSE)
+		{
+			if(count($this->storedObjects) < MAX_STORED_OBJECTS)
+			{
+				$this->storedObjects[] = & $d;
+			}
+			
+			$this->storedDefinitions++;
+
+			//Type the object as an array
+			if(AMFPHP_PHP5)
+			{
+				$obj = $d;
+			}
+			else
+			{
+				$obj = (array) $d;
+			}
+			$realObj = array();
+			foreach($obj as $key => $val)
+			{
+				if($key[0] != "\0" && $key != '_explicitType') //Don't show private members
+				{
+					$realObj[$key] = $val;
+				}
+			}
+			
+			//Type this as a dynamic object
+			$this->outBuffer .= "\13";
+			
+			$classname = $this->getClassName($d);
+			
+			$this->writeAmf3String($classname);
+			
+			foreach($realObj as $key => $val)
+			{
+				$this->writeAmf3String($key);
+				$this->writeAmf3Data($val);
+			}
+			//Now we close the open object
+			$this->outBuffer .= "\1";
+		}
+		else
+		{
+			$handle = $key << 1;
+			$this->writeAmf3Int($handle);
+		}
+	}
+}
+
+
+
+?>
\ No newline at end of file
diff --git a/core/amf/readme.txt b/core/amf/readme.txt
new file mode 100755
index 0000000..7658f0a
--- /dev/null
+++ b/core/amf/readme.txt
@@ -0,0 +1,3 @@
+The files located here are part of the amfphp core functionality. 
+
+Unless you want to patch or add functionality to amfphp, you probably don't want to play with these files.
\ No newline at end of file
diff --git a/core/amf/util/AMFObject.php b/core/amf/util/AMFObject.php
new file mode 100755
index 0000000..f7d7ebf
--- /dev/null
+++ b/core/amf/util/AMFObject.php
@@ -0,0 +1,207 @@
+rawData = $rawData;
+		$this->outputStream = "";
+		$this->_incomingHeaders = array();
+		$this->_outgoingHeaders = array();
+		$this->_bodys = array();
+		$this->_headerTable = array();
+	} 
+
+	/**
+	 * addHeader places a new header into the pool of headers.
+	 * 
+	 * Each header has 3 properties, they header key, the required flag
+	 * and the data associated with the header.
+	 * 
+	 * @param object $header The AMFHeader object to add to the list
+	 */
+	function addHeader(&$header) {
+		//$len = array_push($this->_incomingHeaders, $header);
+		$this->_incomingHeaders[] = $header;
+		$name = $header->name;
+		$this->_headerTable[$name] = $header;
+	} 
+
+	/**
+	 * addOutgoingHeader places a new header into the pool of outbound headers.
+	 * 
+	 * Each header has 3 properties, they header key, the required flag
+	 * and the data associated with the header.
+	 * 
+	 * @param object $header The AMFHeader object to add to the list
+	 */
+	function addOutgoingHeader(&$header) {
+		//$len = array_push($this->_outgoingHeaders, $header);
+		$this->_outgoingHeaders[] = $header;
+	} 
+
+	/**
+	 * getHeader returns a header record for a given key
+	 * 
+	 * @param string $key The header key
+	 * @return mixed The header record
+	 */
+	function getHeader ($key) {
+		if (isset($this->_headerTable[$key])) {
+			return $this->_headerTable[$key];
+		} 
+		return false;
+	} 
+
+	/**
+	 * Gets the number of headers for this amf packet
+	 * 
+	 * @return int The header count
+	 */
+	function numHeader() {
+		return count($this->_incomingHeaders);
+	} 
+
+	/**
+	 * Gets the number of outgoing headers for this amf packet
+	 * 
+	 * @return int The header count
+	 */
+	function numOutgoingHeader() {
+		return count($this->_outgoingHeaders);
+	} 
+
+	/**
+	 * Get the header at the specified position.
+	 * 
+	 * If you pass an id this method will return the header
+	 * located at that id, otherwise it will return the first header
+	 * 
+	 * @param int $id Optional id field
+	 * @return array The header object
+	 */
+	function &getHeaderAt($id = 0) {
+		return $this->_incomingHeaders[$id];
+	} 
+
+	/**
+	 * Get the header at the specified position from the outgoing header queue.
+	 * 
+	 * If you pass an id this method will return the header
+	 * located at that id, otherwise it will return the first header
+	 * 
+	 * @param int $id Optional id field
+	 * @return array The header object
+	 */
+	function &getOutgoingHeaderAt($id = 0) {
+		return $this->_outgoingHeaders[$id];
+	} 
+
+	/**
+	 * addBody has the job of adding a new body element to the bodys array.
+	 * 
+	 * @param string $t The target URI
+	 * @param string $r The response URI
+	 * @param mixed $v The value of the object
+	 * @param string $ty The type of the results
+	 * @param int $ps The pagesize of a recordset
+	 */
+	function addBody($body) {
+		$this->_bodys[] = $body;
+	} 
+
+	/**
+	 * addBodyAt provides an interface to push a body element to a desired
+	 * position in the array.
+	 * 
+	 * @param int $pos The position to add the body element
+	 * @param AMFBody $body The body element to add
+	 */
+	function addBodyAt($pos, $body) {
+		array_splice($this->_bodys, $pos, 0, array($body)); // splice the new body into the array
+	} 
+	
+	/**
+	 * removeBodyAt provides an interface to remove a body element to a desired
+	 * position in the array.
+	 * 
+	 * @param int $pos The position to add the body element
+	 * @param AMFBody $body The body element to add
+	 */
+	function removeBodyAt($pos) {
+		array_splice($this->_bodys, $pos, 1); // splice the new body into the array
+	} 
+
+	/**
+	 * numBody returns the total number of body elements.  There is one body
+	 * element for each method call.
+	 * 
+	 * @return int The number of body elements
+	 */
+	function numBody() {
+		return count($this->_bodys);
+	} 
+
+	/**
+	 * getBodyAt returns the current body element the specified position.
+	 * 
+	 * If a integer is passed this method will return the element at the given position.
+	 * Otherwise the first element will be returned.
+	 * 
+	 * @param int $id The id of the body element desired
+	 * @return array The body element
+	 */
+	function &getBodyAt($id = 0) {
+		return $this->_bodys[$id];
+	} 
+} 
+
+?>
\ No newline at end of file
diff --git a/core/amf/util/DateWrapper.php b/core/amf/util/DateWrapper.php
new file mode 100755
index 0000000..63e6f9e
--- /dev/null
+++ b/core/amf/util/DateWrapper.php
@@ -0,0 +1,83 @@
+_date = $input/1000;
+		}
+		else
+		{
+			$this->_date = time();
+		}
+	}
+	
+	/**
+	 * Get date according to client timezone
+	 */
+	function getClientDate()
+	{
+		return $this->_date + DateWrapper::getTimezone();
+	}
+	
+	/**
+	 * Get date according to server timezone
+	 */
+	function getServerDate()
+	{
+		return ($this->_date + date("Z"));
+	}
+	
+	/**
+	 * Get raw date
+	 */
+	function getRawDate()
+	{
+		return $this->_date;
+	}
+	
+	/**
+	 * Set utc date
+	 */
+	function setDate($input)
+	{
+		$this->_date = $input;
+	}
+	
+	/**
+	 * Get timezone
+	 */
+	function getTimezone($val=NULL)
+	{
+		static $timezone = 0;
+		if($val != NULL)
+		{
+			$timezone = $val;
+		}
+		return $timezone;
+	}
+	
+	/**
+	 * Set timezone
+	 */
+	function setTimezone($val=0){
+		return DateWrapper::getTimezone($val);
+	}
+} 
+
+?>
\ No newline at end of file
diff --git a/core/amf/util/DescribeService.php b/core/amf/util/DescribeService.php
new file mode 100755
index 0000000..6a0a370
--- /dev/null
+++ b/core/amf/util/DescribeService.php
@@ -0,0 +1,74 @@
+methodTable as $key => $value) {
+			if ($value["access"] = "remote")    {
+				$args = array();
+				if(is_array($value["arguments"]) && count($value["arguments"]) >= 1)
+				{
+					foreach($value["arguments"] as $key2 => $arg)
+					{
+						if(is_array($arg))
+						{
+						$args[] = array("name" => $key2,
+								  "required" => $arg['required'] ? 'true' : 'false',
+								  "type" => $arg['type'],
+								  "description" => $arg['description']
+								  );
+						}
+						else
+						{
+						$args[] = array("name" => $arg,
+								  "required" => "true",
+								  "type" => "undefined");
+						}
+					}
+				}
+				
+				if( !isset( $value["returns"] ) )
+				{
+					$returns = 'undefined';
+				}
+				else
+				{
+					$returns = $value["returns"];
+				}
+				
+				$description["functions"][] = array(
+					"description" => $value["description"],
+					"name" => $key,
+					"version" => "1.0",
+					"returns" => $returns,
+					"arguments" => $args
+				);
+			}
+		}
+		return $description;
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/core/amf/util/PageAbleResult.php b/core/amf/util/PageAbleResult.php
new file mode 100755
index 0000000..d1c0af0
--- /dev/null
+++ b/core/amf/util/PageAbleResult.php
@@ -0,0 +1,84 @@
+methodTable = array("getRecords" => array("access" => "remote",
+				"returns" => "__RECORDSETPAGE__"
+				),
+			"release" => array("access" => "remote"
+				)
+			);
+	} 
+	/**
+	 * Collects the page of the recordset from the session and returns it along
+	 * with the cursor position of the first record.
+	 * 
+	 * @param string $id The session id
+	 * @param int $c The cursor position
+	 * @param int $ps The page size
+	 * @return array Contains the cursor position of the first record and the page data
+	 */
+	function getRecords($id, $c, $ps) {
+		$keys = explode("=", $id);
+		$currset = intval($keys[1]);
+		session_id($keys[0]);
+		session_start();
+		$pageData = array();
+		$pageData['Cursor'] = $c;
+		$pageData['Page'] = array_slice($_SESSION['amfphp_recordsets'][$currset]['data'], $c - 1, $ps);
+
+		for($i = 0; $i < $ps; $i++)
+		{
+			$_SESSION['amfphp_recordsets'][$currset]['indexes'][$c + $i] = true;
+		}
+		return $pageData;
+	} 
+	/**
+	 * Unsets the recordset data from the session
+	 * Flash, for some reason does not give back the recordid, so it's  difficult to see
+	 * what exactly is going on, this is why we store sent data in another session var
+	 *
+	 */
+	function release() {
+		foreach($_SESSION['amfphp_recordsets'] as $key => $value)
+		{
+			$found = false;
+			foreach($value['indexes'] as $recordid => $recordsent)
+			{
+				if(!$recordsent)
+				{
+					$found = true;
+					break;
+				}
+			}
+			if(!$found)
+			{
+				//Release recordset
+				unset($_SESSION['amfphp_recordsets'][$key]);
+			}
+		}
+		return;
+	} 
+} 
+
+?>
\ No newline at end of file
diff --git a/core/amf/util/TraceHeader.php b/core/amf/util/TraceHeader.php
new file mode 100755
index 0000000..b0b19bc
--- /dev/null
+++ b/core/amf/util/TraceHeader.php
@@ -0,0 +1,38 @@
+EventType = "trace";
+		$this->Time = time();
+		$this->Source = "Server";
+		$this->Date = array(date("D M j G:i:s T O Y"));
+		$this->messages = $traceStack;
+	} 
+} 
+
+class ProfilingHeader {
+	function ProfilingHeader() {
+		global $amfphp;
+		$this->EventType = "profiling";
+		
+		$this->includeTime = (int) ($amfphp['includeTime']*1000);
+		$this->decodeTime = (int) ($amfphp['decodeTime']*1000);
+		$this->callTime = (int) ($amfphp['callTime']*1000);
+		$this->totalTime = -268435457;
+		$this->frameworkTime = ((int) ($amfphp['totalTime']*1000)) 
+							- $this->includeTime
+							- $this->decodeTime
+							- $this->callTime;
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/amf/util/WrapperClasses.php b/core/amf/util/WrapperClasses.php
new file mode 100755
index 0000000..0a605a3
--- /dev/null
+++ b/core/amf/util/WrapperClasses.php
@@ -0,0 +1,87 @@
+data = $data;
+	}
+}
+
+class RecordSet
+{
+	var $data;
+	
+	function RecordSet($data)
+	{
+		$this->data = $data;
+	}
+}
+
+
+class PageableRecordSet
+{
+	var $data;
+	var $limit;
+	
+	function PageableRecordSet($data, $limit = 15)
+	{
+		$this->data = $data;
+		$this->limit = $limit;
+	}
+}
+
+class AcknowledgeMessage
+{
+	var $_explicitType = "flex.messaging.messages.AcknowledgeMessage";
+	
+	function AcknowledgeMessage($messageId = NULL, $clientId = NULL)
+	{
+	    $this->messageId = $this->generateRandomId();
+	    $this->clientId = $clientId != NULL ? $clientId : $this->generateRandomId();
+	    $this->destination = null;
+	    $this->body = null;
+	    $this->timeToLive = 0;
+	    $this->timestamp = (int) (time() . '00');
+	    $this->headers = new stdClass();
+	    $this->correlationId = $messageId;	
+	}
+	
+	function generateRandomId()
+	{
+	   // version 4 UUID
+	   return sprintf(
+	       '%08X-%04X-%04X-%02X%02X-%012X',
+	       mt_rand(),
+	       mt_rand(0, 65535),
+	       bindec(substr_replace(
+	           sprintf('%016b', mt_rand(0, 65535)), '0100', 11, 4)
+	       ),
+	       bindec(substr_replace(sprintf('%08b', mt_rand(0, 255)), '01', 5, 2)),
+	       mt_rand(0, 255),
+	       mt_rand()
+	   );
+	}
+}
+
+class CommandMessage
+{
+	var $_explicitType = 'flex.messaging.messages.CommandMessage';
+}
+
+class RemotingMessage
+{
+	var $_explicitType = 'flex.messaging.messages.RemotingMessage';
+}
+
+class ErrorMessage
+{
+	var $_explicitType = "flex.messaging.messages.ErrorMessage";
+	var $correlationId;
+	var $faultCode;
+	var $faultDetail;
+	var $faultString;
+}
+
+?>
\ No newline at end of file
diff --git a/core/json/app/Actions.php b/core/json/app/Actions.php
new file mode 100755
index 0000000..26e438f
--- /dev/null
+++ b/core/json/app/Actions.php
@@ -0,0 +1,119 @@
+getValue();
+	$target = $args[0];
+	
+	$baseClassPath = $GLOBALS['amfphp']['classPath'];
+	
+	$lpos = strrpos($target, '.');
+	
+	$methodname = substr($target, $lpos + 1);
+	$trunced = substr($target, 0, $lpos);
+	$lpos = strrpos($trunced, ".");
+	if ($lpos === false) {
+		$classname = $trunced;
+		$uriclasspath = $trunced . ".php";
+		$classpath = $baseClassPath . $trunced . ".php";
+	} else {
+		$classname = substr($trunced, $lpos + 1);
+		$classpath = $baseClassPath . str_replace(".", "/", $trunced) . ".php"; // removed to strip the basecp out of the equation here
+		$uriclasspath = str_replace(".", "/", $trunced) . ".php"; // removed to strip the basecp out of the equation here
+	} 
+	
+	$body->methodName = $methodname;
+	$body->className = $classname;
+	$body->classPath = $classpath;
+	$body->uriClassPath = $uriclasspath;
+	
+	//Now deserialize the arguments
+	array_shift($args);
+	
+	$actualArgs = array();
+	
+	foreach($args as $key => $value)
+	{
+		//Look at the value to see if it is JSON-encoded
+		$value = urldecode($value);
+		if($value != "")
+		{
+			if($value[0] != '[' && $value[0] != '{' && $value != "null" && $value != "false" && $value != "true")
+			{
+				//check to see if it is a number
+				$char1 = ord($value[0]);
+				if($char1 >= 0x30 && $char1 <= 0x39)
+				{
+					//Then this is a number
+					$value = json_decode($value, true);
+				} //Else leave value as is
+			}
+			else
+			{
+				$value = json_decode($value, true);
+			}
+		}
+		$actualArgs[] = $value;
+	}
+	
+	$body->setValue($actualArgs);
+}
+
+function executionAction(& $body)
+{
+	$classConstruct = &$body->getClassConstruct();
+	$methodName = $body->methodName;
+	$args = $body->getValue();
+	
+	$output = Executive::doMethodCall($body, &$classConstruct, $methodName, $args);
+	
+	if($output !== "__amfphp_error")
+	{
+		$body->setResults($output);
+	}
+}
+
+
+function serializationAction(& $body)
+{
+	//Take the raw response
+	$rawResponse = & $body->getResults();
+	
+	adapterMap($rawResponse);
+	
+	//Now serialize it
+	$encodedResponse = json_encode($rawResponse);
+	
+	if(count(NetDebug::getTraceStack()) > 0)
+	{
+		$trace = "/*" . implode("\n", NetDebug::getTraceStack()) . "*/";
+		$encodedResponse = $trace . "\n" . $encodedResponse;
+	}
+	
+	$body->setResults($encodedResponse);
+}
+
+if(!function_exists("json_encode"))
+{
+	include_once(AMFPHP_BASE . "shared/util/JSON.php");
+	
+	function json_encode($val)
+	{
+		$json = new Services_JSON();
+		return $json->encode($val);
+	}
+	
+	function json_decode($val, $asAssoc = FALSE)
+	{
+		if($asAssoc)
+		{
+			$json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
+		}
+		else
+		{
+			$json = new Services_JSON();
+		}
+		return $json->decode($val);
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/json/app/Gateway.php b/core/json/app/Gateway.php
new file mode 100755
index 0000000..2f49fe7
--- /dev/null
+++ b/core/json/app/Gateway.php
@@ -0,0 +1,48 @@
+setValue($rawArgs);
+		return $body;
+	}
+	
+	/**
+	 * Create the chain of actions
+	 */
+	function registerActionChain()
+	{
+		$this->actions['deserialization'] = 'deserializationAction';
+		$this->actions['classLoader'] = 'classLoaderAction';
+		$this->actions['security'] = 'securityAction';
+		$this->actions['exec'] = 'executionAction';
+		$this->actions['serialization'] = 'serializationAction';
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/RecordSetAdapter.php b/core/shared/adapters/RecordSetAdapter.php
new file mode 100755
index 0000000..b07da32
--- /dev/null
+++ b/core/shared/adapters/RecordSetAdapter.php
@@ -0,0 +1,63 @@
+_resultResource = $d;
+		$this->_charsetHandler = new CharsetHandler('sqltophp');
+		$this->_directCharsetHandler = new CharsetHandler('sqltoflash');
+		$this->isBigEndian = AMFPHP_BIG_ENDIAN;
+	} 
+
+	/**
+	 * getter for the number of rows
+	 * 
+	 * @return int The number of rows
+	 */
+	function getRowCount () {
+		if($this->numRows == -1)
+		{
+			$this->numRows = count($this->rows);
+		}
+		return $this->numRows;
+	} 
+	
+	function getID() {
+		return md5(microtime());
+	}
+} 
+
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/adodbAdapter.php b/core/shared/adapters/adodbAdapter.php
new file mode 100755
index 0000000..dcff29c
--- /dev/null
+++ b/core/shared/adapters/adodbAdapter.php
@@ -0,0 +1,39 @@
+FieldCount();	// grab	the	number of fields
+		
+		for($i = 0;	$i < $fieldcount; $i++)	{ // loop over all of the fields
+			$fld = $d->FetchField($i);
+			$this->columns[] = $fld->name;
+		}
+		
+		$d->MoveFirst();
+		$this->rows = $d->GetArray();
+	} 
+} 
+
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/doctrineAdapter.php b/core/shared/adapters/doctrineAdapter.php
new file mode 100755
index 0000000..242c559
--- /dev/null
+++ b/core/shared/adapters/doctrineAdapter.php
@@ -0,0 +1,39 @@
+ 0)
+		{
+			$firstRow = true;
+			foreach($d as $row)
+			{
+				$this->rows[] = array_values($row->toArray());
+				if($firstRow)
+				{
+					$this->columns = array_keys($row->toArray());
+					$firstRow = false;
+				}
+			}
+		}
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/fbsqlAdapter.php b/core/shared/adapters/fbsqlAdapter.php
new file mode 100755
index 0000000..18a06f9
--- /dev/null
+++ b/core/shared/adapters/fbsqlAdapter.php
@@ -0,0 +1,43 @@
+columns[] = fbsql_field_name($d, $i);
+		} 
+		
+		if(fbsql_num_rows($d) > 0)
+		{
+			fbsql_data_seek($d, 0); 
+			while ($line = fbsql_fetch_row($d)) {
+				$this->rows[] = $line;
+			}
+		}
+	} 
+} 
+
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/informixAdapter.php b/core/shared/adapters/informixAdapter.php
new file mode 100755
index 0000000..322c91a
--- /dev/null
+++ b/core/shared/adapters/informixAdapter.php
@@ -0,0 +1,47 @@
+columns[$i] = key($properties);
+			next($properties);
+		}
+		
+		if(ifx_num_rows($d) > 0)
+		{
+			$line = ifx_fetch_row($d,"FIRST");
+			do 
+			{
+				$this->rows[] = $line;
+			} while ($line = ifx_fetch_row($d,"NEXT") );
+		}
+	}
+}
+?> 
\ No newline at end of file
diff --git a/core/shared/adapters/mssqlAdapter.php b/core/shared/adapters/mssqlAdapter.php
new file mode 100755
index 0000000..864750e
--- /dev/null
+++ b/core/shared/adapters/mssqlAdapter.php
@@ -0,0 +1,41 @@
+columnNames[] = mssql_field_name($d, $i);
+		} 
+		
+		if(mssql_num_rows($d) > 0)
+		{
+			mssql_data_seek($d, 0);
+			while ($line = mssql_fetch_row($d)) {
+				$this->rows[] = $line;
+			}
+		}
+	} 
+} 
+
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/mysqlAdapter.php b/core/shared/adapters/mysqlAdapter.php
new file mode 100755
index 0000000..d95e8e1
--- /dev/null
+++ b/core/shared/adapters/mysqlAdapter.php
@@ -0,0 +1,49 @@
+columns[] = mysql_field_name($d, $i);
+			$type = mysql_field_type($d, $i);
+			if(in_array($type, array('int', 'real', 'year')))
+			{
+				$intFields[] = $i;
+			}
+		}
+		
+		while($row = mysql_fetch_row($d))
+		{
+			foreach($intFields as $key => $val)
+			{
+				$row[$val] = (float) $row[$val];
+			}
+			$this->rows[] = $row;
+		}
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/mysqliAdapter.php b/core/shared/adapters/mysqliAdapter.php
new file mode 100755
index 0000000..812d103
--- /dev/null
+++ b/core/shared/adapters/mysqliAdapter.php
@@ -0,0 +1,41 @@
+columns[] = $field->name;
+		}
+		
+		if(mysqli_num_rows($d) > 0)
+		{
+			mysqli_data_seek($d, 0); 
+			while ($line = mysqli_fetch_row($d)) {
+				$this->rows[] = $line;
+			}
+		}
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/mysqliobjectAdapter.php b/core/shared/adapters/mysqliobjectAdapter.php
new file mode 100755
index 0000000..d2bf2db
--- /dev/null
+++ b/core/shared/adapters/mysqliobjectAdapter.php
@@ -0,0 +1,41 @@
+fetch_field())
+		{   
+			$this->columns[] = $field->name;
+		}
+		
+		if($d->num_rows > 0)
+		{
+			$d->data_seek(0); 
+			while ($line = $d->fetch_row()) {
+				$this->rows[] = $line;
+			}
+		}
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/oci8Adapter.php b/core/shared/adapters/oci8Adapter.php
new file mode 100755
index 0000000..e6825c4
--- /dev/null
+++ b/core/shared/adapters/oci8Adapter.php
@@ -0,0 +1,37 @@
+columnNames[] = ocicolumnname($d, $j+1);
+		}
+		
+		$i = 0;
+		while ( OCIFetchInto($d,$line,OCI_NUM+OCI_RETURN_LOBS+OCI_RETURN_NULLS)) {
+			$this->rows[] = $line;
+		} 
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/odbcAdapter.php b/core/shared/adapters/odbcAdapter.php
new file mode 100755
index 0000000..24d3828
--- /dev/null
+++ b/core/shared/adapters/odbcAdapter.php
@@ -0,0 +1,44 @@
+columns[] = odbc_field_name($d, $i + 1);
+		} 
+		
+		if(odbc_num_rows($d) > 0)
+		{
+			$line = odbc_fetch_row($d, 0);
+			do {
+				$this->rows[] = $line;
+			} while ($line = odbc_fetch_row($d));
+		}
+	} 
+} 
+
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/pdoAdapter.php b/core/shared/adapters/pdoAdapter.php
new file mode 100755
index 0000000..0647579
--- /dev/null
+++ b/core/shared/adapters/pdoAdapter.php
@@ -0,0 +1,49 @@
+fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_ABS, 0);
+		if($line != null)
+		{
+			$colNum = 0;
+			$firstLine = array();
+			foreach($line as $k => $v)
+			{
+				$this->columns[$colNum] = $k;
+				$firstLine[] = $v;
+				$colNum++;
+			}
+			
+			$lastLines = $d->fetchAll(PDO::FETCH_NUM);
+			if($lastLines == NULL)
+			{
+				$this->rows = array($firstLine);
+			}
+			else
+			{
+				array_unshift($lastLines, $firstLine);
+				$this->rows = $lastLines;
+			}
+		}
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/peardbAdapter.php b/core/shared/adapters/peardbAdapter.php
new file mode 100755
index 0000000..e505cae
--- /dev/null
+++ b/core/shared/adapters/peardbAdapter.php
@@ -0,0 +1,56 @@
+numCols();
+		
+		$intFields = array();
+		$info = $d->dbh->tableInfo($d);
+		for($i = 0; $i < $fieldcount; $i++) {
+			$this->columnNames[$i] = $this->_charsetHandler->transliterate($info[$i]['name']);
+			
+			$type = $info[$i]['type'];
+			if(in_array($type, array('int', 'real', 'year')))
+			{
+				$intFields[] = $i;
+			}
+		}
+		
+		if($d->numRows() > 0)
+		{
+			$line = $d->fetchRow(DB_FETCHMODE_ORDERED, 0);
+			do {
+				foreach($intFields as $key => $val)
+				{
+					$line[$val] = (float) $line[$val];
+				}
+				$this->rows[] = $line;
+			} while ($line = $d->fetchRow(DB_FETCHMODE_ORDERED, $rows));
+		}
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/pgsqlAdapter.php b/core/shared/adapters/pgsqlAdapter.php
new file mode 100755
index 0000000..9be3d8a
--- /dev/null
+++ b/core/shared/adapters/pgsqlAdapter.php
@@ -0,0 +1,46 @@
+columns[] = pg_field_name($d, $i);
+		}
+		
+		if(pg_num_rows($d) > 0)
+		{
+			pg_result_seek($d, 0);
+			while($line = pg_fetch_row($d)) {
+				$this->rows[] = $line;
+			}
+		}
+	} 
+} 
+
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/plainrecordsetAdapter.php b/core/shared/adapters/plainrecordsetAdapter.php
new file mode 100755
index 0000000..49da450
--- /dev/null
+++ b/core/shared/adapters/plainrecordsetAdapter.php
@@ -0,0 +1,47 @@
+data;
+		
+		parent::RecordSetAdapter($d);
+		
+		if(count($d) > 0)
+		{
+			$columns = array_keys($d[0]);
+		}
+		
+		$this->columns = $columns;
+		
+		foreach($d as $key => $val)
+		{
+			$row = array();
+			foreach($columns as $key2 => $val2)
+			{
+				$row[] = $val[$val2];
+			}
+			$this->rows[] = $row;
+		}
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/sqliteAdapter.php b/core/shared/adapters/sqliteAdapter.php
new file mode 100755
index 0000000..afe6f3c
--- /dev/null
+++ b/core/shared/adapters/sqliteAdapter.php
@@ -0,0 +1,50 @@
+columns[] = sqlite_field_name($d, $i);
+		}
+		
+		if(sqlite_num_rows($d) > 0)
+		{
+			$this->rows = sqlite_fetch_all($d, SQLITE_NUM);
+		}
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/sqliteobjectAdapter.php b/core/shared/adapters/sqliteobjectAdapter.php
new file mode 100755
index 0000000..9c6876f
--- /dev/null
+++ b/core/shared/adapters/sqliteobjectAdapter.php
@@ -0,0 +1,50 @@
+numFields();
+		
+		// loop over all of the fields
+		for($i=0; $i<$fieldcount; $i++)  {
+			// decode each field name ready for encoding when it goes through serialization
+			// and save each field name into the array
+			$this->columns[] = $d->fieldName($i);
+		}
+		
+		if($d->numRows() > 0)
+		{
+			$this->rows = $d->fetchAll(SQLITE_NUM);
+		}
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/zendrowAdapter.php b/core/shared/adapters/zendrowAdapter.php
new file mode 100755
index 0000000..0fccfe3
--- /dev/null
+++ b/core/shared/adapters/zendrowAdapter.php
@@ -0,0 +1,29 @@
+toArray();
+		$this->columns = array_keys($val);
+		$this->rows[] = array_values($val);
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/adapters/zendrowsetAdapter.php b/core/shared/adapters/zendrowsetAdapter.php
new file mode 100755
index 0000000..f51787d
--- /dev/null
+++ b/core/shared/adapters/zendrowsetAdapter.php
@@ -0,0 +1,41 @@
+count() > 0)
+		{
+			$d->rewind();
+			$firstRow = $d->current()->toArray();
+			
+			$this->columns = array_keys($firstRow);
+			
+			//Note: foreach resets array iterator pointer
+			
+			foreach($d as $row)
+			{
+				$this->rows[] = array_values($row->toArray());
+			}
+		}
+	}
+}
+?
+>
\ No newline at end of file
diff --git a/core/shared/app/BasicActions.php b/core/shared/app/BasicActions.php
new file mode 100755
index 0000000..a9d9b64
--- /dev/null
+++ b/core/shared/app/BasicActions.php
@@ -0,0 +1,183 @@
+noExec)
+	{ 
+		// change to the gateway.php script directory
+		// now change to the directory of the classpath.  Possible relative to gateway.php
+		$dirname = dirname($amfbody->classPath); 
+		if(is_dir($dirname))
+		{
+			chdir($dirname);
+		}
+		else
+		{
+			$ex = new MessageException(E_USER_ERROR, "The classpath folder {" . $amfbody->classPath . "} does not exist. You probably misplaced your service." , __FILE__, __LINE__, "AMFPHP_CLASSPATH_NOT_FOUND");
+			MessageException::throwException($amfbody, $ex);
+			return false;
+		}
+	   
+		$fileExists = @file_exists(basename($amfbody->classPath)); // see if the file exists
+		if(!$fileExists)
+		{
+				$ex = new MessageException(E_USER_ERROR, "The class {" . $amfbody->className . "} could not be found under the class path {" . $amfbody->classPath . "}" , __FILE__, __LINE__, "AMFPHP_FILE_NOT_FOUND");
+				MessageException::throwException($amfbody, $ex);
+				return false;
+		}
+		
+		global $amfphp;
+		$time = microtime_float();
+		$fileIncluded = Executive::includeClass($amfbody, "./" . basename($amfbody->classPath));
+		$amfphp['includeTime'] += microtime_float() - $time;
+	
+		if (!$fileIncluded) 
+		{ 
+			$ex = new MessageException(E_USER_ERROR, "The class file {" . $amfbody->className . "} exists but could not be included. The file may have syntax errors, or includes at the top of the file cannot be resolved.", __FILE__, __LINE__, "AMFPHP_FILE_NOT_INCLUDED");
+			MessageException::throwException($amfbody, $ex);
+			return false;
+		}
+		
+		if (!class_exists($amfbody->className))
+		{ // Just make sure the class name is the same as the file name
+				
+				$ex = new MessageException(E_USER_ERROR, "The file {" . $amfbody->className . ".php} exists and was included correctly but a class by that name could not be found in that file. Perhaps the class is misnamed.", __FILE__, __LINE__, "AMFPHP_CLASS_NOT_FOUND");
+				MessageException::throwException($amfbody, $ex);
+				return false;
+		}
+
+		//Let executive handle building the class
+		//The executive can handle making exceptions and all that, that's why
+		$classConstruct = Executive::buildClass($amfbody, $amfbody->className);
+
+		if($classConstruct !== '__amfphp_error')
+		{
+			$amfbody->setClassConstruct($classConstruct);
+		}
+		else
+		{
+			return false;
+		}
+	}
+	return true;
+} 
+
+/**
+ * MetaDataAction loads the required info from the methodTable
+ */
+function securityAction (&$amfbody) {
+	if(!$amfbody->noExec)
+	{
+		$classConstruct = &$amfbody->getClassConstruct();
+		$methodName = $amfbody->methodName;
+		$className = $amfbody->className;
+		
+		//Check if method exists
+		if (!method_exists($classConstruct, $methodName)) { // check to see if the method exists
+			$ex = new MessageException(E_USER_ERROR, "The method  {" . $methodName . "} does not exist in class {" . $className . "}.", __FILE__, __LINE__, "AMFPHP_INEXISTANT_METHOD");
+			MessageException::throwException($amfbody, $ex);
+			return false;
+		} 
+		
+		//Check if method is private (PHP4)
+		if (strpos($methodName, '_') === 0) { // check to see if the method exists
+			$ex = new MessageException(E_USER_ERROR, "The method  {" . $methodName . "} starts with an underscore and is therefore considered private, so it cannot be remotely called.", __FILE__, __LINE__, "AMFPHP_PRIVATE_METHOD");
+			MessageException::throwException($amfbody, $ex);
+			return false;
+		} 
+		
+		//Check to see if method is private or protected (PHP5)
+		if(class_exists('ReflectionMethod'))
+		{
+			$method = new ReflectionMethod($className, $methodName);
+			if(!$method->isPublic())
+			{
+				$ex = new MessageException(E_USER_ERROR, "The method  {" . $methodName . "} in {" . $className . "} is not public and therefore cannot be called.", __FILE__, __LINE__, "AMFPHP_PRIVATE_METHOD");
+				MessageException::throwException($amfbody, $ex);
+				return false;
+			}
+		}
+		
+		$classConstruct = &$amfbody->getClassConstruct();
+		$methodName = $amfbody->methodName;
+		$className = $amfbody->className;
+		
+		if (method_exists($classConstruct, "beforeFilter")) {			
+			//Pass throught the executive
+			$allow = Executive::doMethodCall($amfbody, 
+										$classConstruct, 
+										'beforeFilter', 
+										array($methodName));
+			if ($allow === '__amfphp_error' || $allow === false) {
+				$ex = new MessageException(E_USER_ERROR, "Method access blocked by beforeFilter in " . $className . " class", __FILE__, __LINE__, "AMFPHP_AUTHENTICATE_ERROR");
+				MessageException::throwException($amfbody, $ex);
+				return false;
+			} 
+		}
+	}
+	return true;
+}
+
+function adapterMap(&$results)
+{
+	if(is_array($results))
+	{
+		array_walk($results, 'adapterMap');
+	}
+	elseif(is_object($results))
+	{
+		$className = strtolower(get_class($results));
+		if(array_key_exists($className, $GLOBALS['amfphp']['adapterMappings']))
+		{
+			$type = $GLOBALS['amfphp']['adapterMappings'][$className];
+			$results = mapRecordSet($results, $type);
+		}
+		else
+		{
+			$vars = get_object_vars($results);
+			
+			array_walk($vars, 'adapterMap');
+			
+			foreach($vars as $key => $value)
+			{
+				$results->$key = $value;
+			}
+		}
+	}
+	elseif(is_resource($results))
+	{
+		$type = get_resource_type($results);
+		$str = explode(' ', $type);
+		if(in_array($str[1], array("result", 'resultset', "recordset", "statement")))
+		{
+			$results = mapRecordSet($results, $str[0]);
+		}
+		else
+		{
+			$results = false;
+		}
+	}
+	return $results;
+}
+
+function mapRecordSet($result, $type)
+{
+	$classname = $type . "Adapter"; // full class name
+	$includeFile = include_once(AMFPHP_BASE . "shared/adapters/" . $classname . ".php"); // try to load the recordset library from the sql folder
+	if (!$includeFile) {
+		trigger_error("The recordset filter class " . $classname . " was not found");
+	} 
+	$recordSet = new $classname($result); // returns formatted recordset
+	
+	return array("columns" => $recordSet->columns, "rows" => $recordSet->rows);
+}
+?>
\ No newline at end of file
diff --git a/core/shared/app/BasicGateway.php b/core/shared/app/BasicGateway.php
new file mode 100755
index 0000000..f471d3d
--- /dev/null
+++ b/core/shared/app/BasicGateway.php
@@ -0,0 +1,95 @@
+registerActionChain();
+	}
+	
+	/**
+	 * Sets the base path for loading service methods.
+	 * 
+	 * Call this method to define the directory to look for service classes in.
+	 * Relative or full paths are acceptable
+	 * 
+	 * @param string $path The path the the service class directory
+	 */
+	function setBaseClassPath($value) {
+		$path = realpath($value . '/') . '/';
+		$GLOBALS['amfphp']['classPath'] = $path;
+	}
+	
+	function service()
+	{
+		//Process the arguments
+		$body = $this->createBody();
+		foreach($this->actions as $key => $action)
+		{
+			$result = $action($body); //   invoke the first filter in the chain
+			if($result === false)
+			{
+				//Go straight to serialization actions
+				$serAction = 'serializationAction';
+				$serAction($body);
+				break;
+			}
+		}
+		
+		echo $body->getResults();
+	}
+	
+	/**
+	 * Add a class mapping for adapters
+	 */
+	function addAdapterMapping($key, $value)
+	{
+		$GLOBALS['amfphp']['adapterMappings'][$key] = $value;
+	}
+	
+	/**
+	 * This function should overriden by the gateways
+	 */
+	function createBody()
+	{
+		
+	}
+	
+	/**
+	 * Create the chain of actions
+	 * Subclass gateway and overwrite to create a custom gateway
+	 */
+	function registerActionChain()
+	{
+		
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/app/Constants.php b/core/shared/app/Constants.php
new file mode 100755
index 0000000..aff0241
--- /dev/null
+++ b/core/shared/app/Constants.php
@@ -0,0 +1,53 @@
+= 5 ? true : false);
+/**
+ * The Content Type String
+ */
+$tmp = pack("d", 1); // determine the multi-byte ordering of this machine temporarily pack 1
+define("AMFPHP_BIG_ENDIAN", $tmp == "\0\0\0\0\0\0\360\77");
+
+?>
diff --git a/core/shared/app/Globals.php b/core/shared/app/Globals.php
new file mode 100755
index 0000000..d3eeca1
--- /dev/null
+++ b/core/shared/app/Globals.php
@@ -0,0 +1,47 @@
+ 'peardb', //PEAR::DB
+	'pdostatement' => 'pdo', //PDO
+	'mysqli_result' => 'mysqliobject', //Mysqli
+	'sqliteresult' => 'sqliteobject', //SQLite
+	'sqliteunbuffered' => 'sqliteobject',
+	'adorecordset' => 'adodb', //ADODB
+	'zend_db_table_row' => 'zendrow', //Zend::DB
+	'zend_db_table_rowset' => 'zendrowset',
+	'recordset' => 'plainrecordset', //Plain recordset
+	'doctrine_collection_immediate' => 'doctrine' //Doctrine table
+);
+
+?>
\ No newline at end of file
diff --git a/core/shared/app/php4Executive.php b/core/shared/app/php4Executive.php
new file mode 100755
index 0000000..be94f3b
--- /dev/null
+++ b/core/shared/app/php4Executive.php
@@ -0,0 +1,115 @@
+
diff --git a/core/shared/app/php5Executive.php b/core/shared/app/php5Executive.php
new file mode 100755
index 0000000..74fdb38
--- /dev/null
+++ b/core/shared/app/php5Executive.php
@@ -0,0 +1,181 @@
+code, $fault->getMessage(), $fault->file, $fault->line, 'AMFPHP_RUNTIME_ERROR');
+			}
+			else
+			{
+				$code = "AMFPHP_RUNTIME_ERROR";
+				if($fault->getCode() != 0)
+				{
+					$code = $fault->getCode();
+				}
+				$ex = new MessageException(E_USER_ERROR, $fault->getMessage(), $fault->getFile(), $fault->getLine(), $code);
+			}
+			MessageException::throwException($bodyObj, $ex);
+			$output = '__amfphp_error';
+		}
+		return $output;
+	} 
+	
+	/**
+	 * Builds a class using a class name
+	 * If there is a failure, catch the error and return to caller
+	 */
+	function buildClass(&$bodyObj, $className)
+	{
+		global $amfphp;
+		if(isset($amfphp['classInstances'][$className]))
+		{
+			return $amfphp['classInstances'][$className];
+		}
+		
+		try
+		{
+			$construct = new $className($className);
+			$amfphp['classInstances'][$className] = & $construct;
+		}
+		catch(Exception $fault)
+		{
+			//When constructing a class, getLine and getFile don't refer to the appropriate thing,
+			//hence this hack
+			$ex = new MessageException(E_USER_ERROR, $fault->getMessage(), $bodyObj->classPath, 'Undetermined line  in constructor', 'AMFPHP_BUILD_ERROR');
+			MessageException::throwException($bodyObj, $ex);
+			$construct = '__amfphp_error';
+		}
+		
+		return $construct;
+	}
+	
+	/**
+	 * We are using a deferred metho call instead of directly 
+	 * calling the method because of a strange bug with throwing exceptions within
+	 * an error handler which seems to break the convential rule for working with exceptions
+	 * Nesting function calls seems to solve the problem, but not nesting try...catch
+	 */
+	function deferredMethodCall(&$bodyObj, &$object, $method, $args)
+	{
+		try
+		{
+			if($object === NULL)
+			{
+				$output = call_user_func_array ($method, $args);
+			}
+			else
+			{
+				$output = call_user_func_array (array(&$object, $method), $args);
+			}
+		}
+		catch(Exception $fault)
+		{
+			if(get_class($fault) == "VerboseException")
+			{
+				$ex = new MessageException($fault->code, $fault->getMessage(), $fault->file, $fault->line, 'AMFPHP_RUNTIME_ERROR');
+			}
+			else
+			{
+				$code = "AMFPHP_RUNTIME_ERROR";
+				if($fault->getCode() != 0)
+				{
+					$code = $fault->getCode();
+				}
+				$ex = new MessageException(E_USER_ERROR, $fault->getMessage(), $fault->getFile(), $fault->getLine(), $code);
+			}
+			$output = '__amfphp_error';
+			MessageException::throwException($bodyObj, $ex);
+			
+		}
+		
+		return $output;
+	}
+	
+	/**
+	 * Include a class
+	 * If there is an error, catch and return to caller
+	 */
+	function includeClass(&$bodyObj, $location)
+	{
+		$included = false;
+		try
+		{
+			include_once($location);
+			$included = true;
+		}
+		catch(Exception $fault)
+		{
+			$included = false;
+			if(get_class($fault) == "VerboseException")
+			{
+				$ex = new MessageException($fault->code, $fault->getMessage(), $fault->file, $fault->line, 'AMFPHP_INCLUDE_ERROR');
+			}
+			else
+			{
+				$ex = new MessageException(E_USER_ERROR, $fault->getMessage(), $fault->getFile(), $fault->getLine(), 'AMFPHP_INCLUDE_ERROR');
+			}
+			MessageException::throwException($bodyObj, $ex);
+		}
+		return $included;
+	}
+} 
+?>
diff --git a/core/shared/exception/MessageException.php b/core/shared/exception/MessageException.php
new file mode 100755
index 0000000..7d6941b
--- /dev/null
+++ b/core/shared/exception/MessageException.php
@@ -0,0 +1,110 @@
+code = $detailCode;
+		$this->description = $description; // pass the description    
+		$this->details = $file; // pass the details
+		$this->level = MessageException::getFriendlyError($code); 
+		$this->line = $line; // pass the line number
+	}
+	
+	/**
+	 * throwException provides the means to raise an exception.  This method will 
+	 * stop the further execution of the remote method, but not hault the execution
+	 * of the entire process.  Using the built in PHP exception system will stop
+	 * the entire process and not allow us to report very detailed information back
+	 * to the client, especially if there are multiple methods.
+	 * 
+	 * When we upgrade to PHP 5, using the try...catch syntax will make this much easier.
+	 * 
+	 * @static
+	 * @param AMFBody $body The AMFBody object to apply the exception to.
+	 * @param AMFException @exception The exception object to throw
+	 * @see AMFBody
+	 */ 
+	function throwException (&$body, $exception) {
+		$body->responseURI = $body->responseIndex . "/onStatus";
+		$results = &$body->getResults();
+
+		if($GLOBALS['amfphp']['encoding'] == 'amf3')
+		{
+			$results = new ErrorMessage();
+			$results->correlationId = $GLOBALS['amfphp']['lastMessageId'];
+			$results->faultCode = $exception->code;
+			$results->faultDetail = $exception->details . ' on line ' . $exception->line;
+			$results->faultString = $exception->description;
+		}
+		elseif($GLOBALS['amfphp']['encoding'] == 'amf0')
+		{
+			$results["description"] = $exception->description;
+			$results["details"] = $exception->details;
+			$results["level"] = $exception->level;
+			$results["line"] = $exception->line;
+			$results["code"] = $exception->code;
+		}
+		else
+		{
+			$results['faultCode'] = $exception->code;
+			$results['faultDetail'] = $exception->details . ' on line ' . $exception->line;
+			$results['faultString'] = $exception->description;
+		}
+	} 
+	
+	function getFriendlyError ($err) {
+		$errortype = array (1 => "Error",
+			2 => "Warning",
+			4 => "Parsing Error",
+			8 => "Notice",
+			16 => "Core Error",
+			32 => "Core Warning",
+			64 => "Compile Error",
+			128 => "Compile Warning",
+			256 => "User Error",
+			512 => "User Warning",
+			1024 => "User Notice",
+			2048 => "Strict error",
+			);
+		if(isset($errortype[$err]))
+		{
+			return $errortype[$err];
+		}
+		else
+		{
+			return "Unknown error type";
+		}
+	} 
+} 
+
+?>
\ No newline at end of file
diff --git a/core/shared/exception/php4Exception.php b/core/shared/exception/php4Exception.php
new file mode 100755
index 0000000..c8dcd68
--- /dev/null
+++ b/core/shared/exception/php4Exception.php
@@ -0,0 +1,56 @@
+setResults($error);
+	
+	if($GLOBALS['amfphp']['encoding'] == 'amf0' || $GLOBALS['amfphp']['encoding'] == 'amf3')
+	{
+		// build a new AMFObject
+		$amfout = new AMFObject("");
+	
+		$amfout->addBody($amfbody);  
+		
+		// Add the trace headers we have so far while we're at it
+		debugFilter($amfout);
+		
+		// create a new serializer
+		$serializer = new AMFSerializer();
+		
+		// serialize the data
+		$data = $serializer->serialize($amfout);
+	
+		// send the correct header
+		header('Content-type: application/x-amf');
+		// flush the amf data to the client.
+		print($data);
+		
+		// kill the system after we find a single error
+		exit;
+	}
+	else
+	{
+		serializationAction($amfbody);
+		print($amfbody->getResults());
+		exit;
+	}
+
+}
+
+set_error_handler("reportExceptions");
+
+?>
\ No newline at end of file
diff --git a/core/shared/exception/php5Exception.php b/core/shared/exception/php5Exception.php
new file mode 100755
index 0000000..c41dd93
--- /dev/null
+++ b/core/shared/exception/php5Exception.php
@@ -0,0 +1,46 @@
+description = $string;
+		$this->level = $level;
+		$this->code = "AMFPHP_RUNTIME_ERROR";
+		$this->file = $file;
+		$this->line = $line;
+		Exception::__construct($string);
+	}
+}
+
+function amfErrorHandler($level, $string, $file, $line, $context)
+{
+	//forget about errors not defined at reported
+	$amfphpErrorLevel = $GLOBALS['amfphp']['errorLevel'];
+
+	if( error_reporting() != 0 && ($amfphpErrorLevel | $level) == $amfphpErrorLevel )
+	{
+		throw new VerboseException($string, $level, $file, $line);
+	}
+}
+
+set_error_handler("amfErrorHandler");
+?>
\ No newline at end of file
diff --git a/core/shared/util/Authenticate.php b/core/shared/util/Authenticate.php
new file mode 100755
index 0000000..4e58b97
--- /dev/null
+++ b/core/shared/util/Authenticate.php
@@ -0,0 +1,113 @@
+ $role) {
+			$methodRoles[$key] = strtolower(trim($role));
+		}
+		if(!isset($_SESSION['amfphp_roles']))
+		{
+			$_SESSION['amfphp_roles'] = "";
+			
+		}
+		$userRoles = explode(",", $_SESSION['amfphp_roles']); // split the users session roles into an array
+		
+		foreach($userRoles as $key => $role) {
+			$userRoles[$key] = strtolower(trim($role));
+			if (in_array($userRoles[$key], $methodRoles)) {
+				return true;
+			} 
+		} 
+		return false;
+	} 
+
+	/**
+	 * login assumes that the user has verified the credentials and logs in the user.
+	 * 
+	 * The login method hides the session implementation for storing the user credentials
+	 * 
+	 * @param string $name The user name
+	 * @param string $roles The comma delimited list of roles for the user
+	 */
+	function login($name, $roles) {
+		if(!session_id())
+		{
+			session_start();
+		}
+		$_SESSION['amfphp_username'] = $name;
+		$_SESSION['amfphp_roles'] = $roles;
+	} 
+
+	/**
+	 * logout kills the user session and terminates the login properties
+	 */
+	function logout() {
+		$_SESSION['amfphp_username'] = null;
+		$_SESSION['amfphp_roles'] = null;
+		if(isset($_SESSION['amfphp_username']))
+		{
+			unset($_SESSION['amfphp_username']);
+		}
+		if(isset($_SESSION['amfphp_roles']))
+		{
+			unset($_SESSION['amfphp_roles']);
+		}
+		return true;
+	} 
+} 
+
+?>
\ No newline at end of file
diff --git a/core/shared/util/CharsetHandler.php b/core/shared/util/CharsetHandler.php
new file mode 100755
index 0000000..f3a9668
--- /dev/null
+++ b/core/shared/util/CharsetHandler.php
@@ -0,0 +1,130 @@
+_method = CharsetHandler::getMethod();
+		$this->_phpCharset = CharsetHandler::getPhpCharset();
+		$this->_sqlCharset = CharsetHandler::getSqlCharset();
+		$this->_mode = $mode;
+		
+		$newset = "";
+		if($this->_mode == "flashtophp")
+		{
+			$this->_fromCharset = "utf-8";
+			$this->_toCharset = $this->_phpCharset;
+			$newset = $this->_phpCharset;
+		}
+		else if($this->_mode == "phptoflash")
+		{
+			$this->_fromCharset = $this->_phpCharset;
+			$this->_toCharset = "utf-8";
+			$newset = $this->_phpCharset;
+		}
+		else if($this->_mode == "sqltophp")
+		{
+			$this->_fromCharset = $this->_sqlCharset;
+			$this->_toCharset = $this->_phpCharset;
+			$newset = $this->_sqlCharset;
+		}
+		else if($this->_mode == "sqltoflash")
+		{
+			$this->_fromCharset = $this->_sqlCharset;
+			$this->_toCharset = "utf-8";
+			$newset = $this->_sqlCharset;
+		}
+		
+		//Don't try to reencode charsets for nothing
+		if($this->_fromCharset == $this->_toCharset)
+		{
+			$this->_method = "none";
+		}
+	}
+	
+	function transliterate($string)
+	{
+		switch($this->_method)
+		{
+			case "none" :
+				return $string;
+				break;
+			case "iconv":
+				return iconv($this->_fromCharset,$this->_toCharset, $string);
+				break;
+			case "utf8_decode":
+				return ($this->_mode == "flashtophp" ? utf8_decode($string) : utf8_encode($string));
+				break;
+			case "mbstring":
+				return mb_convert_encoding($string, $this->_toCharset, $this->_fromCharset);
+				break;
+			case "recode":
+				return recode_string($this->_fromCharset . ".." . $this->_toCharset, $string);
+				break;
+			default:
+				return $string;
+				break;
+		}
+	}
+	
+	/**
+	 * Sets the charset handling method
+	 *
+	 * @param string $location One of "none", "iconv", "mbstring", "recode"
+	 */
+	function getMethod($val=NULL)
+	{
+		static $method = 0;
+		if($val != NULL)
+		{
+			if($val == 'utf8_encode')
+			{
+				$val = 'utf8_decode';
+			}
+			$method = $val;
+		}
+		return $method;
+	}
+	
+	function setMethod($val=0){
+		return CharsetHandler::getMethod($val);
+	}
+
+	function getPhpCharset($val=NULL)
+	{
+		static $phpCharset = 0;
+		if($val != NULL)
+		{
+			$phpCharset = strtolower($val);
+		}
+		return $phpCharset;
+	}
+	
+	function setPhpCharset($val=0){
+		return CharsetHandler::getPhpCharset($val);
+	}
+	
+	function getSqlCharset($val=NULL)
+	{
+		static $sqlCharset = 0;
+		if($val != NULL)
+		{
+			$sqlCharset = strtolower($val);
+		}
+		return $sqlCharset;
+	}
+	
+	function setSqlCharset($val=0){
+		return CharsetHandler::getSqlCharset($val);
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/util/CompatPhp4.php b/core/shared/util/CompatPhp4.php
new file mode 100755
index 0000000..f9241c4
--- /dev/null
+++ b/core/shared/util/CompatPhp4.php
@@ -0,0 +1,60 @@
+ $val) {
+	   if ($needle === $val) {
+	       return($key);
+	   }
+	}
+	return FALSE;
+}
+
+function microtime_float()
+{
+	list($usec, $sec) = explode(" ", microtime());
+	return ((float)$usec + (float)$sec);
+}
+
+if(!function_exists('is_a'))
+{
+	//We only use is_a as a replacement for PHP5-related stuff, so we always return false
+	//anyways
+	function is_a($obj, $d)
+	{
+		return false;
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/util/CompatPhp5.php b/core/shared/util/CompatPhp5.php
new file mode 100755
index 0000000..aaaf11e
--- /dev/null
+++ b/core/shared/util/CompatPhp5.php
@@ -0,0 +1,20 @@
+
\ No newline at end of file
diff --git a/core/shared/util/Headers.php b/core/shared/util/Headers.php
new file mode 100755
index 0000000..692af8f
--- /dev/null
+++ b/core/shared/util/Headers.php
@@ -0,0 +1,32 @@
+
\ No newline at end of file
diff --git a/core/shared/util/JSON.php b/core/shared/util/JSON.php
new file mode 100755
index 0000000..d1f983f
--- /dev/null
+++ b/core/shared/util/JSON.php
@@ -0,0 +1,645 @@
+
+ * @author      Matt Knapp 
+ * @author      Brett Stimmerman 
+ * @copyright   2005 Michal Migurski
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+ *
+ * Note: this is a stripped version of JSON.php to remove pear dependencies and
+ * encoding capability
+ */
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_SLICE',   1);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_STR',  2);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_ARR',  3);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_OBJ',  4);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_CMT', 5);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_LOOSE_TYPE', 16);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
+
+class Services_JSON
+{
+	function Services_JSON($use = 0)
+	{
+		$this->use = $use;
+	}
+
+	function utf162utf8($utf16)
+	{
+		// oh please oh please oh please oh please oh please
+		if(function_exists('mb_convert_encoding'))
+			return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
+		
+		$bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
+
+		switch(true) {
+			case ((0x7F & $bytes) == $bytes):
+				// this case should never be reached, because we are in ASCII range
+				// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+				return chr(0x7F & $bytes);
+
+			case (0x07FF & $bytes) == $bytes:
+				// return a 2-byte UTF-8 character
+				// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+				return chr(0xC0 | (($bytes >> 6) & 0x1F))
+					 . chr(0x80 | ($bytes & 0x3F));
+
+			case (0xFFFF & $bytes) == $bytes:
+				// return a 3-byte UTF-8 character
+				// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+				return chr(0xE0 | (($bytes >> 12) & 0x0F))
+					 . chr(0x80 | (($bytes >> 6) & 0x3F))
+					 . chr(0x80 | ($bytes & 0x3F));
+		}
+
+		// ignoring UTF-32 for now, sorry
+		return '';
+	}        
+
+	function utf82utf16($utf8)
+	{
+		// oh please oh please oh please oh please oh please
+		if(function_exists('mb_convert_encoding'))
+			return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+		
+		switch(strlen($utf8)) {
+			case 1:
+				// this case should never be reached, because we are in ASCII range
+				// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+				return $ut8;
+
+			case 2:
+				// return a UTF-16 character from a 2-byte UTF-8 char
+				// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+				return chr(0x07 & (ord($utf8{0}) >> 2))
+					 . chr((0xC0 & (ord($utf8{0}) << 6))
+						 | (0x3F & ord($utf8{1})));
+				
+			case 3:
+				// return a UTF-16 character from a 3-byte UTF-8 char
+				// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+				return chr((0xF0 & (ord($utf8{0}) << 4))
+						 | (0x0F & (ord($utf8{1}) >> 2)))
+					 . chr((0xC0 & (ord($utf8{1}) << 6))
+						 | (0x7F & ord($utf8{2})));
+		}
+
+		// ignoring UTF-32 for now, sorry
+		return '';
+	}        
+	
+	function name_value($name, $value)
+	{
+		$encoded_value = $this->encode($value);
+	
+		return $this->encode(strval($name)) . ':' . $encoded_value;
+	}        
+
+	function reduce_string($str)
+	{
+		$str = preg_replace(array(
+		
+				// eliminate single line comments in '// ...' form
+				'#^\s*//(.+)$#m',
+	
+				// eliminate multi-line comments in '/* ... */' form, at start of string
+				'#^\s*/\*(.+)\*/#Us',
+	
+				// eliminate multi-line comments in '/* ... */' form, at end of string
+				'#/\*(.+)\*/\s*$#Us'
+	
+			), '', $str);
+		
+		// eliminate extraneous space
+		return trim($str);
+	}
+	
+   /**
+    * encodes an arbitrary variable into JSON format
+    *
+    * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
+    *                           see argument 1 to Services_JSON() above for array-parsing behavior.
+    *                           if var is a strng, note that encode() always expects it
+    *                           to be in ASCII or UTF-8 format!
+    *
+    * @return   mixed   JSON string representation of input var or an error if a problem occurs
+    * @access   public
+    */
+    function encode($var)
+    {
+        switch (gettype($var)) {
+            case 'boolean':
+                return $var ? 'true' : 'false';
+
+            case 'NULL':
+                return 'null';
+
+            case 'integer':
+                return (int) $var;
+
+            case 'double':
+            case 'float':
+                return (float) $var;
+
+            case 'string':
+                // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+                $ascii = '';
+                $strlen_var = strlen($var);
+
+               /*
+                * Iterate over every character in the string,
+                * escaping with a slash or encoding to UTF-8 where necessary
+                */
+                for ($c = 0; $c < $strlen_var; ++$c) {
+
+                    $ord_var_c = ord($var{$c});
+
+                    switch (true) {
+                        case $ord_var_c == 0x08:
+                            $ascii .= '\b';
+                            break;
+                        case $ord_var_c == 0x09:
+                            $ascii .= '\t';
+                            break;
+                        case $ord_var_c == 0x0A:
+                            $ascii .= '\n';
+                            break;
+                        case $ord_var_c == 0x0C:
+                            $ascii .= '\f';
+                            break;
+                        case $ord_var_c == 0x0D:
+                            $ascii .= '\r';
+                            break;
+
+                        case $ord_var_c == 0x22:
+                        case $ord_var_c == 0x2F:
+                        case $ord_var_c == 0x5C:
+                            // double quote, slash, slosh
+                            $ascii .= '\\'.$var{$c};
+                            break;
+
+                        case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+                            // characters U-00000000 - U-0000007F (same as ASCII)
+                            $ascii .= $var{$c};
+                            break;
+
+                        case (($ord_var_c & 0xE0) == 0xC0):
+                            // characters U-00000080 - U-000007FF, mask 110XXXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+                            $c += 1;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xF0) == 0xE0):
+                            // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}));
+                            $c += 2;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xF8) == 0xF0):
+                            // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}));
+                            $c += 3;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xFC) == 0xF8):
+                            // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}));
+                            $c += 4;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xFE) == 0xFC):
+                            // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}),
+                                         ord($var{$c + 5}));
+                            $c += 5;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+                    }
+                }
+
+                return '"'.$ascii.'"';
+
+            case 'array':
+               /*
+                * As per JSON spec if any array key is not an integer
+                * we must treat the the whole array as an object. We
+                * also try to catch a sparsely populated associative
+                * array with numeric keys here because some JS engines
+                * will create an array with empty indexes up to
+                * max_index which can cause memory issues and because
+                * the keys, which may be relevant, will be remapped
+                * otherwise.
+                *
+                * As per the ECMA and JSON specification an object may
+                * have any string as a property. Unfortunately due to
+                * a hole in the ECMA specification if the key is a
+                * ECMA reserved word or starts with a digit the
+                * parameter is only accessible using ECMAScript's
+                * bracket notation.
+                */
+
+                // treat as a JSON object
+                if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+                    $properties = array_map(array($this, 'name_value'),
+                                            array_keys($var),
+                                            array_values($var));
+
+                    return '{' . join(',', $properties) . '}';
+                }
+
+                // treat it like a regular array
+                $elements = array_map(array($this, 'encode'), $var);
+
+                return '[' . join(',', $elements) . ']';
+
+            case 'object':
+                $vars = get_object_vars($var);
+
+                $properties = array_map(array($this, 'name_value'),
+                                        array_keys($vars),
+                                        array_values($vars));
+
+                return '{' . join(',', $properties) . '}';
+            case 'resource':
+				return null;
+            default:
+                return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
+                    ? 'null'
+                    : trigger_error(gettype($var)." can not be encoded as JSON string", E_USER_ERROR);
+        }
+    }
+    
+	function sanitizeType($type)
+	{
+		$subtype = -1;
+		$type = strtolower($type);
+		if($type == NULL || trim($type) == "")
+		{
+			$type = -1;
+		}
+		
+		if(strpos($type, ' ') !== false)
+		{
+			$str = explode(' ', $type);
+			if(in_array($str[1], array("result", 'resultset', "recordset", "statement")))
+			{
+				$type = "__RECORDSET__";
+				$subtype = $str[0];
+			}
+		}
+		return array($type, $subtype);
+	} 
+
+	function decode($str)
+	{
+		$str = $this->reduce_string($str);
+	
+		switch (strtolower($str)) {
+			case 'true':
+				return true;
+
+			case 'false':
+				return false;
+			
+			case 'null':
+				return null;
+			
+			default:
+				if (is_numeric($str)) {
+					// Lookie-loo, it's a number
+
+					// Return float or int, as appropriate
+					return ((float)$str == (integer)$str)
+						? (integer)$str
+						: (float)$str;
+					
+				} 
+				elseif (preg_match('/^("|\').*(\1)$/s', $str,   $m) && $m[1] == $m[2]) {
+					// STRINGS RETURNED IN UTF-8 FORMAT
+					$delim = substr($str, 0, 1);
+					$chrs = substr($str, 1, -1);
+					$utf8 = '';
+					$strlen_chrs = strlen($chrs);
+					
+					for ($c = 0; $c < $strlen_chrs; ++$c) {
+					
+						$substr_chrs_c_2 = substr($chrs, $c, 2);
+						$ord_chrs_c = ord($chrs{$c});
+						
+						switch (true) {
+							case $substr_chrs_c_2 == '\b':
+								$utf8 .= chr(0x08);
+								++$c;
+								break;
+							case $substr_chrs_c_2 == '\t':
+								$utf8 .= chr(0x09);
+								++$c;
+								break;
+							case $substr_chrs_c_2 == '\n':
+								$utf8 .= chr(0x0A);
+								++$c;
+								break;
+							case $substr_chrs_c_2 == '\f':
+								$utf8 .= chr(0x0C);
+								++$c;
+								break;
+							case $substr_chrs_c_2 == '\r':
+								$utf8 .= chr(0x0D);
+								++$c;
+								break;
+
+							case $substr_chrs_c_2 == '\\"':
+							case $substr_chrs_c_2 == '\\\'':
+							case $substr_chrs_c_2 == '\\\\':
+							case $substr_chrs_c_2 == '\\/':
+								if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
+								   ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
+									$utf8 .= $chrs{++$c};
+								}
+								break;
+								
+							case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
+								// single, escaped unicode character
+								$utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
+									   . chr(hexdec(substr($chrs, ($c + 4), 2)));
+								$utf8 .= $this->utf162utf8($utf16);
+								$c += 5;
+								break;
+		
+							case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
+								$utf8 .= $chrs{$c};
+								break;
+		
+							case ($ord_chrs_c & 0xE0) == 0xC0:
+								// characters U-00000080 - U-000007FF, mask 110XXXXX
+								//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+								$utf8 .= substr($chrs, $c, 2);
+								++$c;
+								break;
+	
+							case ($ord_chrs_c & 0xF0) == 0xE0:
+								// characters U-00000800 - U-0000FFFF, mask 1110XXXX
+								// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+								$utf8 .= substr($chrs, $c, 3);
+								$c += 2;
+								break;
+	
+							case ($ord_chrs_c & 0xF8) == 0xF0:
+								// characters U-00010000 - U-001FFFFF, mask 11110XXX
+								// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+								$utf8 .= substr($chrs, $c, 4);
+								$c += 3;
+								break;
+	
+							case ($ord_chrs_c & 0xFC) == 0xF8:
+								// characters U-00200000 - U-03FFFFFF, mask 111110XX
+								// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+								$utf8 .= substr($chrs, $c, 5);
+								$c += 4;
+								break;
+	
+							case ($ord_chrs_c & 0xFE) == 0xFC:
+								// characters U-04000000 - U-7FFFFFFF, mask 1111110X
+								// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+								$utf8 .= substr($chrs, $c, 6);
+								$c += 5;
+								break;
+
+						}
+
+					}
+					
+					return $utf8;
+				
+				} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
+					// array, or object notation
+
+					if ($str{0} == '[') {
+						$stk = array(SERVICES_JSON_IN_ARR);
+						$arr = array();
+					} else {
+						if ($this->use & SERVICES_JSON_LOOSE_TYPE ) {
+							$stk = array(SERVICES_JSON_IN_OBJ);
+							$obj = array();
+						} else {
+							$stk = array(SERVICES_JSON_IN_OBJ);
+							$obj = new stdClass();
+						}
+					}
+					
+					array_push($stk, array('what'  => SERVICES_JSON_SLICE,
+										   'where' => 0,
+										   'delim' => false));
+
+					$chrs = substr($str, 1, -1);
+					$chrs = $this->reduce_string($chrs);
+					
+					if ($chrs == '') {
+						if (reset($stk) == SERVICES_JSON_IN_ARR) {
+							return $arr;
+
+						} else {
+							return $obj;
+
+						}
+					}
+
+					//print("\nparsing {$chrs}\n");
+					
+					$strlen_chrs = strlen($chrs);
+					
+					for ($c = 0; $c <= $strlen_chrs; ++$c) {
+					
+						$top = end($stk);
+						$substr_chrs_c_2 = substr($chrs, $c, 2);
+					
+						if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
+							// found a comma that is not inside a string, array, etc.,
+							// OR we've reached the end of the character list
+							$slice = substr($chrs, $top['where'], ($c - $top['where']));
+							array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
+							//print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+							if (reset($stk) == SERVICES_JSON_IN_ARR) {
+								// we are in an array, so just push an element onto the stack
+								array_push($arr, $this->decode($slice));
+
+							} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+								// we are in an object, so figure
+								// out the property name and set an
+								// element in an associative array,
+								// for now
+								if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+									// "name":value pair
+									$key = $this->decode($parts[1]);
+									$val = $this->decode($parts[2]);
+
+									if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
+										$obj[$key] = $val;
+									} else {
+										$obj->$key = $val;
+									}
+								} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+									// name:value pair, where name is unquoted
+									$key = $parts[1];
+									$val = $this->decode($parts[2]);
+
+									if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
+										$obj[$key] = $val;
+									} else {
+										$obj->$key = $val;
+									}
+								}
+
+							}
+
+						} elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
+							// found a quote, and we are not inside a string
+							array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
+							//print("Found start of string at {$c}\n");
+
+						} elseif (($chrs{$c} == $top['delim']) &&
+								 ($top['what'] == SERVICES_JSON_IN_STR) &&
+								 (($chrs{$c - 1} != '\\') ||
+								 ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) {
+							// found a quote, we're in a string, and it's not escaped
+							array_pop($stk);
+							//print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
+
+						} elseif (($chrs{$c} == '[') &&
+								 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+							// found a left-bracket, and we are in an array, object, or slice
+							array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
+							//print("Found start of array at {$c}\n");
+
+						} elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
+							// found a right-bracket, and we're in an array
+							array_pop($stk);
+							//print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+						} elseif (($chrs{$c} == '{') &&
+								 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+							// found a left-brace, and we are in an array, object, or slice
+							array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
+							//print("Found start of object at {$c}\n");
+
+						} elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
+							// found a right-brace, and we're in an object
+							array_pop($stk);
+							//print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+						} elseif (($substr_chrs_c_2 == '/*') &&
+								 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+							// found a comment start, and we are in an array, object, or slice
+							array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
+							$c++;
+							//print("Found start of comment at {$c}\n");
+
+						} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
+							// found a comment end, and we're in one now
+							array_pop($stk);
+							$c++;
+							
+							for ($i = $top['where']; $i <= $c; ++$i)
+								$chrs = substr_replace($chrs, ' ', $i, 1);
+							
+							//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+						}
+					
+					}
+					
+
+					
+					if (reset($stk) == SERVICES_JSON_IN_ARR) {
+						return $arr;
+
+					} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+						return $obj;
+
+					}
+				
+				}
+		}
+	}
+}
+?>
\ No newline at end of file
diff --git a/core/shared/util/MessageBody.php b/core/shared/util/MessageBody.php
new file mode 100755
index 0000000..90edc59
--- /dev/null
+++ b/core/shared/util/MessageBody.php
@@ -0,0 +1,143 @@
+responseIndex = $responseIndex;
+		$this->targetURI = $targetURI;
+		$this->responseURI = $this->responseIndex . "/onStatus"; // default to the onstatus method
+		$this->setValue($value);
+	}
+	
+	/**
+	 * setter for the results from the process execution
+	 * 
+	 * @param mixed $results The returned results from the process execution
+	 */
+	function setResults ($result) {
+		$this->_results = $result;
+	} 
+
+	/**
+	 * getter for the result of the process execution
+	 * 
+	 * @return mixed The results
+	 */
+	function &getResults () {
+		return $this->_results;
+	} 
+
+	/**
+	 * setter for the class construct
+	 * 
+	 * @param object $classConstruct The instance of the service class
+	 */
+	function setClassConstruct (&$classConstruct) {
+		$this->_classConstruct = &$classConstruct;
+	} 
+
+	/**
+	 * getter for the class construct
+	 * 
+	 * @return object The class instance
+	 */
+	function &getClassConstruct () {
+		return $this->_classConstruct;
+	} 
+	
+	/**
+	 * setter for the value property
+	 * 
+	 * @param mixed $value The value of the body object
+	 */
+	function setValue ($value) {
+		$this->_value = $value;
+	} 
+
+	/**
+	 * getter for the value property
+	 * 
+	 * @return mixed The value property
+	 */
+	function &getValue () {
+		return $this->_value;
+	} 
+	
+	/**
+	 * Set special handling type for this body
+	 */
+	function setSpecialHandling($type)
+	{
+		$this->_specialHandling = $type;
+	}
+	
+	/**
+	 * Get special handling type for this body
+	 */
+	function getSpecialHandling()
+	{
+		return $this->_specialHandling;
+	}
+
+	/**
+	 * Check if this body is handled special against an array of special cases
+	 */
+	function isSpecialHandling($against = NULL)
+	{
+		if($against !== NULL)
+		{
+			return in_array($this->_specialHandling, $against);
+		}
+		else
+		{
+			return ($this->_specialHandling != NULL);
+		}
+	}
+	
+	function setMetaData($key, $val)
+	{
+		$this->_metaData[$key] = $val;
+	}
+	
+	function getMetaData($key)
+	{
+		if(isset($this->_metaData[$key]))
+		{
+			return $this->_metaData[$key];
+		}
+		else
+		{
+			return NULL;
+		}
+	}
+} 
+
+?>
diff --git a/core/shared/util/MessageHeader.php b/core/shared/util/MessageHeader.php
new file mode 100755
index 0000000..43bcee3
--- /dev/null
+++ b/core/shared/util/MessageHeader.php
@@ -0,0 +1,49 @@
+name = $name;
+		$this->required = $required;
+		$this->value = $value;
+	} 
+} 
+
+?>
\ No newline at end of file
diff --git a/core/shared/util/MethodTable.php b/core/shared/util/MethodTable.php
new file mode 100755
index 0000000..a52dc02
--- /dev/null
+++ b/core/shared/util/MethodTable.php
@@ -0,0 +1,552 @@
+methodTable = MethodTable::create($this);
+ * @author Christophe Herreman
+ * @since 05/01/2005
+ * @version $id$
+ * 
+ * Special contributions by Allessandro Crugnola and Ted Milker
+ */
+
+if (!defined('T_ML_COMMENT')) {
+   define('T_ML_COMMENT', T_COMMENT);
+} else {
+   define('T_DOC_COMMENT', T_ML_COMMENT);
+}
+
+function strrstr($haystack, $needle)
+{
+	return substr($haystack, 0, strpos($haystack.$needle,$needle));
+}
+
+function strstrafter($haystack, $needle)
+{
+	return substr(strstr($haystack, $needle), strlen($needle));
+}
+
+class MethodTable
+{
+	/**
+	 * Constructor.
+	 *
+	 * Since this class should only be accessed through the static create() method
+	 * this constructor should be made private. Unfortunately, this is not possible
+	 * in PHP4.
+	 *
+	 * @access private
+	 */
+	function MethodTable(){
+	}
+
+
+	/**
+	 * Creates the methodTable for a passed class.
+	 *
+	 * @static
+	 * @access public
+	 * @param $className(String) The name of the service class.
+	 *        May also simply be __FILE__
+	 * @param $servicePath(String) The location of the classes (optional)
+	 */
+	function create($className, $servicePath = NULL, &$classComment){
+		
+		$methodTable = array();
+		if(file_exists($className))
+		{
+			//The new __FILE__ way of doing things was used
+			$sourcePath = $className;
+			$className = str_replace("\\", '/', $className);
+			$className = substr($className, strrpos($className, '/') + 1);
+			$className = str_replace('.php', '', $className);
+		}
+		else
+		{
+			$className = str_replace('.php', '', $className);
+			$fullPath = str_replace('.', '/', $className);
+			$className = $fullPath;
+			if(strpos($fullPath, '/') !== FALSE)
+			{
+				$className = substr(strrchr($fullPath, '/'), 1);
+			}
+			
+			if($servicePath == NULL)
+			{
+				if(isset($GLOBALS['amfphp']['classPath']))
+				{
+					$servicePath = $GLOBALS['amfphp']['classPath'];
+				}
+				else
+				{
+					$servicePath = "../services/";
+				}
+			}
+			$sourcePath = $servicePath . $fullPath . ".php";
+		}
+		
+		if(!file_exists($sourcePath))
+		{
+			trigger_error("The MethodTable class could not find {" . 
+				$sourcePath . "}", 
+				E_USER_ERROR);
+		}
+		
+		if(class_exists('ReflectionClass'))
+		{
+			//PHP5
+			$classMethods = MethodTable::getClassMethodsReflection($sourcePath, $className, $classComment);
+		}
+		else
+		{
+			//PHP4
+			
+			$classMethods = MethodTable::getClassMethodsTokenizer($sourcePath, $className, $classComment);
+		}
+		
+		foreach ($classMethods as $key => $value) {
+			if($value['name'][0] == '_' || $value['name'] == 'beforeFilter')
+			{
+				continue;
+			}
+			$methodSignature = $value['args'];
+			$methodName = $value['name'];
+			$methodComment = $value['comment'];
+			
+			$description = MethodTable::getMethodDescription($methodComment) . " " . MethodTable::getMethodCommentAttribute($methodComment, "desc");
+			$description = trim($description);
+			$access = MethodTable::getMethodCommentAttributeFirstWord($methodComment, "access");
+			$roles = MethodTable::getMethodCommentAttributeFirstWord($methodComment, "roles");
+			$instance = MethodTable::getMethodCommentAttributeFirstWord($methodComment, "instance");
+			$returns = MethodTable::getMethodCommentAttributeFirstLine($methodComment, "returns");
+			$pagesize = MethodTable::getMethodCommentAttributeFirstWord($methodComment, "pagesize");
+			$params = MethodTable::getMethodCommentArguments($methodComment);
+						
+			//description, arguments, access, [roles, [instance, [returns, [pagesize]]]]
+			$methodTable[$methodName] = array();
+			//$methodTable[$methodName]["signature"] = $methodSignature; //debug purposes
+			$methodTable[$methodName]["description"] = ($description == "") ? "No description given." : $description;
+			$methodTable[$methodName]["arguments"] = MethodTable::getMethodArguments($methodSignature, $params);
+			$methodTable[$methodName]["access"] = ($access == "") ? "private" : $access;
+			
+			if($roles != "") $methodTable[$methodName]["roles"] = $roles;
+			if($instance != "") $methodTable[$methodName]["instance"] = $instance;
+			if($returns != "") $methodTable[$methodName]["returns"] = $returns;
+			if($pagesize != "") $methodTable[$methodName]["pagesize"] = $pagesize;
+		}
+		
+		$classComment = trim(str_replace("\r\n", "\n", MethodTable::getMethodDescription($classComment)));
+		
+		return $methodTable;
+	}
+	
+	function getClassMethodsReflection($sourcePath, $className, & $classComment)
+	{
+		//Include the class in question
+		$dir = dirname($sourcePath);
+		if(!is_dir($dir))
+		{
+			return array();
+		}
+		
+		chdir($dir);
+		
+		if(!file_exists($sourcePath))
+		{
+			return array();
+		}
+		
+		//HACK: eAccelerator
+		//Check if eAccelator is installed
+		if( extension_loaded( "eAccelerator" ))
+		{
+			//Touch the file so the results of getDocComment will be accurate
+			touch($sourcePath);
+		}
+		
+		$included = include_once($sourcePath);
+		if($included === FALSE)
+		{
+			return array();
+		}
+		
+		//Verify that the class exists
+		if(!class_exists($className))
+		{
+			return array();
+		}
+		
+		$methodTable = array();
+		
+		$class = new ReflectionClass($className);
+		
+		$classComment = $class->getDocComment();
+		$methods = $class->getMethods();
+		
+		
+		foreach($methods as $reflectionMethod){
+			
+			if($reflectionMethod->isPublic() && $method->name[0] != '_' && $method->name != 'beforeFilter')
+			{
+				if($reflectionMethod->isConstructor())
+				{
+					$classComment .= $reflectionMethod->getDocComment();
+				}
+				else
+				{
+					$reflectionParameter = $reflectionMethod->getParameters();
+					
+					$methodTableEntry = array();			
+					$parameters = array();
+					
+					foreach($reflectionParameter as $parameter){
+						$parameters[] = $parameter->getName();
+					}
+					
+					$methodTableEntry['args'] = '(' . implode(', ', $parameters);
+					$methodTableEntry['name'] = $reflectionMethod->name;
+					$methodTableEntry['comment'] = $reflectionMethod->getDocComment();
+					
+					$methodTable[] = $methodTableEntry;
+				}
+			}
+		}
+		
+		return $methodTable;
+	}
+	
+	function getClassMethodsTokenizer($sourcePath, $className, & $classComment)
+	{
+		$source = file_get_contents($sourcePath);
+		$tokens = token_get_all($source);
+		
+		$waitingForOpenParenthesis = false;
+		$waitingForFunction = false;
+		$waitingForClassName = false;
+		$bufferingArgs = false;
+		$argBuffer = "";
+		$lastFunction = "";
+		$lastFunctionComment = "";
+		$lastComment = "";
+		$classMethods = array();
+		$realClassName = "";
+
+		$openBraces = -10000;
+
+		$waitingForEndEncapsedString = false;
+		foreach($tokens as $token)
+		{
+		   if (is_string($token)) {
+				if($token == '{')
+				{
+					$openBraces++;
+				}
+				if($token == '}')
+				{
+					if($waitingForEndEncapsedString)
+					{
+						$waitingForEndEncapsedString = false;
+					}
+					else
+					{
+						$lastComment = '';
+						$openBraces--;
+						
+						if($openBraces == 0)
+						{
+							//break;
+						}
+					}
+				}
+				elseif($waitingForOpenParenthesis && $token == '(')
+				{
+					$bufferingArgs = true;
+					$argBuffer = "";
+					$waitingForOpenParenthesis = false;
+				}
+				elseif($bufferingArgs)
+				{
+					if($token != ')')
+					{
+						$argBuffer .= $token;
+					}
+					else
+					{
+						if($lastFunction != $realClassName && $lastFunction != "__construct")
+						{
+							$classMethods[] = array("name" => $lastFunction,
+											   "comment" => $lastFunctionComment,
+											   "args" => $argBuffer);
+						}
+						else
+						{
+							$classComment .= "\n\n" . $lastComment;
+						}
+						
+						$bufferingArgs = false;
+						$argBuffer = "";
+						$lastFunction = "";
+						$lastFunctionComment = "";
+					}
+					
+				}
+		   } else {
+			   // token array
+			   list($id, $text) = $token;
+				
+				if($bufferingArgs)
+				{
+					$argBuffer .= $text;                    
+				}
+			   switch ($id) 
+			   {
+					
+				   case T_COMMENT:
+				   case T_ML_COMMENT: // we've defined this
+				   case T_DOC_COMMENT: // and this
+				   // no action on comments
+						$lastComment = $text;
+						break;
+				   case T_FUNCTION:
+						if($openBraces >= 1)
+						{
+							$waitingForFunction = true;
+						}
+						break;
+					case T_STRING:
+						if($waitingForFunction)
+						{
+							$waitingForFunction = false;
+							$waitingForOpenParenthesis = true;
+							$lastFunction = $text;
+							$lastFunctionComment = $lastComment;
+							$lastComment = "";              
+						}
+						if($waitingForClassName)
+						{
+							$waitingForClassName = false;
+							if(strpos(strtolower($className), strtolower($text)) !== FALSE)
+							{
+								//Not the class we were looking for
+								$classComment = $lastComment;
+								$realClassName = $text;
+							}
+						}
+						break;
+					case T_CLASS:
+						$openBraces = 0;
+						$waitingForClassName = true;
+						break;
+					case T_CURLY_OPEN:
+					case T_DOLLAR_OPEN_CURLY_BRACES:
+						$waitingForEndEncapsedString = true;
+						break;
+				}
+			}
+		}
+		return $classMethods;
+	}
+	
+	/**
+	 * 
+	 */
+	function getMethodCommentArguments($comment)
+	{
+		$pieces = explode('@param', $comment);
+		$args = array();
+		if(is_array($pieces) && count($pieces) > 1)
+		{
+			for($i = 0; $i < count($pieces) - 1; $i++)
+			{
+				$ps = strrstr($pieces[$i + 1], '@');
+				$ps = strrstr($ps, '*/');
+				$args[] = MethodTable::cleanComment($ps);
+			}
+		}
+		return $args;
+	}
+	
+	
+	/**
+	 * Returns the description from the comment.
+	 * The description is(are) the first line(s) in the comment.
+	 *
+	 * @static
+	 * @private
+	 * @param $comment(String) The method's comment.
+	 */
+	function getMethodDescription($comment){
+		$comment = MethodTable::cleanComment(strrstr($comment, "@"));
+		return trim($comment);
+	}
+	
+	
+	/**
+	 * Returns the value of a comment attribute.
+	 *
+	 * @static
+	 * @private
+	 * @param $comment(String) The method's comment.
+	 * @param $attribute(String) The name of the attribute to get its value from.
+	 */
+	function getMethodCommentAttribute($comment, $attribute){
+		$pieces = strstrafter($comment, '@' . $attribute);
+		if($pieces !== FALSE)
+		{
+			$pieces = strrstr($pieces, '@');
+			$pieces = strrstr($pieces, '*/');
+			return MethodTable::cleanComment($pieces);
+		}
+		return "";
+	}
+	
+	/**
+	 * Returns the value of a comment attribute.
+	 *
+	 * @static
+	 * @private
+	 * @param $comment(String) The method's comment.
+	 * @param $attribute(String) The name of the attribute to get its value from.
+	 */
+	function getMethodCommentAttributeFirstLine($comment, $attribute){
+		$pieces = strstrafter($comment, '@' . $attribute);
+		if($pieces !== FALSE)
+		{
+			$pieces = strrstr($pieces, '@');
+			$pieces = strrstr($pieces, "*");
+			$pieces = strrstr($pieces, "/");
+			$pieces = strrstr($pieces, "-");
+			$pieces = strrstr($pieces, "\n");
+			$pieces = strrstr($pieces, "\r");
+			$pieces = strrstr($pieces, '*/');
+			return MethodTable::cleanComment($pieces);
+		}
+		return "";
+	}
+	
+	function getMethodCommentAttributeFirstWord($comment, $attribute){
+		$pieces = strstrafter($comment, '@' . $attribute);
+		if($pieces !== FALSE)
+		{
+			$val = MethodTable::cleanComment($pieces);
+			return trim(strrstr($val, ' '));
+		}
+		return "";
+	}
+	
+	/**
+	 * Returns an array with the arguments of a method.
+	 *
+	 * @static
+	 * @access private
+	 * @param $methodSignature (String)The method's signatureg;
+	 */
+	function getMethodArguments($methodSignature, $commentParams){
+		if(strlen($methodSignature) < 2){
+			//no arguments, return an empty array
+			$result = array();
+		}else{
+			//clean the arguments before returning them
+			$result = MethodTable::cleanArguments(explode(",", $methodSignature), $commentParams);
+		}
+		
+		return $result;
+	}
+	
+	
+	/**
+	 * Cleans the arguments array.
+	 * This method removes all whitespaces and the leading "$" sign from each argument
+	 * in the array.
+	 *
+	 * @static
+	 * @access private
+	 * @param $args(Array) The "dirty" array with arguments.
+	 */
+	function cleanArguments($args, $commentParams){
+		$result = array();
+		
+		foreach($args as $index => $arg){
+			$arg = strrstr(str_replace('(', '', $arg), '=');
+			if(!isset($commentParams[$index]))
+			{
+				$result[] = trim($arg);
+			}
+			else
+			{
+				$start = trim($arg);
+				$end = trim(str_replace('$', '', $commentParams[$index]));
+				//echo($start);
+				//echo($end);
+				if($end != "" && $start != "" && strpos(strtolower($end), strtolower($start)) === 0)
+				{
+					$end = substr($end, strlen($start));
+				}
+				$result[] = $start . ' - ' . trim($end);
+			}
+		}
+		
+		return $result;
+	}
+	
+	
+	/**
+	 * Cleans the comment string by removing all comment start and end characters.
+	 *
+	 * @static
+	 * @private
+	 * @param $comment(String) The method's comment.
+	 */
+	function cleanComment($comment){
+		$comment = str_replace("/**", "", $comment);
+		$comment = str_replace("*/", "", $comment);
+		$comment = str_replace("*", "", $comment);
+		$comment = str_replace("\r", "", trim($comment));
+		$comment = eregi_replace("\n[ \t]+", "\n", trim($comment));
+		$comment = str_replace("\n", "\\n", trim($comment));
+		$comment = eregi_replace("[\t ]+", " ", trim($comment));
+		
+		$comment = str_replace("\"", "\\\"", $comment);
+		return $comment;
+	}
+
+	/**
+	 *
+	 */
+	function showCode($methodTable){
+		
+
+		foreach($methodTable as $methodName=>$methodProps){
+			$result .= "\n\t\"" . $methodName . "\" => array(";
+			
+			foreach($methodProps as $key=>$value){
+				$result .= "\n\t\t\"" . $key . "\" => ";
+
+				if($key=="arguments"){
+					$result .= "array(";
+					for($i=0; $i
\ No newline at end of file
diff --git a/core/shared/util/NetDebug.php b/core/shared/util/NetDebug.php
new file mode 100755
index 0000000..f03f43c
--- /dev/null
+++ b/core/shared/util/NetDebug.php
@@ -0,0 +1,52 @@
+
\ No newline at end of file
diff --git a/core/shared/util/functions.php b/core/shared/util/functions.php
new file mode 100755
index 0000000..5fefdf8
--- /dev/null
+++ b/core/shared/util/functions.php
@@ -0,0 +1,44 @@
+
\ No newline at end of file
diff --git a/core/xmlrpc/app/Actions.php b/core/xmlrpc/app/Actions.php
new file mode 100755
index 0000000..7bfecd0
--- /dev/null
+++ b/core/xmlrpc/app/Actions.php
@@ -0,0 +1,104 @@
+getValue();
+	
+	//Get the method that is being called
+	$description = xmlrpc_parse_method_descriptions($data);
+	$target = $description['methodName'];
+	
+	$baseClassPath = $GLOBALS['amfphp']['classPath'];
+	
+	$lpos = strrpos($target, '.');
+	
+	$methodname = substr($target, $lpos + 1);
+	$trunced = substr($target, 0, $lpos);
+	$lpos = strrpos($trunced, ".");
+	if ($lpos === false) {
+		$classname = $trunced;
+		$uriclasspath = $trunced . ".php";
+		$classpath = $baseClassPath . $trunced . ".php";
+	} else {
+		$classname = substr($trunced, $lpos + 1);
+		$classpath = $baseClassPath . str_replace(".", "/", $trunced) . ".php"; // removed to strip the basecp out of the equation here
+		$uriclasspath = str_replace(".", "/", $trunced) . ".php"; // removed to strip the basecp out of the equation here
+	} 
+	
+	$body->methodName = $methodname;
+	$body->className = $classname;
+	$body->classPath = $classpath;
+	$body->uriClassPath = $uriclasspath;
+	$body->packageClassMethodName = $description['methodName'];
+}
+
+function executionAction(& $body)
+{
+	$classConstruct = $body->getClassConstruct();
+	$methodName = $body->methodName;
+	$className = $body->className;
+	
+	$xmlrpc_server = xmlrpc_server_create();
+	
+	$lambdaFunc = 'return adapterMap(call_user_func_array (array(&$userData[0], $userData[1]), $args));';
+	$func = create_function('$a,$args,$userData', $lambdaFunc);
+
+	xmlrpc_server_register_method($xmlrpc_server,
+		$body->packageClassMethodName,
+		$func);
+	
+	$request_xml = $body->getValue();
+	$args = array($xmlrpc_server, $request_xml, array(&$classConstruct, $methodName));
+	$nullObj = NULL;
+	$response = Executive::doMethodCall($body, $nullObj, 'xmlrpc_server_call_method', $args);
+	//$response = xmlrpc_server_call_method();
+	
+	if($response !== "__amfphp_error")
+	{
+		$body->setResults($response);
+	}
+	else
+	{
+		return false;
+	}
+}
+
+/**
+ * Debug action
+ */
+function debugAction(& $body)
+{
+	if(count(NetDebug::getTraceStack()) != 0)
+	{
+		$previousResults = $body->getResults();
+		$debugInfo = NetDebug::getTraceStack();
+		$debugString = "";
+		$body->setResults($debugString . "\n" . $previousResults);
+	}
+}
+
+/**
+ * This won't ever be called unless there is an error
+ */
+function serializationAction(& $body)
+{
+	$request_xml = $body->getValue();
+	$toSerialize = $body->getResults();
+	
+	$lambdaFunc = 'return $userData;';
+	$func = create_function('$a,$b,$userData', $lambdaFunc);
+	
+	$xmlrpc_server = xmlrpc_server_create();
+	
+	$request_xml = $body->getValue();
+	
+	xmlrpc_server_register_method($xmlrpc_server,
+		$body->packageClassMethodName,
+		$func);
+
+	$response = xmlrpc_server_call_method($xmlrpc_server, $request_xml, $toSerialize);
+	
+	$body->setResults($response);
+}
+
+?>
\ No newline at end of file
diff --git a/core/xmlrpc/app/Gateway.php b/core/xmlrpc/app/Gateway.php
new file mode 100755
index 0000000..9698304
--- /dev/null
+++ b/core/xmlrpc/app/Gateway.php
@@ -0,0 +1,34 @@
+setValue($GLOBALS["HTTP_RAW_POST_DATA"]);
+		return $body;
+	}
+	
+	/**
+	 * Create the chain of actions
+	 */
+	function registerActionChain()
+	{
+		$this->actions['deserialization'] = 'deserializationAction';
+		$this->actions['classLoader'] = 'classLoaderAction';
+		$this->actions['security'] = 'securityAction';
+		$this->actions['exec'] = 'executionAction';
+		$this->actions['debug'] = 'debugAction';
+	}
+}
+?>
\ No newline at end of file