source: trunk/instant_messenger/bkp/instant_messenger_64/inc/Jabber.abstract.php @ 151

Revision 151, 10.6 KB checked in by niltonneto, 16 years ago (diff)

Commit da nova versão do módulo, usando agente em C.
Vide Página do módulo do Trac:
http://www.expressolivre.org/dev/wiki/messenger

A versão anterior encontra-se na subpasta bkp (32/64).

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         $this->blocking($this->_socket, 0);
73                       
74                        $xml = $this->read();
75         
76         if ( $xml === false )
77            throw new Exception('[connect] #1 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
78         
79         if ( preg_match('/(<starttls .*<required\/><\/starttls>)/', $xml, $matches) )
80         {
81            if ( !$this->starttls() )
82               throw new Exception('[connect] #2 it isn\'t possible start tls. File: ' . __FILE__ . '  ::  ' . __LINE__);
83         }
84         else
85                        {
86            if ( !$this->_plain() )
87               throw new Exception('[connect] #3 it isn\'t possible carry out the verification. File: ' . __FILE__ . '  ::  ' . __LINE__);
88                        }
89
90         return true;
91      }
92      catch(Exception $e)
93      {
94         $this->writeLog('ERROR', $e->getMessage());
95         $this->_disconnect();
96         return false;
97      }
98   }
99
100   protected final function _disconnect()
101   {
102      try
103      {
104         $xml = "</stream:stream>";
105
106         if ( $this->write($xml) === false )
107            throw new Exception('[disconnect] #1 Cannot write to socket (' . $this->_socket . '). File: ' . __FILE__ . '  ::  ' . __LINE__);
108
109         if ( ($xml = $this->read()) === false )
110            throw new Exception('[disconnect] #2 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
111      }
112      catch(Exception $e)
113      {
114         $this->writeLog('ERROR', $e->getMessage());
115         return false;
116      }
117   }
118
119   private final function starttls()
120   {
121      try
122      {
123         $xml = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>";
124         
125         if ( $this->write($xml) === false )
126            throw new Exception('[starttls] #1 Cannot write to socket (' . $this->_socket . '). File: ' . __FILE__ . '  ::  ' . __LINE__);
127
128         if ( ($xml = $this->read()) === false )
129            throw new Exception('[starttls] #2 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
130
131         if ( !preg_match('/<proceed.*\/>/', $xml, $matches) )
132            throw new Exception('[starttls] #3 can\'t start tls in the socket ' .$this->_socket . '. File: ' . __FILE__ . '  ::  ' . __LINE__);
133
134                   stream_socket_enable_crypto($this->_socket, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT);
135
136         $xml  = "<?xml version='1.0' encoding='UTF-8'?>";
137         $xml .= "<stream:stream to='" . $this->_server . "' xmlns='jabber:client' ";
138         $xml .= "xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>";
139         if ( $this->write($xml) === false )
140            throw new Exception('[starttls] #4 Cannot write to socket (' . $this->_socket . '). File: ' . __FILE__ . '  ::  ' . __LINE__);
141
142         usleep(90000);
143         $this->blocking($this->_socket, 0);
144
145         if ( ($xml = $this->read()) === false )
146            throw new Exception('[starttls] #5 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
147
148         if ( !$this->_plain() )
149            throw new Exception('[starttls] #6 it isn\'t possible carry out the verification. File: ' . __FILE__ . '  ::  ' . __LINE__);
150
151         return true;
152      }
153      catch(Exception $e)
154      {
155         $this->writeLog('ERROR', $e->getMessage());
156         return false;
157      }
158   }
159
160   private final function _plain()
161   {
162      try
163      {
164                        //$this->blocking($this->_socket, 1);
165
166         if ( ($xml = $this->read()) === false )
167            throw new Exception('[_plain] #1 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
168
169         $xml  = "<username>" . $this->_username . "</username>";
170         $xml .= "<password>" . $this->_password . "</password>";
171         $xml .= "<resource>" . $this->_resource . "</resource>";
172
173         unset($this->_password);
174
175         if ( !$this->iq('set', 'auth_1', NULL, NULL, "jabber:iq:auth", $xml) )
176            throw new Exception('[_plain] #2 it isn\'t possible carry out the verification. File: ' . __FILE__ . '  ::  ' . __LINE__);
177
178         while ( !preg_match("/<iq xmlns='jabber:client' id='auth_1' type='(result|error)'/", ($readSocket = $this->read()), $matches) )
179                   usleep(10000);
180
181                        if($matches[1] == "error")
182                                return false;
183
184         if ( ($xml = $this->read()) === false )
185            throw new Exception('[_plain] #3 it isn\'t possible read the socket. File: ' . __FILE__ . '  ::  ' . __LINE__);
186
187         return true;
188      }
189      catch(Exception $e)
190      {
191         $this->writeLog('ERROR', $e->getMessage());
192         return false;
193      }
194   }
195
196        private final function _iq($pType = false, $pId = false, $pTo = false, $pFrom = false, $pXmlns = false, $pLoad = false )
197        {
198                $xml  = "<iq type='" . $pType . "' id='" . $pId . "'";
199                $xml .= ( $pTo ) ? " to='" . $pTo . "'" : "";
200                $xml .= ( $pFrom ) ? " from='" . $pFrom . "'" : "";
201
202                if ( $pXmlns == "vcard-temp" )
203      {
204                        $xml .= ">";
205                        $xml .= $pLoad;
206                }
207      else
208      {
209                        $xml .= "><query xmlns='" . $pXmlns . "'";
210                        $xml .= ( $pLoad ) ? ">" . $pLoad . "</query>" : "/>";
211                }
212
213                $xml .= "</iq>";
214               
215                return $xml;   
216        }
217
218   protected final function iq($pType = false, $pId = false, $pTo = false, $pFrom = false, $pXmlns = false, $pLoad = false)
219   {
220      try
221      {
222         if ( !preg_match("/^(get|set|result|error)$/i", $pType, $matches) )
223            throw new Exception('[iq] #1 type must be GET, SET, RESULT or ERROR. File: ' . __FILE__ . '  ::  ' . __LINE__);
224
225                   if ( $this->write($this->_iq($pType, $pId, $pTo, $pFrom, $pXmlns, $pLoad)) === false )
226            throw new Exception('[iq] #2 Cannot write to socket (' . $this->_socket . '). File: ' . __FILE__ . '  ::  ' . __LINE__);
227         else
228            return true;
229      }
230      catch(Exception $e)
231      {
232         $this->writeLog('ERROR', $e->getMessage());
233         return false;
234      }
235   }
236
237        protected final function presence($pType = false, $pTo = false, $pShow = false, $pStatus = false, $pPriority = false)
238        {
239      try
240      {
241         $xml  = "<presence";
242         $xml .= ($pTo)   ? " to='{$pTo}'" : '';
243         $xml .= ($pType) ? " type='{$pType}'" : '';
244         
245         if ( !($pStatus || $pShow || $pPriority) )
246                                $xml .= "/>";
247                        else
248                        {
249                         $xml .= ">";
250                 $xml .= ($pStatus) ? "<status>" . $pStatus . "</status>" : '';
251                 $xml .= ($pShow) ? "<show>" . $pShow . "</show>" : '';
252                 $xml .= ($pPriority) ? "<priority>" . $pPriority . "</priority>" : '';
253                 $xml .= ($pStatus || $pShow || $pPriority) ? "</presence>" : '';
254                        }
255
256         if ( $this->write($xml) === false )
257            throw new Exception('[presence] #1 it isn\'t possible send presence for ' . $this->_server . '. File: ' . __FILE__ . '  ::  ' . __LINE__);
258
259         return true;
260      }
261      catch(Exception $e)
262      {
263         $this->writeLog('ERROR', $e->getMessage());
264         return false;
265      }
266        }
267
268   protected final function read()
269   {
270      $return = NULL;
271      do
272      {
273         $line = NULL;
274         $line = utf8_decode(parent::read($this->_socket, 4096));
275
276         if ( $line === false )
277         {
278            $return = false;
279            break;
280         }
281
282         if ( $line != NULL )
283            $return .= $line ;
284      }
285      while ( $line != NULL );
286
287      return $return;
288   }
289
290        protected final function write($pData = false)
291   {
292      if ( !$pData )
293         return false;
294
295      return parent::write($this->_socket, utf8_encode($pData));
296   }
297
298   protected final function writeLog($pType = false, $pLog = false)
299   {
300      if ( !defined('self::'.$pType) && !$pLog )
301         return false;
302
303      if ( !(bool)constant('self::J_'.$pType) && !(bool)constant('self::J_ALL') )
304         return false;
305
306      $log  = date('m/d/Y H:i:s');
307      $log .= ' [' . constant('self::'.$pType) . '] :: ';
308      $log .= $pLog . "\n";
309      if ( $fp = fopen (self::J_FILE, "a+") )
310      {
311         fwrite($fp, $log);
312         fclose($fp);
313      }
314   }
315}
316
317?>
Note: See TracBrowser for help on using the repository browser.