Login   Register  
PHP Classes
elePHPant
Icontem

File: cIMSPStream.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Michael Rubinsky  >  IMSP Client Classes  >  cIMSPStream.php  >  Download  
File: cIMSPStream.php
Role: ???
Content type: text/plain
Description: Class description for the IMSPStream class
Class: IMSP Client Classes
Deprecated classes for dealing with IMSP servers.
Author: By
Last change:
Date: 2002-04-16 21:37
Size: 14,195 bytes
 

Contents

Class file image Download
<?php
 /******************************************************************************************************
 * Project: PHP IMSP CLIENT LIBRARY  
 * FILE: 		cIMSPStream.PHP
 * PROVIDES: 	Basic IMSP connectivity and defines the CIMSPStream object.
 *
 * Copyright 2002 Michael Rubinsky <mike@theupstairsroom.com>
 *
 *  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
 *
 ********************************************************************************************************

 * Change Log:
 *
 *  4/16/02: mjr Version 1.1
 * 		
 *		-Improved the imspError() routine for more informative error messages.
 *		-Added a showImspErrors property to allow turning on and off the display of the IMSP specific errors.
 *		 (This does not affect the behaviour of PHP errors).
 *		-Released project under the GNU GPL
 *	
 *	3/19/02: mjr
 *		
 *		-Changed the imspRecieve() function making it responsible for determining if the server returns
 *		 a "OK", "BAD" or "NO" response.  It returns the words "OK", "BAD", or "NO" if that is the case.
 *		 All other server responses are passed back as-is to the caller.  Any failures are still reported
 *		 as a returned FALSE.
 *	
 * 3/31/02: mjr
 *		 
 *		-Updated the constructor function and the logout() function to use the new imspSend() and 
 *		 imspRecieve() routines.
 *
 *		-Seperated out the authentication code into a seperate function to allow for easier future
 *       support of other Authentication mechs.
 *		
 *		-Added beginnings of an error handling scheme.
 ********************************************************************************************************/
//Constant Definitions
define("IMSP_CRLF","\r\n");
define("IMSP_RESPONSE_TAG_LENGTH",5);
define("IMSP_DEFAULT_RESPONSE_LENGTH",512);

//These define regExp that should match the respective server response strings
define ("IMSP_CONNECTION_OK","^\* OK");
define ("IMSP_LOGIN_OK","OK User");
define ("IMSP_COMMAND_CONTINUATION_RESPONSE","^\+");

//Exit code values
define ("IMSP_EXIT_LOGIN_FAILED","Login to host failed");
define ("IMSP_EXIT_CONNECTION_FAILED","Connection failure");
define ("IMSP_NOT_EXPECTED_RESPONSE", "Did not recieve the expected response from the server.");
define ("IMSP_EXIT_UNEXPECTED_RESPONSE", "Did not recieve the expected response from the server.");		//For compatability
define ("IMSP_SYNTAX_ERROR","The server did not understand your request.");
define ("IMSP_BAD_SYNTAX","The server did not understand your request.");								//For backwards compatability.
define ("IMSP_NO","Server returned a NO response");		
define ("IMSP_EXIT_BAD_ARGUMENT","The wrong type of arguement was passed to this function");		
define ("IMSP_ENTRY_LOCKED","That addressbook entry is locked or cannot be unlocked.");
						
class IMSPStream {
	/****************************************************************************************
 	* Public Property Declarations
 	****************************************************************************************/
 	var $imsp_server = "localhost";									//Defaults to "localhost" for the IMSP server host 	
	var $imsp_port = "406"; 										//...on the default port
 	var $user;														//Property for the username
 	var $pass;														//Holds the user's password
 	var $auth_method = "PLAIN";										//Set this to the type of Authentication Method to be used. (ONLY PLAIN SUPPORTED AT THIS TIME)	
 	var $exitCode;													//Routines may place exit codes into this property for checking by the client application
 	var $log_name = "imspstream.log";								//The name of the log to write to if logging enabled.
 	var $logging = true;											//Set this to "TRUE" to enable logging.
	var $log_level = 2;												// 1 = Normal user level logging 																
																	// 2 = Include client debugging info (response strings etc..)
	
	var $seperator = ".";											//Heirarchy seperator (not used in the class...here as a convienience to the client)
	var $showImspErrors = TRUE;										//Determines if IMSP errors are passed thru to the client.
	
