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

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