source: tags/instant_messenger/inc/Jabber.abstract.php @ 305

Revision 305, 10.0 KB checked in by niltonneto, 16 years ago (diff)

Correçoes

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