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

Revision 151, 10.2 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).

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