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

Revision 55, 10.6 KB checked in by niltonneto, 17 years ago (diff)

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