Overview

Packages

  • Horde
    • Imsp

Classes

  • Horde_Imsp_Auth_Base
  • Horde_Imsp_Auth_CramMd5
  • Horde_Imsp_Auth_Imtest
  • Horde_Imsp_Auth_Plaintext
  • Horde_Imsp_Book
  • Horde_Imsp_Client_Base
  • Horde_Imsp_Client_Socket
  • Horde_Imsp_Exception
  • Horde_Imsp_Options
  • Horde_Imsp_Translation
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * The Horde_Imsp_Client base class.
  4:  *
  5:  * Copyright 2003-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * See the enclosed file COPYING for license information (LGPL). If you
  8:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  9:  *
 10:  * @author  Michael Rubinsky <mrubinsk@horde.org>
 11:  * @package Horde_Imsp
 12:  */
 13: class Horde_Imsp_Client_Socket extends Horde_Imsp_Client_Base
 14: {
 15:     /**
 16:      * Stream handle
 17:      *
 18:      * @var resource
 19:      */
 20:     protected $_stream;
 21: 
 22:     /**
 23:      *
 24:      * @var Horde_Imsp_Auth_Base
 25:      */
 26:     protected $_authObj;
 27: 
 28:     /**
 29:      * Constructor function.
 30:      * Required parameters:
 31:      *<pre>
 32:      *  authObj  <Horde_Imsp_Auth>  The object to handle the authentication
 33:      *</pre>
 34:      *
 35:      * Optional parameters:
 36:      *<pre>
 37:      *  server   <string>           The IMSP host
 38:      *  port     <string>           The port the IMSP server listens on
 39:      *  logger  <Horde_Log_Logger>  The logger.
 40:      *</pre>
 41:      * @param array $params Hash containing server parameters.
 42:      */
 43:     public function __construct(array $params)
 44:     {
 45:         parent::__construct($params);
 46:         $this->_imspOpen();
 47:         $this->_logger->debug('Initializing Horde_Imsp object.');
 48:     }
 49: 
 50:     /**
 51:      * Attempts to login to IMSP server.
 52:      *
 53:      * @param boolean $login   Should we remain logged in after auth?
 54:      *
 55:      * @return boolean
 56:      */
 57:     public function authenticate($login = true)
 58:     {
 59:         if (!$this->_authObj->authenticate($this, $login)) {
 60:             return false;
 61:         }
 62: 
 63:         return true;
 64:     }
 65: 
 66:     /**
 67:      * Logs out of the server and closes the IMSP stream
 68:      */
 69:     public function logout()
 70:     {
 71:         $this->_logger->debug('Closing IMSP Connection.');
 72:         $command_string = 'LOGOUT';
 73:         $this->send($command_string);
 74:         fclose($this->_stream);
 75:     }
 76: 
 77:     /**
 78:      * Returns the raw capability response from the server.
 79:      *
 80:      * @return string  The raw capability response.
 81:      * @throws Horde_Imsp_Exception
 82:      */
 83:     public function capability()
 84:     {
 85:         $command_string = 'CAPABILITY';
 86:         $this->send($command_string);
 87:         $server_response = $this->receive();
 88:         if (preg_match("/^\* CAPABILITY/", $server_response)) {
 89:             $capability = preg_replace("/^\* CAPABILITY/", '', $server_response);
 90:             $server_response = $this->receive(); //OK
 91:             if (!$server_response == 'OK') {
 92:                 $this->_logger->err('Did not receive the expected response from the server.');
 93:                 throw new Horde_Imsp_Exception('Did not receive the expected response from the server.');
 94:             } else {
 95:                 $this->_logger->debug('CAPABILITY completed OK');
 96:                 return $capability;
 97:             }
 98:         }
 99:     }
100: 
101:     /**
102:      * Attempts to send a command to the server.
103:      *
104:      * @param string  $commandText   Text to send to the server.
105:      * @param boolean $includeTag    Determines if command tag is prepended.
106:      * @param boolean  $sendCRLF     Determines if CRLF is appended.
107:      * @param boolean $continuation  Expect a command continuation response.
108:      *
109:      * @throws Horde_Imsp_Exception
110:      */
111:     public function send($commandText, $includeTag = true, $sendCRLF = true, $continuation = false)
112:     {
113:         $command_text = '';
114: 
115:         if (!$this->_stream) {
116:             throw new Horde_Imsp_Exception('No IMSP connection in place');
117:         }
118: 
119:         if ($includeTag) {
120:             $this->_tag = $this->_getNextCommandTag();
121:             $command_text = "$this->_tag ";
122:         }
123:         $command_text .= $commandText;
124: 
125:         if ($sendCRLF) {
126:             $command_text .= "\r\n";
127:         }
128: 
129:         $this->_logger->debug('C: ' . $command_text);
130:         if (!fputs($this->_stream, $command_text)) {
131:             $this->_logger->err('Connection to IMSP host failed.');
132:             fclose($this->_stream);
133:             throw new Horde_Imsp_Exception('Connection to IMSP host failed');
134:         }
135: 
136:         if ($continuation && !preg_match("/^\+/", $this->receive())) {
137:             $this->_logger->err('Did not receive expected command continuation response from IMSP server.');
138:             throw new Horde_Imsp_Exception('Did not receive expected command continuation response from IMSP server.');
139:         }
140:     }
141: 
142:     /**
143:      * Receives a single CRLF terminated server response string
144:      *
145:      * @return mixed 'NO', 'BAD', 'OK', raw response.
146:      * @throws Horde_Imsp_Exception
147:      */
148:     public function receive()
149:     {
150:         if (!$this->_stream) {
151:             throw new Horde_Imsp_Exception('No IMSP connection in place.');
152:         }
153:         $result = fgets($this->_stream, 512);
154:         if (!$result) {
155:             $this->_logger->err('Did not receive the expected response from the server.');
156:             throw new Horde_Imsp_Exception('Did not receive the expected response from the server.');
157:         }
158:         $meta = stream_get_meta_data($this->_stream);
159:         if ($meta['timed_out']) {
160:             $this->_logger->err('Connection timed out.');
161:             throw new Horde_Imsp_Exception(Horde_Imsp_Translation::t('Connection timed out!'));
162:         }
163: 
164:         $server_response = trim($result);
165:         $this->_logger->debug('S: ' . $server_response);
166: 
167:         /* Parse out the response:
168:          * First make sure that this is not for a previous command.
169:          * If it is, it means we did not read all the server responses from
170:          * the last command...read them now, but throw an error. */
171:         while (preg_match("/^" . $this->_lastCommandTag . "/", $server_response)) {
172:             $server_response = trim(fgets($this->_stream, 512));
173:             throw new Horde_Imsp_Exception('Did not receive the expected response from the server: ' . $server_response);
174:         }
175: 
176:         $currentTag = $this->_tag;
177:         if (preg_match("/^" . $currentTag . " NO/", $server_response)) {
178:             $this->lastRawError = $server_response;
179:             return 'NO';
180:         }
181: 
182:         if (preg_match("/^" . $currentTag . " BAD/", $server_response)) {
183:             $this->_logger->err('The IMSP server did not understand your request.');
184:             $this->lastRawError = $server_response;
185:             return 'BAD';
186:         }
187: 
188:         if (preg_match("/^" . $currentTag . " OK/", $server_response)) {
189:             return 'OK';
190:         }
191: 
192:         /* If it was not a 'NO', 'BAD' or 'OK' response,
193:          * then it's up to the calling function to decide
194:          * what to do with it. */
195:         return $server_response;
196:     }
197: 
198:     /**
199:      * Retrieves CRLF terminated response from server and splits it into
200:      * an array delimited by a <space>.
201:      *
202:      * @return array The exploded string
203:      */
204:     public function getServerResponseChunks()
205:     {
206:         $server_response = trim(fgets($this->_stream, 512));
207:         $chunks = explode(' ', $server_response);
208: 
209:         return $chunks;
210:     }
211: 
212:     /**
213:      * Receives fixed number of bytes from IMSP socket. Used when server returns
214:      * a string literal.
215:      *
216:      * @param integer $length  Number of bytes to read from socket.
217:      *
218:      * @return string  Text of string literal.
219:      */
220:     public function receiveStringLiteral($length)
221:     {
222:         $literal = '';
223:         do {
224:             $temp = fread($this->_stream, $length);
225:             $length -= strlen($temp);
226:             $literal .= $temp;
227:         } while ($length > 0 && strlen($temp));
228:         $this->_logger->debug('From{}: ' . $literal);
229: 
230:         return $literal;
231:     }
232: 
233:     /**
234:      * Attempts to open an IMSP socket with the server.
235:      *
236:      * @throws Horde_Imsp_Exception
237:      */
238:     protected function _imspOpen()
239:     {
240:         $fp = @fsockopen($this->host, $this->port);
241:         if (!$fp) {
242:             $this->_logger->err('Connection to IMSP host failed.');
243:             throw new Horde_Imsp_Exception('Connection to IMSP host failed.');
244:         }
245:         $this->_stream = $fp;
246:         $server_response = $this->receive();
247:         if (!preg_match("/^\* OK/", $server_response)) {
248:             fclose($fp);
249:             $this->_logger->err('Did not receive the expected response from the server.');
250:         }
251:     }
252: 
253: }
API documentation generated by ApiGen