PHP Classes

File: cIMSPStream.php

Recommend this page to a friend!
  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: 20 years ago
Size: 14,195 bytes


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 <> * * 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 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 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 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 ?>