903 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			903 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| /*
 | |
| 	This file should not be modified. This is so that future versions can be
 | |
| 	dropped into place as servers are updated.
 | |
| 	
 | |
| 	Version 2.3.0: Supports phantoms.
 | |
| 	Version 2.2.1: Supports channel comments.
 | |
| */
 | |
| 
 | |
| 
 | |
| function StrKey( $src, $key, &$res )
 | |
| {
 | |
| 	$key .= " ";
 | |
| 	if ( strncasecmp( $src, $key, strlen( $key ) ) )
 | |
| 		return false;
 | |
| 		
 | |
| 	$res = substr( $src, strlen( $key ) );
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| function StrSplit( $src, $sep, &$d1, &$d2 )
 | |
| {
 | |
| 	$pos = strpos( $src, $sep );
 | |
| 	if ( $pos === false )
 | |
| 	{
 | |
| 		$d1 = $src;
 | |
| 		return;
 | |
| 	}
 | |
| 	
 | |
| 	$d1 = substr( $src, 0, $pos );
 | |
| 	$d2 = substr( $src, $pos + 1 );
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| function StrDecode( &$src )
 | |
| {
 | |
| 	$res = "";
 | |
| 	
 | |
| 	for ( $i = 0; $i < strlen( $src ); )
 | |
| 	{
 | |
| 		if ( $src[ $i ] == '%' )
 | |
| 		{
 | |
| 			$res .= sprintf( "%c", intval( substr( $src, $i + 1, 2 ), 16 ) );
 | |
| 			$i += 3;
 | |
| 			continue;
 | |
| 		}
 | |
| 		
 | |
| 		$res .= $src[ $i ];
 | |
| 		$i += 1;
 | |
| 	}
 | |
| 	
 | |
| 	return( $res );
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| class CVentriloClient
 | |
| {
 | |
| 	var	$m_uid;			// User ID.
 | |
| 	var	$m_admin;		// Admin flag.
 | |
| 	var $m_phan;		// Phantom flag.
 | |
| 	var $m_cid;			// Channel ID.
 | |
| 	var $m_ping;		// Ping.
 | |
| 	var	$m_sec;			// Connect time in seconds.
 | |
| 	var	$m_name;		// Login name.
 | |
| 	var	$m_comm;		// Comment.
 | |
| 	
 | |
| 	function Parse( $str )
 | |
| 	{
 | |
| 		$ary = explode( ",", $str );
 | |
| 		
 | |
| 		for ( $i = 0; $i < count( $ary ); $i++ )
 | |
| 		{
 | |
| 			StrSplit( $ary[ $i ], "=", $field, $val );
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "UID" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_uid = $val;
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "ADMIN" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_admin = $val;
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "CID" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_cid = $val;
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "PHAN" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_phan = $val;
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "PING" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_ping = $val;
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "SEC" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_sec = $val;
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "NAME" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_name = StrDecode( $val );
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "COMM" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_comm = StrDecode( $val );
 | |
| 				continue;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| class CVentriloChannel
 | |
| {
 | |
| 	var	$m_cid;		// Channel ID.
 | |
| 	var	$m_pid;		// Parent channel ID.
 | |
| 	var	$m_prot;	// Password protected flag.
 | |
| 	var	$m_auth;	// Authorication protected flag.
 | |
| 	var	$m_name;	// Channel name.
 | |
| 	var	$m_comm;	// Channel comment.
 | |
| 	
 | |
| 	function Parse( $str )
 | |
| 	{
 | |
| 		$ary = explode( ",", $str );
 | |
| 		
 | |
| 		for ( $i = 0; $i < count( $ary ); $i++ )
 | |
| 		{
 | |
| 			StrSplit( $ary[ $i ], "=", $field, $val );
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "CID" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_cid = $val;
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "PID" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_pid = $val;
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "PROT" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_prot = $val;
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "NAME" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_name = StrDecode( $val );
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			if ( strcasecmp( $field, "COMM" ) == 0 )
 | |
| 			{
 | |
| 				$this->m_comm = StrDecode( $val );
 | |
| 				continue;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| class CVentriloStatus
 | |
| {
 | |
| 	// These need to be filled in before issueing the request.
 | |
| 	
 | |
| 	var	$m_cmdcode;		// Specific status request code. 1=General, 2=Detail.
 | |
| 	var	$m_cmdhost;		// Hostname or IP address to perform status of.
 | |
| 	var	$m_cmdport;		// Port number of server to status.
 | |
| 	
 | |
| 	// These are the result variables that are filled in when the request is performed.
 | |
| 	
 | |
| 	var	$m_error;		// If the ERROR: keyword is found then this is the reason following it.
 | |
| 	
 | |
| 	var	$m_name;				// Server name.
 | |
| 	var	$m_phonetic;			// Phonetic spelling of server name.
 | |
| 	var	$m_comment;				// Server comment.
 | |
| 	var	$m_maxclients;			// Maximum number of clients.
 | |
| 	var	$m_voicecodec_code;		// Voice codec code.
 | |
| 	var $m_voicecodec_desc;		// Voice codec description.
 | |
| 	var	$m_voiceformat_code;	// Voice format code.
 | |
| 	var	$m_voiceformat_desc;	// Voice format description.
 | |
| 	var	$m_uptime;				// Server uptime in seconds.
 | |
| 	var	$m_platform;			// Platform description.
 | |
| 	var	$m_version;				// Version string.
 | |
| 	
 | |
| 	var	$m_channelcount;		// Number of channels as specified by the server.
 | |
| 	var	$m_channelfields;		// Channel field names.
 | |
| 	var	$m_channellist;			// Array of CVentriloChannel's.
 | |
| 	
 | |
| 	var	$m_clientcount;			// Number of clients as specified by the server.
 | |
| 	var	$m_clientfields;		// Client field names.
 | |
| 	var $m_clientlist;			// Array of CVentriloClient's.
 | |
| 	
 | |
| 	function Parse( $str )
 | |
| 	{
 | |
| 		// Remove trailing newline.
 | |
| 		
 | |
| 		$pos = strpos( $str, "\n" );
 | |
| 		if ( $pos === false )
 | |
| 		{
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			$str = substr( $str, 0, $pos );
 | |
| 		}
 | |
| 		
 | |
| 		// Begin parsing for keywords.
 | |
| 		
 | |
| 		if ( StrKey( $str, "ERROR:", $val ) )
 | |
| 		{
 | |
| 			$this->m_error = $val;
 | |
| 			return -1;
 | |
| 		}
 | |
| 
 | |
| 		if ( StrKey( $str, "NAME:", $val ) )
 | |
| 		{
 | |
| 			$this->m_name = StrDecode( $val );
 | |
| 			return 0;
 | |
| 		}
 | |
| 		
 | |
| 		if ( StrKey( $str, "PHONETIC:", $val ) )
 | |
| 		{
 | |
| 			$this->m_phonetic = StrDecode( $val );
 | |
| 			return 0;
 | |
| 		}
 | |
| 		
 | |
| 		if ( StrKey( $str, "COMMENT:", $val ) )
 | |
| 		{
 | |
| 			$this->m_comment = StrDecode( $val );
 | |
| 			return 0;
 | |
| 		}
 | |
| 		
 | |
| 		if ( StrKey( $str, "AUTH:", $this->m_auth ) )
 | |
| 			return 0;
 | |
| 		
 | |
| 		if ( StrKey( $str, "MAXCLIENTS:", $this->m_maxclients ) )
 | |
| 			return 0;
 | |
| 		
 | |
| 		if ( StrKey( $str, "VOICECODEC:", $val ) )
 | |
| 		{
 | |
| 			StrSplit( $val, ",", $this->m_voicecodec_code, $desc );
 | |
| 			$this->m_voicecodec_desc = StrDecode( $desc );
 | |
| 			return 0;
 | |
| 		}
 | |
| 		
 | |
| 		if ( StrKey( $str, "VOICEFORMAT:", $val ) )
 | |
| 		{
 | |
| 			StrSplit( $val, ",", $this->m_voiceformat_code, $desc );
 | |
| 			$this->m_voiceformat_desc = StrDecode( $desc );
 | |
| 			return 0;
 | |
| 		}
 | |
| 		
 | |
| 		if ( StrKey( $str, "UPTIME:", $val ) )
 | |
| 		{
 | |
| 			$this->m_uptime = $val;
 | |
| 			return 0;
 | |
| 		}
 | |
| 		
 | |
| 		if ( StrKey( $str, "PLATFORM:", $val ) )
 | |
| 		{
 | |
| 			$this->m_platform = StrDecode( $val );
 | |
| 			return 0;
 | |
| 		}
 | |
| 			
 | |
| 		if ( StrKey( $str, "VERSION:", $val ) )
 | |
| 		{
 | |
| 			$this->m_version = StrDecode( $val );
 | |
| 			return 0;
 | |
| 		}
 | |
| 			
 | |
| 		if ( StrKey( $str, "CHANNELCOUNT:", $this->m_channelcount ) )
 | |
| 			return 0;
 | |
| 			
 | |
| 		if ( StrKey( $str, "CHANNELFIELDS:", $this->m_channelfields ) )
 | |
| 			return 0;
 | |
| 			
 | |
| 		if ( StrKey( $str, "CHANNEL:", $val ) )
 | |
| 		{
 | |
| 			$chan = new CVentriloChannel;
 | |
| 			$chan->Parse( $val );
 | |
| 			
 | |
| 			$this->m_channellist[ count( $this->m_channellist ) ] = $chan;
 | |
| 			return 0;
 | |
| 		}
 | |
| 			
 | |
| 		if ( StrKey( $str, "CLIENTCOUNT:", $this->m_clientcount ) )
 | |
| 			return 0;
 | |
| 			
 | |
| 		if ( StrKey( $str, "CLIENTFIELDS:", $this->m_clientfields ) )
 | |
| 			return 0;
 | |
| 			
 | |
| 		if ( StrKey( $str, "CLIENT:", $val ) )
 | |
| 		{
 | |
| 			$client = new CVentriloClient;
 | |
| 			$client->Parse( $val );
 | |
| 			
 | |
| 			$this->m_clientlist[ count( $this->m_clientlist ) ] = $client;
 | |
| 			return 0;
 | |
| 		}
 | |
| 
 | |
| 		// Unknown key word. Could be a new keyword from a newer server.
 | |
| 		
 | |
| 		return 1;
 | |
| 	}
 | |
| 	
 | |
| 	function ChannelFind( $cid )
 | |
| 	{
 | |
| 		for ( $i = 0; $i < count( $this->m_channellist ); $i++ )
 | |
| 			if ( $this->m_channellist[ $i ]->m_cid == $cid )
 | |
| 				return( $this->m_channellist[ $i ] );
 | |
| 				
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	
 | |
| 	function ChannelPathName( $idx )
 | |
| 	{
 | |
| 		$chan = $this->m_channellist[ $idx ];
 | |
| 		$pathname = $chan->m_name;
 | |
| 		
 | |
| 		for(;;)
 | |
| 		{
 | |
| 			$chan = $this->ChannelFind( $chan->m_pid );
 | |
| 			if ( $chan == NULL )
 | |
| 				break;
 | |
| 				
 | |
| 			$pathname = $chan->m_name . "/" . $pathname;
 | |
| 		}
 | |
| 		
 | |
| 		return( $pathname );
 | |
| 	}
 | |
| 	
 | |
| 	function Request()
 | |
| 	{
 | |
| 		$ventserv = new Vent;
 | |
| 		$ventserv->setTimeout( 100000 );		// 100 ms timeout
 | |
| 		if ( $ventserv->makeRequest( $this->m_cmdcode, $this->m_cmdhost, $this->m_cmdport )) {
 | |
| 			$res = split("[\n\r\t]+", $ventserv->getResponse());
 | |
| 		}
 | |
| 		
 | |
| 		foreach($res as $line)
 | |
| 		{
 | |
| 			$this->Parse($line);
 | |
| 		}
 | |
| 		
 | |
| 		return 0;
 | |
| 	}
 | |
| };
 | |
| 
 | |
| 
 | |
| /* vent.inc.php: structures, helper functions and classes related to ventrilo queries.
 | |
|  *	written for PHP4. You'll need to make a few changes for PHP5. 
 | |
|  *	Based on a C program written by Luigi Auriemma.
 | |
| 
 | |
| LICENSE
 | |
| =======
 | |
|     Copyright (C) 2005 C. Mark Veaudry
 | |
|     Copyright 2005 Luigi Auriemma
 | |
| 
 | |
|     This program is free software; you can redistribute it and/or modify
 | |
|     it under the terms of the GNU General Public License as published by
 | |
|     the Free Software Foundation; either version 2 of the License, or
 | |
|     (at your option) any later version.
 | |
| 
 | |
|     This program is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|     GNU General Public License for more details.
 | |
| 
 | |
|     You should have received a copy of the GNU General Public License
 | |
|     along with this program; if not, write to the Free Software
 | |
|     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 | |
| 
 | |
|     http://www.gnu.org/licenses/gpl.txt
 | |
| 
 | |
| =======
 | |
| 
 | |
|     If you modify or create derivative works based on this code, please respect
 | |
| 	our work and carry along our Copyright notices along with the GNU GPL.
 | |
| 	The GPL DOES NOT allow you to release modified or derivative works under
 | |
| 	any other license. Before you modify this code, read up on your rights
 | |
| 	and obligations under the GPL.
 | |
|  */
 | |
| 
 | |
| define( "VENT_HEADSIZE", 20 );
 | |
| define( "VENT_MAXPACKETSIZE", 512 );
 | |
| define( "VENT_MAXPACKETNO", 32 );
 | |
| 
 | |
| 
 | |
| function &getHeadEncodeRef() {
 | |
| 	static $ventrilo_udp_encdata_head = array(
 | |
| 		0x80, 0xe5, 0x0e, 0x38, 0xba, 0x63, 0x4c, 0x99, 0x88, 0x63, 0x4c, 0xd6, 0x54, 0xb8, 0x65, 0x7e,
 | |
| 		0xbf, 0x8a, 0xf0, 0x17, 0x8a, 0xaa, 0x4d, 0x0f, 0xb7, 0x23, 0x27, 0xf6, 0xeb, 0x12, 0xf8, 0xea,
 | |
| 		0x17, 0xb7, 0xcf, 0x52, 0x57, 0xcb, 0x51, 0xcf, 0x1b, 0x14, 0xfd, 0x6f, 0x84, 0x38, 0xb5, 0x24,
 | |
| 		0x11, 0xcf, 0x7a, 0x75, 0x7a, 0xbb, 0x78, 0x74, 0xdc, 0xbc, 0x42, 0xf0, 0x17, 0x3f, 0x5e, 0xeb,
 | |
| 		0x74, 0x77, 0x04, 0x4e, 0x8c, 0xaf, 0x23, 0xdc, 0x65, 0xdf, 0xa5, 0x65, 0xdd, 0x7d, 0xf4, 0x3c,
 | |
| 		0x4c, 0x95, 0xbd, 0xeb, 0x65, 0x1c, 0xf4, 0x24, 0x5d, 0x82, 0x18, 0xfb, 0x50, 0x86, 0xb8, 0x53,
 | |
| 		0xe0, 0x4e, 0x36, 0x96, 0x1f, 0xb7, 0xcb, 0xaa, 0xaf, 0xea, 0xcb, 0x20, 0x27, 0x30, 0x2a, 0xae,
 | |
| 		0xb9, 0x07, 0x40, 0xdf, 0x12, 0x75, 0xc9, 0x09, 0x82, 0x9c, 0x30, 0x80, 0x5d, 0x8f, 0x0d, 0x09,
 | |
| 		0xa1, 0x64, 0xec, 0x91, 0xd8, 0x8a, 0x50, 0x1f, 0x40, 0x5d, 0xf7, 0x08, 0x2a, 0xf8, 0x60, 0x62,
 | |
| 		0xa0, 0x4a, 0x8b, 0xba, 0x4a, 0x6d, 0x00, 0x0a, 0x93, 0x32, 0x12, 0xe5, 0x07, 0x01, 0x65, 0xf5,
 | |
| 		0xff, 0xe0, 0xae, 0xa7, 0x81, 0xd1, 0xba, 0x25, 0x62, 0x61, 0xb2, 0x85, 0xad, 0x7e, 0x9d, 0x3f,
 | |
| 		0x49, 0x89, 0x26, 0xe5, 0xd5, 0xac, 0x9f, 0x0e, 0xd7, 0x6e, 0x47, 0x94, 0x16, 0x84, 0xc8, 0xff,
 | |
| 		0x44, 0xea, 0x04, 0x40, 0xe0, 0x33, 0x11, 0xa3, 0x5b, 0x1e, 0x82, 0xff, 0x7a, 0x69, 0xe9, 0x2f,
 | |
| 		0xfb, 0xea, 0x9a, 0xc6, 0x7b, 0xdb, 0xb1, 0xff, 0x97, 0x76, 0x56, 0xf3, 0x52, 0xc2, 0x3f, 0x0f,
 | |
| 		0xb6, 0xac, 0x77, 0xc4, 0xbf, 0x59, 0x5e, 0x80, 0x74, 0xbb, 0xf2, 0xde, 0x57, 0x62, 0x4c, 0x1a,
 | |
| 		0xff, 0x95, 0x6d, 0xc7, 0x04, 0xa2, 0x3b, 0xc4, 0x1b, 0x72, 0xc7, 0x6c, 0x82, 0x60, 0xd1, 0x0d 
 | |
| 	);
 | |
| 
 | |
| 	return $ventrilo_udp_encdata_head;
 | |
| }
 | |
| 
 | |
| function &getDataEncodeRef() {
 | |
| 	static $ventrilo_udp_encdata_data = array(
 | |
| 		0x82, 0x8b, 0x7f, 0x68, 0x90, 0xe0, 0x44, 0x09, 0x19, 0x3b, 0x8e, 0x5f, 0xc2, 0x82, 0x38, 0x23,
 | |
| 		0x6d, 0xdb, 0x62, 0x49, 0x52, 0x6e, 0x21, 0xdf, 0x51, 0x6c, 0x76, 0x37, 0x86, 0x50, 0x7d, 0x48,
 | |
| 		0x1f, 0x65, 0xe7, 0x52, 0x6a, 0x88, 0xaa, 0xc1, 0x32, 0x2f, 0xf7, 0x54, 0x4c, 0xaa, 0x6d, 0x7e,
 | |
| 		0x6d, 0xa9, 0x8c, 0x0d, 0x3f, 0xff, 0x6c, 0x09, 0xb3, 0xa5, 0xaf, 0xdf, 0x98, 0x02, 0xb4, 0xbe,
 | |
| 		0x6d, 0x69, 0x0d, 0x42, 0x73, 0xe4, 0x34, 0x50, 0x07, 0x30, 0x79, 0x41, 0x2f, 0x08, 0x3f, 0x42,
 | |
| 		0x73, 0xa7, 0x68, 0xfa, 0xee, 0x88, 0x0e, 0x6e, 0xa4, 0x70, 0x74, 0x22, 0x16, 0xae, 0x3c, 0x81,
 | |
| 		0x14, 0xa1, 0xda, 0x7f, 0xd3, 0x7c, 0x48, 0x7d, 0x3f, 0x46, 0xfb, 0x6d, 0x92, 0x25, 0x17, 0x36,
 | |
| 		0x26, 0xdb, 0xdf, 0x5a, 0x87, 0x91, 0x6f, 0xd6, 0xcd, 0xd4, 0xad, 0x4a, 0x29, 0xdd, 0x7d, 0x59,
 | |
| 		0xbd, 0x15, 0x34, 0x53, 0xb1, 0xd8, 0x50, 0x11, 0x83, 0x79, 0x66, 0x21, 0x9e, 0x87, 0x5b, 0x24,
 | |
| 		0x2f, 0x4f, 0xd7, 0x73, 0x34, 0xa2, 0xf7, 0x09, 0xd5, 0xd9, 0x42, 0x9d, 0xf8, 0x15, 0xdf, 0x0e,
 | |
| 		0x10, 0xcc, 0x05, 0x04, 0x35, 0x81, 0xb2, 0xd5, 0x7a, 0xd2, 0xa0, 0xa5, 0x7b, 0xb8, 0x75, 0xd2,
 | |
| 		0x35, 0x0b, 0x39, 0x8f, 0x1b, 0x44, 0x0e, 0xce, 0x66, 0x87, 0x1b, 0x64, 0xac, 0xe1, 0xca, 0x67,
 | |
| 		0xb4, 0xce, 0x33, 0xdb, 0x89, 0xfe, 0xd8, 0x8e, 0xcd, 0x58, 0x92, 0x41, 0x50, 0x40, 0xcb, 0x08,
 | |
| 		0xe1, 0x15, 0xee, 0xf4, 0x64, 0xfe, 0x1c, 0xee, 0x25, 0xe7, 0x21, 0xe6, 0x6c, 0xc6, 0xa6, 0x2e,
 | |
| 		0x52, 0x23, 0xa7, 0x20, 0xd2, 0xd7, 0x28, 0x07, 0x23, 0x14, 0x24, 0x3d, 0x45, 0xa5, 0xc7, 0x90,
 | |
| 		0xdb, 0x77, 0xdd, 0xea, 0x38, 0x59, 0x89, 0x32, 0xbc, 0x00, 0x3a, 0x6d, 0x61, 0x4e, 0xdb, 0x29
 | |
| 	);
 | |
| 
 | |
| 	return $ventrilo_udp_encdata_data;
 | |
| }
 | |
| 
 | |
| function &getCRCref() {
 | |
| 	static $ventrilo_crc_table = array(
 | |
| 		0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
 | |
| 		0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
 | |
| 		0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
 | |
| 		0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
 | |
| 		0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
 | |
| 		0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
 | |
| 		0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
 | |
| 		0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
 | |
| 		0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
 | |
| 		0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
 | |
| 		0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
 | |
| 		0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
 | |
| 		0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
 | |
| 		0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
 | |
| 		0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
 | |
| 		0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
 | |
| 		0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
 | |
| 		0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
 | |
| 		0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
 | |
| 		0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
 | |
| 		0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
 | |
| 		0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
 | |
| 		0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
 | |
| 		0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
 | |
| 		0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
 | |
| 		0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
 | |
| 		0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
 | |
| 		0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
 | |
| 		0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
 | |
| 		0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
 | |
| 		0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
 | |
| 		0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
 | |
| 	);
 | |
| 
 | |
| 	return $ventrilo_crc_table;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /* decbin2: PHP's decbin() doesn't pad the binary string to a full 32 bits, unless
 | |
|  *	it's a negative number. Since we need to mimic casting to smaller int types,
 | |
|  *	I'll use this version over the built-in decbin().
 | |
|  */
 | |
| function decbin2( $val ) { return str_pad( decbin( $val ), 32, "0", STR_PAD_LEFT ); }
 | |
| 
 | |
| 
 | |
| /* bindec2: PHP's decbin() stores negative numbers as two's complement... but PHP's
 | |
|  *	bindec() doesn't check for two's! I'll use this to decode rather than the built-in function.
 | |
|  *
 | |
|  *	bindec( decbin( -1000 )) != -1000		// not correct!
 | |
|  *	bindec2( decbin2( -1000 )) == -1000		// correct!
 | |
|  */
 | |
| function bindec2( $binstr ) {
 | |
| 	$val = bindec( $binstr );
 | |
| 
 | |
| 	// it's not two's. Return the built-in bindec() value.
 | |
| 	if (( strlen( $binstr ) != 32 ) || ( substr( $binstr, 0, 1 ) == "0" )) { return $val;  }
 | |
| 
 | |
| 	// it's two's. I needed the 0 shift to trick PHP into treating the var as an int.
 | |
| 	return (( ~ ( $val << 0 )) + 1 ) * - 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* smallCast: mimic a cast from larger int to smaller int. $bits is the destination size.
 | |
|  *	Internally, PHP integers seem to always be 32 bit. (my test systems are both 64-bit
 | |
|  *	- Athlon x64 and PowerPC G5 - and PHP still uses 32 bit ints.)
 | |
|  */
 | |
| function smallCast( $val, $bits ) {
 | |
| 	$binstr = decbin2( $val );
 | |
| 	return bindec2( substr ( $binstr, 32 - $bits ));
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Vent: class to create all the data needed to encode and decode VentPackets.
 | |
|  *	I'm using PHP4. If I were using PHP5, I'd use the 'private' keyword over
 | |
|  *	var and use the accessor functions.
 | |
|  */
 | |
| class Vent {
 | |
| 	var $clock;			// u_short of the epoch time for the last request.
 | |
| 	var $timeout;			// timeout for socket read in *microseconds* ( 1,000,000 microsec = 1 sec )
 | |
| 	var $packets = array();	// hold all the decoded response packets, in correct order
 | |
| 	var $response;			// all the decoded data
 | |
| 
 | |
| 	function getClock()			{ return $this->clock; }
 | |
| 	function getTimeout()			{ return $this->timeout; }
 | |
| 	function setTimeout( $microsecs )	{ $this->timeout = $microsecs; }
 | |
| 	function &getPackets()		{ return $this->packets; } 		// by ref
 | |
| 	function getResponse()		{ return $this->response; }
 | |
| 
 | |
| 	/* makeRequest: send off a request to the vent server, return true/false. I'm not checking
 | |
| 	*	for valid IP or hostname - someone else can add this stuff.
 | |
| 	*	Note: The password field is no longer required for 2.3 or higher servers. Even if a server
 | |
| 	*	  is password protected, it will return status info.
 | |
| 	*/
 | |
| 	function makeRequest( $cmd, $ip, $port, $pass = "" ) {
 | |
| 		$this->clock = smallCast( time(), 16 );		// reset the clock for each request
 | |
| 		$this->packets = array();					// start fresh
 | |
| 		$this->response = '';
 | |
| 	
 | |
| 		$data = pack( "a16", $pass );				// the only data for a request is a password, 16 bytes.
 | |
| 	
 | |
| 		$request = new VentRequestPacket( $cmd, $this->clock, $pass );
 | |
| 
 | |
| 		$sfh = fsockopen( "udp://$ip", $port, $errno, $errstr );
 | |
| 
 | |
| 		if ( !$sfh ) {
 | |
| 			echo("Socket Error: $errno - $errstr\n");
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		fwrite( $sfh, $request->packet );			// put the encoded request packet on the stream
 | |
| 		stream_set_timeout( $sfh, 0, $this->timeout );
 | |
| 
 | |
| 		/* read response packets off the stream. with UDP, packets can (and often)
 | |
| 		*   come out of order, so we'll put then back together after closing the socket.
 | |
| 		*/
 | |
| 		while( false != $pck = fread( $sfh, VENT_MAXPACKETSIZE ) ) {
 | |
| 			if (  count( $this->packets ) >= VENT_MAXPACKETNO ) {
 | |
| 				echo("ERROR: Received more packets than the maximum allowed in a response.\n");
 | |
| 				fclose( $sfh );
 | |
| 				return false;	  
 | |
| 			}
 | |
| 
 | |
| 			// decode this packet. If we get null back, there was an error in the decode.
 | |
| 			if ( null == $rpobj = new VentResponsePacket( $pck )) { fclose( $sfh); return false; }
 | |
| 
 | |
| 			/* check the id / clock. They should match the request, if not - skip it.
 | |
| 			* also skip if there's a duplicate packet. Could throw an error here.
 | |
| 			*/
 | |
| 			if (( $rpobj->id != $this->clock ) || ( isset( $this->packets[$rpobj->pck] ))) { continue; }
 | |
| 
 | |
| 			$this->packets[$rpobj->pck] = $rpobj;
 | |
| 		}
 | |
| 
 | |
| 		fclose( $sfh );
 | |
| 
 | |
| 		// check if we've got the right number of packets
 | |
| 		if ( $this->packets[0]->totpck != count( $this->packets )) {
 | |
| 			echo("ERROR: Received less packets than expected in the response.\n");
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// the order may not be correct. sort on the key.
 | |
| 		if ( !ksort( $this->packets, SORT_NUMERIC )) {
 | |
| 			echo("ERROR: Failed to sort the response packets in order.\n");
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		/* All the response packets arrived, were decoded, and are in the proper order. We 
 | |
| 		*   can pull the decoded data together, and check that the total length matches
 | |
| 		*   the value in the header, and the crc matches.
 | |
| 		*/
 | |
| 		foreach( $this->packets as $packet ) { $this->response .= $packet->rawdata; }
 | |
| 
 | |
| 		$rlen = strlen( $this->response );
 | |
| 		if ( $rlen != $this->packets[0]->totlen ) {
 | |
| 			echo("ERROR: Response data is $rlen bytes. Expected {$this->packets[0]->totlen} bytes.\n");
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$crc = Vent::getCRC( $this->response );
 | |
| 
 | |
| 		if ( $crc != $this->packets[0]->crc ) {
 | |
| 			echo("ERROR: response crc is $crc. Expected: {$this->packets[0]->crc}.\n");
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		return true;			// everything worked fine.
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/* getCRC: find the CRC for a data argument.
 | |
| 	*/
 | |
| 	function getCRC( &$data ) {
 | |
| 		$crc = 0;
 | |
| 		$dtoks = unpack( "c*", $data );		// Note: unpack starts output array index at 1, NOT 0.
 | |
| 		$table = getCRCref();			// my CRC table reference
 | |
| 
 | |
| 		for( $i = 1; $i <= count($dtoks); $i++ ) {
 | |
| 			$crc = $table[ $crc >> 8 ] ^ $dtoks[$i] ^ ( smallCast( $crc << 8, 16 ) );
 | |
| 		}
 | |
| 
 | |
| 		return $crc;
 | |
| 	}
 | |
| 
 | |
| 
 | |
|   /* constructor: (need to change method name for PHP5)
 | |
|    */
 | |
| 	function Vent() {
 | |
| 		$this->timeout = 500000;		// default to 0.5 second timeout
 | |
| 	}
 | |
| 
 | |
| }
 | |
| /* end of Vent class */
 | |
| 
 | |
| 
 | |
| /* VentPacket: class to mimic the ventrilo_udp_head struct in the source,
 | |
|  *	but with more logic moved inside.
 | |
|  */
 | |
| class VentPacket {
 | |
| 	var $rawdata;		// hold raw, unencoded data portion of packet
 | |
| 	var $data;		// hold encoded data
 | |
| 
 | |
| 	var $head_items;	// an array, with references to each item in the header, in proper order.
 | |
| 	var $header;		// encoded header string
 | |
| 
 | |
| 	var $packet;		// hold full encoded packet (header + data)
 | |
| 
 | |
| 	/* 10 vars for the packet header. all 2 byte unsigned shorts (20 byte header)
 | |
| 	 * The order is important for packing / unpacking.
 | |
| 	 */
 | |
| 	var $headkey;		// key used to encode the header part
 | |
| 	var $zero;			// always 0!
 | |
| 	var $cmd;			// 1, 2, or 7 are valid command requests
 | |
| 	var $id;			// epoch time cast into an unsigned short
 | |
| 	var $totlen;		// total data length, across all packets in this request / result
 | |
| 	var $len;			// data length in this packet
 | |
| 	var $totpck;		// total packets in this request / result
 | |
| 	var $pck;			// number of this packet
 | |
| 	var $datakey;		// key used to encode the data part
 | |
| 	var $crc;			// checksum
 | |
| 
 | |
| 
 | |
| 	/* mapHeader: Easy way to keep the correct order. We can use the array for loops when byte
 | |
| 	 *	order is important, and still access each element by name. Using a straight hash would
 | |
| 	 *	have lost the ordering.
 | |
| 	 */
 | |
| 	function mapHeader() {
 | |
| 		$this->head_items = array( & $this->headkey, 	& $this->zero,	& $this->cmd,	& $this->id,
 | |
| 			& $this->totlen, 	& $this->len,	& $this->totpck,	& $this->pck,
 | |
| 			& $this->datakey,	& $this->crc );
 | |
| 	}
 | |
| 
 | |
| }
 | |
| /* end of VentPacket class */
 | |
| 
 | |
| 
 | |
| 
 | |
| /* VentRequestPacket: For outgoing requests.
 | |
|  */
 | |
| class VentRequestPacket extends VentPacket {
 | |
| 
 | |
| 	/* createKeys: keys are used to encode header and data parts. a1 and a2 are the two cyphers
 | |
| 	 *	derived from the full key.
 | |
| 	 */
 | |
| 	function createKeys( &$key, &$a1, &$a2, $is_head = false ) {
 | |
| 		$rndupk = unpack( "vx", pack( "S", mt_rand( 1, 65536 )));	// need this in little endian
 | |
| 		$rnd = $rndupk['x'];
 | |
| 
 | |
| 		$rnd &= 0x7fff;
 | |
| 
 | |
| 		$a1 = smallCast( $rnd, 8 );
 | |
| 		$a2 = $rnd >> 8;
 | |
| 
 | |
| 		if ( $a2 == 0 ) {
 | |
| 			$a2 = ( $is_head ) ? 69 : 1;
 | |
| 			$rnd |= ( $a2 << 8 );
 | |
| 		}
 | |
| 
 | |
| 		$key = $rnd;
 | |
| 	}
 | |
| 
 | |
| 	/* encodeHeader: Encoded after the data portion. Do some sanity checks here,
 | |
| 	 *		make sure all the header info is here, and we've got encoded data of
 | |
| 	 *		the correct length...
 | |
| 	 */
 | |
| 	function encodeHeader() {
 | |
| 		$this->createKeys( $key, $a1, $a2, true );
 | |
| 		$table = getHeadEncodeRef();
 | |
| 
 | |
| 		$enchead = pack( "n", $key );		// the head key doesn't get encoded, just packed.
 | |
| 
 | |
| 		/* start the loop at 1 to skip headkey, pack them as unsigned shorts 
 | |
| 		 *   in network byte order. Append each one to our $to_encode string.
 | |
| 		 */
 | |
| 		$to_encode = '';
 | |
| 
 | |
| 		for( $i = 1; $i < count($this->head_items); $i++ ) {
 | |
| 			$to_encode .= pack( "n", $this->head_items[$i] );
 | |
| 		}
 | |
| 
 | |
| 		/* Need to encode as unsigned chars, not shorts. That's the reason for the pack & unpack.
 | |
| 		 *	Index starts at 1 for unpack return array, not 0.
 | |
| 		 */
 | |
| 		$chars = unpack( "C*", $to_encode );
 | |
| 
 | |
| 		for( $i = 1; $i <= count( $chars ); $i++ ) {
 | |
| 			$chars[$i] = smallCast( $chars[$i] + $table[$a2] + (( $i - 1 ) % 5 ), 8 );
 | |
| 			$enchead .= pack( "C", $chars[$i] );
 | |
| 			$a2 = smallCast( $a2 + $a1, 8 );
 | |
| 		}
 | |
| 
 | |
| 		$this->headkey = $key;
 | |
| 		$this->header = $enchead;
 | |
| 	}
 | |
| 
 | |
| 	/* encodeData: The data has to be encoded first because the datakey is part of the
 | |
| 	 *		header, and it needs to encoded along with the rest of the header.
 | |
| 	 */
 | |
| 	function encodeData() {
 | |
| 		$this->createKeys( $key, $a1, $a2 );
 | |
| 
 | |
| 		$chars = unpack( "c*", $this->rawdata );		// 1 indexed array
 | |
| 		$table = getDataEncodeRef();				// Data table reference
 | |
| 		$encdata = '';
 | |
| 
 | |
| 		for( $i = 1; $i <= count( $chars ); $i++ ) {
 | |
| 			$chars[$i] = smallCast( $chars[$i] + $table[$a2] + (( $i - 1 ) % 72 ), 8 );
 | |
| 			$encdata .= pack( "C", $chars[$i] );
 | |
| 			$a2 = smallCast( $a2 + $a1, 8 );
 | |
| 		}
 | |
| 
 | |
| 		$this->datakey = $key;
 | |
| 		$this->data = $encdata;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/* Constructor (Need to change to __Constructor() for PHP5?)
 | |
| 	 */
 | |
| 	function VentRequestPacket( $cmd, $id, $pass ) {
 | |
| 		$this->mapHeader();							// set up the references
 | |
| 		$this->rawdata = pack( "a16", $pass );			// the only thing in the data part.
 | |
| 
 | |
| 		$this->zero = 0;
 | |
| 		$this->cmd = ( $cmd == 1 || $cmd == 2 || $cmd == 7 ) ? $cmd : 1 ;
 | |
| 		$this->id = $id;
 | |
| 		$this->totlen = strlen( $this->rawdata );
 | |
| 		$this->len = $this->totlen;
 | |
| 		$this->totpck = 1;
 | |
| 		$this->pck = 0;
 | |
| 		$this->crc = Vent::getCRC( $this->rawdata );
 | |
| 		$this->encodeData();						// $this->data & datakey set here.
 | |
| 		$this->encodeHeader();						// $this->header & headkey set here. 
 | |
| 
 | |
| 		$this->packet = $this->header . $this->data;
 | |
| 	}
 | |
| }
 | |
| /* end of VentRequestPacket class */
 | |
| 
 | |
| /* VentResponsePacket: For incoming data.
 | |
|  */
 | |
| class VentResponsePacket extends VentPacket {
 | |
| 
 | |
| 	/* decodeHeader: run through the header portion of the packet, get the key, decode,
 | |
| 	 *	and perform some sanity checks.
 | |
| 	 */
 | |
| 	function decodeHeader() {
 | |
| 		$table = getHeadEncodeRef();
 | |
| 
 | |
| 		$key_array = unpack( "n1", $this->header );			// unpack the key as a short
 | |
| 		$chars = unpack( "C*", substr( $this->header, 2 ));	// unpack the rest of the header as chars
 | |
| 		$key = $key_array[1];
 | |
| 
 | |
| 		$a1 = smallCast( $key, 8 );
 | |
| 		$a2 = $key >> 8;
 | |
| 
 | |
| 		if ( $a1 == 0 ) { 
 | |
| 			echo("ERROR: Invalid packet. Header key is invalid.\n");
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		/* First step is to decode each unsigned char using the cypher key.
 | |
| 		 *	Once we finish 2 bytes treat them as a short, get the endian right,
 | |
| 		 *	and stick them in the proper header item slot.
 | |
| 		 */
 | |
| 		$item_no = 1;		// for $this->head_items array. we skip the unencoded headkey, at index 0.
 | |
| 
 | |
| 		for( $i = 1; $i <= count( $chars ); $i++ ) {
 | |
| 			$chars[$i] -= smallCast( $table[$a2] + (( $i - 1 ) % 5 ), 8 );
 | |
| 			$a2 = smallCast( $a2 + $a1, 8 );
 | |
| 
 | |
| 			// Once we've completed two bytes, we can treat them as a short, and fix the endian.
 | |
| 			if ( ( $i % 2 ) == 0 ) {
 | |
| 				$short_array = unpack( "n1", pack( "C2", $chars[$i - 1], $chars[$i] ));
 | |
| 				$this->head_items[$item_no] = $short_array[1];
 | |
| 				$item_no++;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// simple sanity checks
 | |
| 		if (( $this->zero != 0 ) || ( $this->cmd != 3 )) {
 | |
| 			echo("ERROR: Invalid packet. Expected 0 & 3, found {$this->zero} & {$this->cmd}.\n");
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		if ( $this->len != strlen( $this->data )) {
 | |
| 			echo("ERROR: Invalid packet. Data is ". strlen( $this->data ) ." bytes, expected {$this->len}.\n");
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$this->headkey = $key;
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/* decodeData: use the datakey to find the cyphers and decode the data portion of the
 | |
| 		packet. Straightforward.
 | |
| 	*/
 | |
| 	function decodeData() {
 | |
| 		$table = getDataEncodeRef();
 | |
| 
 | |
| 		$a1 = smallCast( $this->datakey, 8 );
 | |
| 		$a2 = $this->datakey >> 8;
 | |
| 
 | |
| 		if ( $a1 == 0 ) { 
 | |
| 			echo("ERROR: Invalid packet. Data key is invalid.\n");
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$chars = unpack( "C*", $this->data );		// unpack the data as unsigned chars
 | |
| 
 | |
| 		for( $i = 1; $i <= count( $chars ); $i++ ) {
 | |
| 			$chars[$i] -= smallCast( $table[$a2] + (( $i - 1 ) % 72 ), 8 );
 | |
| 			$a2 = smallCast( $a2 + $a1, 8 );
 | |
| 			$this->rawdata .= chr( $chars[$i] );
 | |
| 		}
 | |
| 
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/* constructor: change for PHP5.
 | |
| 	*/
 | |
| 	function VentResponsePacket( $packet ) {
 | |
| 		$plen = strlen( $packet );
 | |
| 
 | |
| 		if (( $plen > VENT_MAXPACKETSIZE ) || ( $plen < VENT_HEADSIZE )) {
 | |
| 			echo("ERROR: Response packet was $plen bytes. It should be between ");
 | |
| 			echo( VENT_HEADSIZE ." and ". VENT_MAXPACKETSIZE ." bytes.\n");
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		$this->mapHeader();							// set up the references
 | |
| 		$this->packet = $packet;
 | |
| 		$this->header = substr( $packet, 0, VENT_HEADSIZE );
 | |
| 		$this->data = substr( $packet, VENT_HEADSIZE );
 | |
| 
 | |
| 		if ( !$this->decodeHeader() ) { return null; }
 | |
| 		if ( !$this->decodeData() ) { return null; }
 | |
| 	}
 | |
| }
 | |
| /* end of VentResponsePacket class */
 | |
| ?>
 |