source: trunk/instant_messenger/inc/Jabber.abstract.php @ 64

Revision 64, 10.7 KB checked in by niltonneto, 17 years ago (diff)

* empty log message *

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1<?php
2/*
3+-------------------------------------------------------------------------+
4|                                                                         |
5| @FILE:        Jabber.abstract.php                                       |
6| @ABSTRACT:    Jabber                                                    |
7| @EXTENDS:     Socket (Socket.class.php)                                 |
8|                                                                         |
9| @DATE:        Wed May,16 2007 08:18:59                                  |
10| @LAST_CHANGE: Wed May,16 2007 09:03:28                                  |
11|                                                                         |
12| @AUTHOR:      [NUTS] Rodrigo Souza - rodsouza@celepar.pr.gov.br         |
13|                                                                         |
14| @BRIEF:       Abstract class for connect with any Jabber server         |
15|                                                                         |
16+-------------------------------------------------------------------------+
17*/
18
19require_once 'Socket.abstract.php';
20
21abstract class Jabber extends Socket
22{
23   const J_FILE    = '/var/log/expresso/Jabber.log';
24   const J_ALL     = false;
25   const J_ERROR   = true;
26   const J_WARNING = true;
27   const J_NOTICE  = true;
28
29   const ALL     = 'ALL';
30   const ERROR   = 'ERROR';
31   const WARNING = 'WARNING';
32   const NOTICE  = 'NOTICE';
33
34   private final function _connect( $pUser = false, $pPassword = false )
35   {
36      try
37      {
38         if ( !preg_match('/^(.+)@(.+)\/(.+):(\d+)$/',$pUser, $matches) )
39            throw new Exception('[connect] #1 ' . $pUser . ' must be [USER]@[DOMAIN]/[RESOURCE]:[PORT] and [PORT] is integer. File: ' . __FILE__ . '  ::  ' . __LINE__);
40
41         list($subject, $USER, $SERVER, $RESOURCE, $PORT) = $matches;
42
43         if ( !($socket = $this->open('tcp://' . $SERVER . ':' . $PORT, 1, 1)) )
44            throw new Exception('[connect] #2 can\'t access tcp://' . $SERVER . ':' . $PORT . '. File: ' . __FILE__ . '  ::  ' . __LINE__);
45
46         $this->_socket = $socket;
47
48         $xml  = "<?xml version='1.0' encoding='UTF-8'?>";
49         $xml .= "<stream:stream to='" . $SERVER . "' xmlns='jabber:client' ";
50         $xml .= "xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>";
51
52         if ( $this->write($xml) === false )
53            throw new Exception('[connect] #3 it isn\'t possible write in the socket ' . $socket . '. File: ' . __FILE__ . '  ::  ' . __LINE__);
54
55         $this->_server = $SERVER;
56         $this->_username = $USER;
57         $this->_password = $pPassword;
58         $this->_resource = $RESOURCE;
59      }
60      catch(Exception $e)
61      {
62         $this->writeLog('ERROR', $e->getMessage());
63         return false;
64      }
65   }
66
67   protected function connect( $pUser = false, $pPassword = false )
68   {   
69      try
70      {
71         $this->_connect($pUser, $pPassword);
72                       
73         if ( ($xml = $this->read()) === false )
74            throw new Exception('[connect] #1 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
75         
76         if ( preg_match('/(<starttls .*<required\/><\/starttls>)/', $xml, $matches) )
77         {
78            if ( !$this->starttls() )
79               throw new Exception('[connect] #2 it isn\'t possible start tls. File: ' . __FILE__ . '  ::  ' . __LINE__);
80
81            # $this->writeLog('NOTICE', 'Connected TLS');
82         }
83         else
84                        {
85            if ( !$this->_plain() )
86               throw new Exception('[connect] #3 it isn\'t possible carry out the verification. File: ' . __FILE__ . '  ::  ' . __LINE__);
87                        }
88
89         return true;
90      }
91      catch(Exception $e)
92      {
93         $this->writeLog('ERROR', $e->getMessage());
94         $this->_disconnect();
95         return false;
96      }
97   }
98
99   protected final function _disconnect()
100   {
101      try
102      {
103         $xml = "</stream:stream>";
104
105         if ( $this->write($xml) === false )
106            throw new Exception('[disconnect] #1 Cannot write to socket (' . $this->_socket . '). File: ' . __FILE__ . '  ::  ' . __LINE__);
107
108         if ( ($xml = $this->read()) === false )
109            throw new Exception('[disconnect] #2 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
110      }
111      catch(Exception $e)
112      {
113         $this->writeLog('ERROR', $e->getMessage());
114         return false;
115      }
116   }
117
118   private final function starttls()
119   {
120      try
121      {
122         $xml = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>";
123         if ( $this->write($xml) === false )
124            throw new Exception('[starttls] #1 Cannot write to socket (' . $this->_socket . '). File: ' . __FILE__ . '  ::  ' . __LINE__);
125
126         if ( ($xml = $this->read()) === false )
127            throw new Exception('[starttls] #2 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
128
129         if ( !preg_match('/<proceed.*\/>/', $xml, $matches) )
130            throw new Exception('[starttls] #3 can\'t start tls in the socket ' .$this->_socket . '. File: ' . __FILE__ . '  ::  ' . __LINE__);
131
132                   stream_socket_enable_crypto($this->_socket, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT);
133
134         $xml  = "<?xml version='1.0' encoding='UTF-8'?>";
135         $xml .= "<stream:stream to='" . $this->_server . "' xmlns='jabber:client' ";
136         $xml .= "xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>";
137         if ( $this->write($xml) === false )
138            throw new Exception('[starttls] #4 Cannot write to socket (' . $this->_socket . '). File: ' . __FILE__ . '  ::  ' . __LINE__);
139
140         usleep(90000);
141         $this->blocking($this->_socket, 0);
142
143         if ( ($xml = $this->read()) === false )
144            throw new Exception('[starttls] #5 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
145
146         if ( !$this->_plain() )
147            throw new Exception('[starttls] #6 it isn\'t possible carry out the verification. File: ' . __FILE__ . '  ::  ' . __LINE__);
148
149         return true;
150      }
151      catch(Exception $e)
152      {
153         $this->writeLog('ERROR', $e->getMessage());
154         return false;
155      }
156   }
157
158   private final function _plain()
159   {
160      try
161      {
162         $this->blocking($this->_socket, 0);
163
164         if ( ($xml = $this->read()) === false )
165            throw new Exception('[_plain] #1 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
166
167         $xml  = "<username>" . $this->_username . "</username>";
168         $xml .= "<password>" . $this->_password . "</password>";
169         $xml .= "<resource>" . $this->_resource . "</resource>";
170
171         unset($this->_password);
172
173         if ( !$this->iq('set', 'auth_1', NULL, NULL, "jabber:iq:auth", $xml) )
174            throw new Exception('[_plain] #2 it isn\'t possible carry out the verification. File: ' . __FILE__ . '  ::  ' . __LINE__);
175
176         while ( !preg_match("/<iq xmlns='jabber:client' id='auth_1' type='(result|error)'/", ($readSocket = $this->read()), $matches) )
177                   usleep(10000);
178
179                        if($matches[1] == "error")
180                                return false;
181
182         if ( ($xml = $this->read()) === false )
183            throw new Exception('[_plain] #3 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
184
185         return true;
186      }
187      catch(Exception $e)
188      {
189         $this->writeLog('ERROR', $e->getMessage());
190         return false;
191      }
192   }
193
194        private final function _iq($pType = false, $pId = false, $pTo = false, $pFrom = false, $pXmlns = false, $pLoad = false )
195        {
196                $xml  = "<iq type='" . $pType . "' id='" . $pId . "'";
197                $xml .= ( $pTo ) ? " to='" . $pTo . "'" : "";
198                $xml .= ( $pFrom ) ? " from='" . $pFrom . "'" : "";
199
200                if ( $pXmlns == "vcard-temp" )
201      {
202                        $xml .= ">";
203                        $xml .= $pLoad;
204                }
205      else
206      {
207                        $xml .= "><query xmlns='" . $pXmlns . "'";
208                        $xml .= ( $pLoad ) ? ">" . $pLoad . "</query>" : "/>";
209                }
210
211                $xml .= "</iq>";
212               
213                return $xml;   
214        }
215
216   protected final function iq($pType = false, $pId = false, $pTo = false, $pFrom = false, $pXmlns = false, $pLoad = false)
217   {
218      try
219      {
220         if ( !preg_match("/^(get|set|result|error)$/i", $pType, $matches) )
221            throw new Exception('[iq] #1 type must be GET, SET, RESULT or ERROR. File: ' . __FILE__ . '  ::  ' . __LINE__);
222
223                   if ( $this->write($this->_iq($pType, $pId, $pTo, $pFrom, $pXmlns, $pLoad)) === false )
224            throw new Exception('[iq] #2 Cannot write to socket (' . $this->_socket . '). File: ' . __FILE__ . '  ::  ' . __LINE__);
225         else
226            return true;
227      }
228      catch(Exception $e)
229      {
230         $this->writeLog('ERROR', $e->getMessage());
231         return false;
232      }
233   }
234
235        protected final function presence($pType = false, $pTo = false, $pShow = false, $pStatus = false, $pPriority = false)
236        {
237      try
238      {
239         $xml  = "<presence";
240         $xml .= ($pTo)   ? " to='{$pTo}'" : '';
241         $xml .= ($pType) ? " type='{$pType}'" : '';
242         
243         //$xml .= ($pStatus || $pShow || $pPriority) ? ">" : "/>";
244         if ( !($pStatus || $pShow || $pPriority) )
245                                $xml .= "/>";
246                        else
247                        {
248                         $xml .= ">";
249                 $xml .= ($pStatus) ? "<status>" . $pStatus . "</status>" : '';
250                 $xml .= ($pShow) ? "<show>" . $pShow . "</show>" : '';
251                 $xml .= ($pPriority) ? "<priority>" . $pPriority . "</priority>" : '';
252                 $xml .= ($pStatus || $pShow || $pPriority) ? "</presence>" : '';
253                        }
254
255         if ( $this->write($xml) === false )
256            throw new Exception('[presence] #1 it isn\'t possible send presence for ' . $this->_server . '. File: ' . __FILE__ . '  ::  ' . __LINE__);
257
258         return true;
259      }
260      catch(Exception $e)
261      {
262         $this->writeLog('ERROR', $e->getMessage());
263         return false;
264      }
265        }
266
267   protected final function read()
268   {
269      $return = NULL;
270      do
271      {
272         $line = NULL;
273         $line = utf8_decode(parent::read($this->_socket, 4096));
274
275         if ( $line === false )
276         {
277            $return = false;
278            break;
279         }
280
281         if ( $line != NULL )
282            $return .= $line;// . "\n";
283      }
284      while ( $line != NULL );
285
286      return $return;
287   }
288
289        protected final function write($pData = false)
290   {
291      if ( !$pData )
292         return false;
293
294      return parent::write($this->_socket, utf8_encode($pData));
295   }
296
297   protected final function writeLog($pType = false, $pLog = false)
298   {
299      if ( !defined('self::'.$pType) && !$pLog )
300         return false;
301
302      if ( !(bool)constant('self::J_'.$pType) && !(bool)constant('self::J_ALL') )
303         return false;
304
305      $log  = date('m/d/Y H:i:s');
306      $log .= ' [' . constant('self::'.$pType) . '] :: ';
307      $log .= $pLog . "\n";
308      if ( $fp = fopen (self::J_FILE, "a+") )
309      {
310         fwrite($fp, $log);
311         fclose($fp);
312      }
313   }
314}
315
316?>
Note: See TracBrowser for help on using the repository browser.