<?
/*
  this softwary by Musicman 2003
  is covered by the GPL
  for the exact terms and conditions please see http://www.fsf.org
 */
class amfdata
{	var $fn, $fnseq, $fnargs;
	var $hdrs;
	var $byteorder;
	function nargs()
	{	return count($this->fnargs);
	}
	function getstr($d, &$n)
	{	// print "($n) ";
		$hi = ord($d[$n++]);
		$lo = ord($d[$n++]);
		$lo += 256 * $hi;
		$val = substr($d, $n, $lo);
		$n += $lo;
		return $val;
	}
	function getnumber($d, &$n)
	{	$ibf = "";
		switch($this->byteorder)
		{	case 'x86':
				for($nc = 7 ; $nc >= 0 ; $nc--)
					$ibf .= $d[$n+$nc];
				break;
			case 'ppc':
				$ibf = substr($d, $n, 8);
				break;
		}
		$n += 8;
		$zz = unpack("dflt", $ibf);
		return $zz['flt'];
	}
	function parseitem($ch, $d, &$n)
	{	switch($ch)
		{	case 1: // boolean
				$ch = ord($d[$n++]);
				// settype($ch, BOOL);
				return $ch;
				break;
			case 0:
				return $this->getnumber($d, $n);
				break;
			case 3:
				return $this->getobj($d, $n);
				break;
			case 10:
				return $this->getarray($d, $n);
				break;
			case 2:
				return $this->getstr($d, $n);
				break;
			case 5:
				return null;
			default:
				print "xxx $ch ";
		}
	}
	function getobj($d, &$n)
	{	$ret = array();
		while($key = $this->getstr($d, $n))
		{	$ch = ord($d[$n++]);
			$val = $this->parseitem($ch, $d, $n);
			$ret[$key] = $val;
		}
		$ch = ord($d[$n++]);
		if($ch != 9) print "obj?? $ch ";
		return $ret;
	}
	function getarray($d, &$n)
	{	$ret = array();
		for($lo = 0, $c = 0 ; $c < 4 ; $c++)
		{	$lo *= 256;
			$lo += ord($d[$n++]);
		}
		for($ni = 0 ; $ni < $lo ; $ni++)
		{	$ch = ord($d[$n++]);
			$ret[] = $this->parseitem($ch, $d, $n);
		}
		return $ret;
	}
	function amfdata()
	{	$this->hdrs = array();
		$this->fnargs = array();
		$tmp = pack("d", 1);
		if($tmp == "\0\0\0\0\0\0\360\77")
			$this->byteorder = 'x86';
		else if($tmp == "\77\360\0\0\0\0\0\0")
			$this->byteorder = 'ppc';
		else
			die("unknown byteorder in amfdata\n");

		$d = $GLOBALS[HTTP_RAW_POST_DATA];
		$l = strlen($d);
		$n = 3;
		$nv = ord($d[$n++]);
		while(--$nv >= 0)
		{	$key = $this->getstr($d, $n);
			$n++;
			for($lo = 0, $c = 0 ; $c < 4 ; $c++)
			{	$lo *= 256;
				$lo += ord($d[$n++]);
			}
			$ch = ord($d[$n++]);
			$val = $this->parseitem($ch, $d, $n);
			$this->$hdrs[$key] = $val;
		}
		$n++;
		if($ch = ord($d[$n++]))
		{	$this->fn = $this->getstr($d, $n);
			$this->fnseq = $this->getstr($d, $n);
			for($lo = 0, $c = 0 ; $c < 4 ; $c++)
			{	$lo *= 256;
				$lo += ord($d[$n++]);
			}
			$ch = ord($d[$n++]); if($ch != 10) print " ??";
			for($lo = 0, $c = 0 ; $c < 4 ; $c++)
			{	$lo *= 256;
				$lo += ord($d[$n++]);
			}
			for($ni = 0 ; $ni < $lo ; $ni++)
			{	$ch = ord($d[$n++]);
				$this->fnargs[] = $this->parseitem($ch, $d, $n);
			}
		}
		return $this;
	}

	function sendnum($val)
	{	$b = pack("d", $val);
		switch($this->byteorder)
		{	case 'x86':
				$r = "";
				for($n = 7 ; $n >= 0 ; $n--)
					$r .= $b[$n];
				return $r;
			case 'ppc':
				return $b;
		}
	}
	function sendstr($str)
	{	return pack("n", strlen($str)) . $str;
	}
	function sendobj($val)
	{	if(is_array($val) || is_object($val))
		{	$first = 1;
			$num_array = 1;
			foreach($val as $key => $data)
			{	if(!is_int($key) || ($key < 0))
				{	$num_array = 0;
					break;
				}
				if($first)
				{	$lo = $hi = $key;
					$first = 0;
				}
				else if($key < $lo)
					$lo = $key;
				else if($key > $hi)
					$hi = $key;
			}
			if($num_array)
			{	$ret = "\12" . pack("N", $hi+1);
				for($n = 0 ; $n <= $hi ; $n++)
					$ret .= $this->sendobj($val[$n]);
			}
			else
			{	$ret = "\3";
				foreach($val as $key => $data)
				{	$ret .= $this->sendstr($key);
					$ret .= $this->sendobj($data);
				}
				$ret .= $this->sendstr('') . "\11";
			}
			return $ret;
		}
		else if(is_integer($val) || is_numeric($val))
			return "\0" . $this->sendnum($val);
		else
			return "\2" . $this->sendstr($val);
	}
	function sendresult($data)
	{	header('Content-type: application/x-amf');
		print "\0\0\0\0\0\1" . $this->sendstr($this->fnseq . "/onResult") .
		 $this->sendstr("null") . pack("N", -1) . $this->sendobj($data);
	}
}
Back