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

Revision 216, 10.2 KB checked in by niltonneto, 16 years ago (diff)

Correções do módulo instant_messenger.
Ver WiKi? em: http://www.expressolivre.org/dev/wiki/messenger

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