	/****************************************************************************************
 	* "Private" or "Friend" Declarations
 	****************************************************************************************/
 	var $commandPrefix = "A";										//Holds the current alphabetic portion of command tag	
 	var $commandCount = 1;											//Holds the current numeric portion of the command tag
 	var $tag = "";													//Holds the most current command tag
 	var $stream;													//reference to the file pointer for the IMSP stream
 	var $log_stream;												//file stream to log file;
	var $connectionID; 												//Holds uniques identifier for this connection (used only for logging purposes as of this version)


function IMSPStream($local_imsp_server="", $local_port="") {
 	
	// Check for passed in values for server and port number
 	if ($local_imsp_server) {
 		$this->imsp_server = $local_imsp_server;
 	}
 	
 	if($local_port) {
 		$this->imsp_port = $local_port;
 	}
 	
 	$this->connectionID = time();								//get a somewhat unique identifier...good enough for logging purposes.
 	
 	 		 	
 }

function login($username,$pass) {
	
	
	$this->user = $username;
	$this->pass = $pass;
	
	
	if ($this->logging) {
 		$this->open_log($this->log_name);							//open log
 		$this->write_to_log("Starting IMSP Session");
 	}
 	
  	
 	// Now try to open the IMSP connection
	if (!$this->imspOpen()) {
		$this->imspError();
		return FALSE;
	}
	 
	 if ($this->log_stream) {
 	  	$this->write_to_log("Connection OK");
 	 }

 
 	/*Everything is ok...so try to login to the server
 	 *For now, we do things simply, using LOGIN command
 	 *
 	 *in release version, we will want to support SASL logins
 	 */
 	 Switch ($this->auth_method) {
 	 	case "PLAIN":
 	 		if (!$this->imspPlainTextLogin()) {
 	 			//Login failed
 	
 	 			if($this->exitCode = "") {
	 	 			$this->exit_code = IMSP_EXIT_LOGIN_FAILED;
 				}
 				
 				
 	 			//$this->imspError();
 	 			return FALSE;
 	 		}
 	 		
 	 		break;
 	 		
 	 	default:
 	 		//must specify an auth method 
 	 		$this->exit_code = IMSP_EXIT_LOGIN_FAILED;
 	 		$this->imspError("Must specify an authentication method in the auth_method property.");
 	 		return FALSE;
 	 }
 	 
 	//OK. We are logged in to the server
 	
 	if ($this->log_stream) {
 		$this->write_to_log("LOGIN for user $this->user successful.");
 	 }
 	return TRUE;

}
/****************************************************************************************
 *logout() - logs out of the server and closes the IMSP stream
 ****************************************************************************************/
function logout() {
	//Disconnect from the server
	
	if($this->log_stream){
		$this->write_to_log("Closing Connection.");
	}
	
	
		$command_string = "LOGOUT";				//Build the command to send to the server
	
		if (!$this->imspSend($command_string)) {
			$this->imspError();
			return FALSE;
		} else {
			//Should we test here for the BYE response? Is there a need for this?
			
			fclose($this->stream);
			
			if ($this->log_stream) {
				$this->close_log();
			}
			
			return TRUE;
		}
		
	
}




/**************************************************************************************
 * IMSP connectivity functions
 *************************************************************************************/

function imspOpen() {
	// Now try to open the IMSP connection
 	$fp = fsockopen($this->imsp_server,$this->imsp_port);
 	
 	
 	// Check for failure
 	if(!$fp) {
 		$this->exit_code = IMSP_CONNECTION_FAILED;
 		$this->imspError();
 		return FALSE;	
 	}
 	
 	//save the file pointer
 	$this->stream = $fp;

 	//Get The Server Response
 	$server_response = $this->imspRecieve();
 		
 		 	
 	//Check that it is what was expected
 	if(!ereg(IMSP_CONNECTION_OK,$server_response)) {
 		$this->exit_code = IMSP_NOT_EXPECTED_RESONSE;
 		$this->imspError();
 		fclose($fp);
 		return FALSE; 
 		
 	}

	return TRUE;
	
}


function imspSend($commandText, $includeTag = TRUE, $sendCRLF=TRUE){
	
	if(!$this->stream){
		//no connection!!
		$this->exit_code = IMSP_EXIT_CONNECTION_FAILED;
		return FALSE;
	}
	
	if ($includeTag) {
		$this->tag = $this->getNextCommandTag();
		$command_text = "$this->tag ";
	}
	
	$command_text .= $commandText;
	
	
	if ($sendCRLF) {	
		$command_text .= IMSP_CRLF;
	}
	
	
	if ($this->log_stream && $this->log_level > 1) {
		$this->write_to_log("[CLIENT COMMAND] $command_text");
	}
	
	if (!fputs($this->stream,$command_text)) {
		//something wrong with connection?
		$this->exit_code = IMSP_EXIT_CONNECTION_FAILED;
		return FALSE;
		
	} else {
	
		return TRUE;
																	//don't forget to report success!	
	}
	
}

function imspRecieve() {
	//Recieves a single CRLF terminated server status response from the server.
	
	if (!$this->stream){
		//no connection!!
		$this->exit_code = IMSP_EXIT_CONNECTION_FAILED;
		return FALSE;
	}
	
	$server_response = trim(fgets($this->stream,IMSP_DEFAULT_RESPONSE_LENGTH));
	
	if ($this->log_stream && $this->log_level > 1) {
		$this->write_to_log("[SERVER RESPONSE] $server_response");
	}
	
	//should we see if the response is simply an OK, BAD or NO in response to an tagged command?
	
	//Parse out the response
	$currentTag = $this->tag;
	if (ereg("^" . $currentTag . " NO", $server_response)) {
		//Could not perform action.
		$this->exitCode = IMSP_NO;
		return "NO";

	}
	
	if (ereg("^" . $currentTag . " BAD",$server_response)) {
		//Bad syntax or entry names
		$this->exitCode = IMSP_SYNTAX_ERROR;
		return "BAD";
	}
	
	if (ereg("^" . $currentTag . " OK",$server_response)) {
		return "OK";
	}

	//If it was not a "NO", "BAD" or "OK" response, then it is up to the 
	//calling function to decide what to do with it 
	return $server_response;
}

function getServerResponseChunks(){
	//Retrieves a CRLF terminated response from the server and splits it into an array delimeted by a <space> and returns array
	$server_response = trim(fgets($this->stream,IMSP_DEFAULT_RESPONSE_LENGTH));
	$chunks = split(" ",$server_response);
	return $chunks;
}



function recieveStringLiteral($length){

	return	trim(fread($this->stream,$length));

}

/**************************************************************************************
 *Authentication Routines
 *************************************************************************************/
 function imspPlainTextLogin() {
 
 	/*Everything is ok...so try to login to the server
 	 *For now, we do things simply, using LOGIN command
 	 *
 	 *in release version, we will want to support SASL logins
 	 */
 	 
 	//Now build the command string
 	$command_string = "LOGIN $this->user $this->pass";
 	
 	//make sure any logging is at level 1 only to ensure no password information
 	//will be sent to the log during the imspSend() call.
 	$logLevel = $this->log_level;
 	$this->log_level = 1;
 	
 	
 	if (!$this->imspSend($command_string)) {
 		$this->exitCode = IMSP_CONNECTION_FAILURE;
 		return FALSE;
 	}
 	
 	//restore original logging level
 	$this->log_level = $logLevel;
 	
 	//Get the response
 	$server_response = $this->imspRecieve();
 	
 	if ($server_response!="OK") {
 		//login failed
 		$this->exitCode = IMSP_LOGIN_FAILED;
 		return FALSE;
 	}
 	
 		return TRUE;
 }
 
 
 
/**************************************************************************************
 * Utility Functions
 *************************************************************************************/
function getNextCommandTag() {
		
		$newtag = $this->commandPrefix;
		
	 	if ($this->commandCount < 10) {
			$newtag .= "000" . (string) $this->commandCount;
		} elseif ($this->commandCount < 100){
			$newtag .= "00" . (string) $this->commandCount;
		} elseif ($this->commandCount < 999) {
			$newtag .= "0" . (string) $this->commandCount;
		}
		
		//increment it for the next command
		$this->commandCount++;
		
		return $newtag;
}

function quoteSpacedString($string) {
	
	if (ereg(" ",$string)) {
		return "\"" . $string . "\"";
	} else {
		return $string;
	}
}

function imspError($server_text = "") {

	if ($this->log_stream) {
		$this->write_to_log("[ERROR]$this->exit_code");
	}
	
	if ($this->showImspErrors) {
		echo("There was an error with the IMSP service.\n");
		echo("\tThe error code is: $this->exitCode\n");
		
		if($server_text != "") {
			echo("\tThe following information is also available: $server_text\n");
		}
	}
	
	//reset the exitCode
	$this->exitCode = "";
	
}





/******************************************************************************************
 *Logging functions
 *****************************************************************************************/
 
function open_log($logfile){
	
	$fp = @fopen("log/" . $logfile,"a");
	
	if (!$fp) {
		return FALSE;
	} else {
		$this->log_stream = $fp;
		return TRUE;
	 }
}
	
function write_to_log($message) {
	@fputs($this->log_stream,date("r") . ":[$this->connectionID][$this->user] $message\n");
}

function close_log(){
	@fclose($this->log_stream);
}


}//End of Class Definition

?>