~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to www/php/phpBB3/includes/functions_jabber.php

  • Committer: William Grant
  • Date: 2009-02-23 23:47:02 UTC
  • mfrom: (1099.1.211 new-dispatch)
  • Revision ID: grantw@unimelb.edu.au-20090223234702-db4b1llly46ignwo
Merge from lp:~ivle-dev/ivle/new-dispatch.

Pretty much everything changes. Reread the setup docs. Backup your databases.
Every file is now in a different installed location, the configuration system
is rewritten, the dispatch system is rewritten, URLs are different, the
database is different, worksheets and exercises are no longer on the
filesystem, we use a templating engine, jail service protocols are rewritten,
we don't repeat ourselves, we have authorization rewritten, phpBB is gone,
and probably lots of other things that I cannot remember.

This is certainly the biggest commit I have ever made, and hopefully
the largest I ever will.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
/**
3
 
*
4
 
* @package phpBB3
5
 
* @version $Id: functions_jabber.php,v 1.40 2007/10/05 14:30:10 acydburn Exp $
6
 
* @copyright (c) 2007 phpBB Group
7
 
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8
 
*
9
 
*/
10
 
 
11
 
/**
12
 
* @ignore
13
 
*/
14
 
if (!defined('IN_PHPBB'))
15
 
{
16
 
        exit;
17
 
}
18
 
 
19
 
/**
20
 
*
21
 
* Jabber class from Flyspray project
22
 
*
23
 
* @version class.jabber2.php 1306 2007-06-21
24
 
* @copyright 2006 Flyspray.org
25
 
* @author Florian Schmitz (floele)
26
 
*
27
 
* Modified by Acyd Burn
28
 
*
29
 
* @package phpBB3
30
 
*/
31
 
class jabber
32
 
{
33
 
        var $connection = null;
34
 
        var $session = array();
35
 
        var $timeout = 10;
36
 
 
37
 
        var $server;
38
 
        var $port;
39
 
        var $username;
40
 
        var $password;
41
 
        var $use_ssl;
42
 
        var $resource = 'functions_jabber.phpbb.php';
43
 
 
44
 
        var $enable_logging;
45
 
        var $log_array;
46
 
 
47
 
        var $features = array();
48
 
 
49
 
        /**
50
 
        */
51
 
        function jabber($server, $port, $username, $password, $use_ssl = false)
52
 
        {
53
 
                $this->server                           = ($server) ? $server : 'localhost';
54
 
                $this->port                                     = ($port) ? $port : 5222;
55
 
                $this->username                         = $username;
56
 
                $this->password                         = $password;
57
 
                $this->use_ssl                          = ($use_ssl && $this->can_use_ssl()) ? true : false;
58
 
 
59
 
                // Change port if we use SSL
60
 
                if ($this->port == 5222 && $this->use_ssl)
61
 
                {
62
 
                        $this->port = 5223;
63
 
                }
64
 
 
65
 
                $this->enable_logging           = true;
66
 
                $this->log_array                        = array();
67
 
        }
68
 
 
69
 
        /**
70
 
        * Able to use the SSL functionality?
71
 
        */
72
 
        function can_use_ssl()
73
 
        {
74
 
                // Will not work with PHP >= 5.2.1 or < 5.2.3RC2 until timeout problem with ssl hasn't been fixed (http://bugs.php.net/41236)
75
 
                return ((version_compare(PHP_VERSION, '5.2.1', '<') || version_compare(PHP_VERSION, '5.2.3RC2', '>=')) && @extension_loaded('openssl')) ? true : false;
76
 
        }
77
 
 
78
 
        /**
79
 
        * Able to use TLS?
80
 
        */
81
 
        function can_use_tls()
82
 
        {
83
 
                if (!@extension_loaded('openssl') || !function_exists('stream_socket_enable_crypto') || !function_exists('stream_get_meta_data') || !function_exists('socket_set_blocking') || !function_exists('stream_get_wrappers'))
84
 
                {
85
 
                        return false;
86
 
                }
87
 
 
88
 
                /**
89
 
                * Make sure the encryption stream is supported
90
 
                * Also seem to work without the crypto stream if correctly compiled
91
 
 
92
 
                $streams = stream_get_wrappers();
93
 
 
94
 
                if (!in_array('streams.crypto', $streams))
95
 
                {
96
 
                        return false;
97
 
                }
98
 
                */
99
 
 
100
 
                return true;
101
 
        }
102
 
 
103
 
        /**
104
 
        * Sets the resource which is used. No validation is done here, only escaping.
105
 
        * @param string $name
106
 
        * @access public
107
 
        */
108
 
        function set_resource($name)
109
 
        {
110
 
                $this->resource = $name;
111
 
        }
112
 
 
113
 
        /**
114
 
        * Connect
115
 
        */
116
 
        function connect()
117
 
        {
118
 
/*              if (!$this->check_jid($this->username . '@' . $this->server))
119
 
                {
120
 
                        $this->add_to_log('Error: Jabber ID is not valid: ' . $this->username . '@' . $this->server);
121
 
                        return false;
122
 
                }*/
123
 
 
124
 
                $this->session['ssl'] = $this->use_ssl;
125
 
 
126
 
                if ($this->open_socket($this->server, $this->port, $this->use_ssl))
127
 
                {
128
 
                        $this->send("<?xml version='1.0' encoding='UTF-8' ?" . ">\n");
129
 
                        $this->send("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
130
 
                }
131
 
                else
132
 
                {
133
 
                        $this->add_to_log('Error: connect() #2');
134
 
                        return false;
135
 
                }
136
 
 
137
 
                // Now we listen what the server has to say...and give appropriate responses
138
 
                $this->response($this->listen());
139
 
                return true;
140
 
        }
141
 
 
142
 
        /**
143
 
        * Disconnect
144
 
        */
145
 
        function disconnect()
146
 
        {
147
 
                if ($this->connected())
148
 
                {
149
 
                        // disconnect gracefully
150
 
                        if (isset($this->session['sent_presence']))
151
 
                        {
152
 
                                $this->send_presence('offline', '', true);
153
 
                        }
154
 
 
155
 
                        $this->send('</stream:stream>');
156
 
                        $this->session = array();
157
 
                        return fclose($this->connection);
158
 
                }
159
 
 
160
 
                return false;
161
 
        }
162
 
 
163
 
        /**
164
 
        * Connected?
165
 
        */
166
 
        function connected()
167
 
        {
168
 
                return (is_resource($this->connection) && !feof($this->connection)) ? true : false;
169
 
        }
170
 
 
171
 
 
172
 
        /**
173
 
        * Initiates login (using data from contructor, after calling connect())
174
 
        * @access public
175
 
        * @return bool
176
 
        */
177
 
        function login()
178
 
        {
179
 
                if (!sizeof($this->features))
180
 
                {
181
 
                        $this->add_to_log('Error: No feature information from server available.');
182
 
                        return false;
183
 
                }
184
 
 
185
 
                return $this->response($this->features);
186
 
        }
187
 
 
188
 
        /**
189
 
        * Send data to the Jabber server
190
 
        * @param string $xml
191
 
        * @access public
192
 
        * @return bool
193
 
        */
194
 
        function send($xml)
195
 
        {
196
 
                if ($this->connected())
197
 
                {
198
 
                        $xml = trim($xml);
199
 
                        $this->add_to_log('SEND: '. $xml);
200
 
                        return fwrite($this->connection, $xml);
201
 
                }
202
 
                else
203
 
                {
204
 
                        $this->add_to_log('Error: Could not send, connection lost (flood?).');
205
 
                        return false;
206
 
                }
207
 
        }
208
 
 
209
 
        /**
210
 
        * OpenSocket
211
 
        * @param string $server host to connect to
212
 
        * @param int $port port number
213
 
        * @param bool $use_ssl use ssl or not
214
 
        * @access public
215
 
        * @return bool
216
 
        */
217
 
        function open_socket($server, $port, $use_ssl = false)
218
 
        {
219
 
                if (@function_exists('dns_get_record'))
220
 
                {
221
 
                        $record = @dns_get_record("_xmpp-client._tcp.$server", DNS_SRV);
222
 
                        if (!empty($record) && !empty($record[0]['target']))
223
 
                        {
224
 
                                $server = $record[0]['target'];
225
 
                        }
226
 
                }
227
 
 
228
 
                $server = $use_ssl ? 'ssl://' . $server : $server;
229
 
 
230
 
                if ($this->connection = @fsockopen($server, $port, $errorno, $errorstr, $this->timeout))
231
 
                {
232
 
                        socket_set_blocking($this->connection, 0);
233
 
                        socket_set_timeout($this->connection, 60);
234
 
 
235
 
                        return true;
236
 
                }
237
 
 
238
 
                // Apparently an error occured...
239
 
                $this->add_to_log('Error: open_socket() - ' . $errorstr);
240
 
                return false;
241
 
        }
242
 
 
243
 
        /**
244
 
        * Return log
245
 
        */
246
 
        function get_log()
247
 
        {
248
 
                if ($this->enable_logging && sizeof($this->log_array))
249
 
                {
250
 
                        return implode("<br /><br />", $this->log_array);
251
 
                }
252
 
 
253
 
                return '';
254
 
        }
255
 
 
256
 
        /**
257
 
        * Add information to log
258
 
        */
259
 
        function add_to_log($string)
260
 
        {
261
 
                if ($this->enable_logging)
262
 
                {
263
 
                        $this->log_array[] = utf8_htmlspecialchars($string);
264
 
                }
265
 
        }
266
 
 
267
 
        /**
268
 
        * Listens to the connection until it gets data or the timeout is reached.
269
 
        * Thus, it should only be called if data is expected to be received.
270
 
        * @access public
271
 
        * @return mixed either false for timeout or an array with the received data
272
 
        */
273
 
        function listen($timeout = 10, $wait = false)
274
 
        {
275
 
                if (!$this->connected())
276
 
                {
277
 
                        return false;
278
 
                }
279
 
 
280
 
                // Wait for a response until timeout is reached
281
 
                $start = time();
282
 
                $data = '';
283
 
 
284
 
                do
285
 
                {
286
 
                        $read = trim(fread($this->connection, 4096));
287
 
                        $data .= $read;
288
 
                }
289
 
                while (time() <= $start + $timeout && ($wait || $data == '' || $read != '' || (substr(rtrim($data), -1) != '>')));
290
 
 
291
 
                if ($data != '')
292
 
                {
293
 
                        $this->add_to_log('RECV: '. $data);
294
 
                        return $this->xmlize($data);
295
 
                }
296
 
                else
297
 
                {
298
 
                        $this->add_to_log('Timeout, no response from server.');
299
 
                        return false;
300
 
                }
301
 
        }
302
 
 
303
 
        /**
304
 
        * Initiates account registration (based on data used for contructor)
305
 
        * @access public
306
 
        * @return bool
307
 
        */
308
 
        function register()
309
 
        {
310
 
                if (!isset($this->session['id']) || isset($this->session['jid']))
311
 
                {
312
 
                        $this->add_to_log('Error: Cannot initiate registration.');
313
 
                        return false;
314
 
                }
315
 
 
316
 
                $this->send("<iq type='get' id='reg_1'><query xmlns='jabber:iq:register'/></iq>");
317
 
                return $this->response($this->listen());
318
 
        }
319
 
 
320
 
        /**
321
 
        * Sets account presence. No additional info required (default is "online" status)
322
 
        * @param $message online, offline...
323
 
        * @param $type dnd, away, chat, xa or nothing
324
 
        * @param $unavailable set this to true if you want to become unavailable
325
 
        * @access public
326
 
        * @return bool
327
 
        */
328
 
        function send_presence($message = '', $type = '', $unavailable = false)
329
 
        {
330
 
                if (!isset($this->session['jid']))
331
 
                {
332
 
                        $this->add_to_log('ERROR: send_presence() - Cannot set presence at this point, no jid given.');
333
 
                        return false;
334
 
                }
335
 
 
336
 
                $type = strtolower($type);
337
 
                $type = (in_array($type, array('dnd', 'away', 'chat', 'xa'))) ? '<show>'. $type .'</show>' : '';
338
 
 
339
 
                $unavailable = ($unavailable) ? " type='unavailable'" : '';
340
 
                $message = ($message) ? '<status>' . utf8_htmlspecialchars($message) .'</status>' : '';
341
 
 
342
 
                $this->session['sent_presence'] = !$unavailable;
343
 
 
344
 
                return $this->send("<presence$unavailable>" . $type . $message . '</presence>');
345
 
        }
346
 
 
347
 
        /**
348
 
        * This handles all the different XML elements
349
 
        * @param array $xml
350
 
        * @access public
351
 
        * @return bool
352
 
        */
353
 
        function response($xml)
354
 
        {
355
 
                if (!is_array($xml) || !sizeof($xml))
356
 
                {
357
 
                        return false;
358
 
                }
359
 
 
360
 
                // did we get multiple elements? do one after another
361
 
                // array('message' => ..., 'presence' => ...)
362
 
                if (sizeof($xml) > 1)
363
 
                {
364
 
                        foreach ($xml as $key => $value)
365
 
                        {
366
 
                                $this->response(array($key => $value));
367
 
                        }
368
 
                        return;
369
 
                }
370
 
                else
371
 
                {
372
 
                        // or even multiple elements of the same type?
373
 
                        // array('message' => array(0 => ..., 1 => ...))
374
 
                        if (sizeof(reset($xml)) > 1)
375
 
                        {
376
 
                                foreach (reset($xml) as $value)
377
 
                                {
378
 
                                        $this->response(array(key($xml) => array(0 => $value)));
379
 
                                }
380
 
                                return;
381
 
                        }
382
 
                }
383
 
 
384
 
                switch (key($xml))
385
 
                {
386
 
                        case 'stream:stream':
387
 
                                // Connection initialised (or after authentication). Not much to do here...
388
 
                                $this->session['id'] = $xml['stream:stream'][0]['@']['id'];
389
 
 
390
 
                                if (isset($xml['stream:stream'][0]['#']['stream:features']))
391
 
                                {
392
 
                                        // we already got all info we need
393
 
                                        $this->features = $xml['stream:stream'][0]['#'];
394
 
                                }
395
 
                                else
396
 
                                {
397
 
                                        $this->features = $this->listen();
398
 
                                }
399
 
 
400
 
                                // go on with authentication?
401
 
                                if (isset($this->features['stream:features'][0]['#']['bind']) || !empty($this->session['tls']))
402
 
                                {
403
 
                                        return $this->response($this->features);
404
 
                                }
405
 
                        break;
406
 
 
407
 
                        case 'stream:features':
408
 
                                // Resource binding after successful authentication
409
 
                                if (isset($this->session['authenticated']))
410
 
                                {
411
 
                                        // session required?
412
 
                                        $this->session['sess_required'] = isset($xml['stream:features'][0]['#']['session']);
413
 
 
414
 
                                        $this->send("<iq type='set' id='bind_1'>
415
 
                                                <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
416
 
                                                        <resource>" . utf8_htmlspecialchars($this->resource) . '</resource>
417
 
                                                </bind>
418
 
                                        </iq>');
419
 
                                        return $this->response($this->listen());
420
 
                                }
421
 
 
422
 
                                // Let's use TLS if SSL is not enabled and we can actually use it
423
 
                                if (!$this->session['ssl'] && $this->can_use_tls() && $this->can_use_ssl() && isset($xml['stream:features'][0]['#']['starttls']))
424
 
                                {
425
 
                                        $this->add_to_log('Switching to TLS.');
426
 
                                        $this->send("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\n");
427
 
                                        return $this->response($this->listen());
428
 
                                }
429
 
 
430
 
                                // Does the server support SASL authentication?
431
 
 
432
 
                                // I hope so, because we do (and no other method).
433
 
                                if (isset($xml['stream:features'][0]['#']['mechanisms'][0]['@']['xmlns']) && $xml['stream:features'][0]['#']['mechanisms'][0]['@']['xmlns'] == 'urn:ietf:params:xml:ns:xmpp-sasl')
434
 
                                {
435
 
                                        // Now decide on method
436
 
                                        $methods = array();
437
 
 
438
 
                                        foreach ($xml['stream:features'][0]['#']['mechanisms'][0]['#']['mechanism'] as $value)
439
 
                                        {
440
 
                                                $methods[] = $value['#'];
441
 
                                        }
442
 
 
443
 
                                        // we prefer DIGEST-MD5
444
 
                                        // we don't want to use plain authentication (neither does the server usually) if no encryption is in place
445
 
 
446
 
                                        // http://www.xmpp.org/extensions/attic/jep-0078-1.7.html
447
 
                                        // The plaintext mechanism SHOULD NOT be used unless the underlying stream is encrypted (using SSL or TLS)
448
 
                                        // and the client has verified that the server certificate is signed by a trusted certificate authority.
449
 
 
450
 
                                        if (in_array('DIGEST-MD5', $methods))
451
 
                                        {
452
 
                                                $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>");
453
 
                                        }
454
 
                                        else if (in_array('PLAIN', $methods) && ($this->session['ssl'] || !empty($this->session['tls'])))
455
 
                                        {
456
 
                                                $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>"
457
 
                                                        . base64_encode(chr(0) . $this->username . '@' . $this->server . chr(0) . $this->password) .
458
 
                                                        '</auth>');
459
 
                                        }
460
 
                                        else if (in_array('ANONYMOUS', $methods))
461
 
                                        {
462
 
                                                $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>");
463
 
                                        }
464
 
                                        else
465
 
                                        {
466
 
                                                // not good...
467
 
                                                $this->add_to_log('Error: No authentication method supported.');
468
 
                                                $this->disconnect();
469
 
                                                return false;
470
 
                                        }
471
 
 
472
 
                                        return $this->response($this->listen());
473
 
                                }
474
 
                                else
475
 
                                {
476
 
                                        // ok, this is it. bye.
477
 
                                        $this->add_to_log('Error: Server does not offer SASL authentication.');
478
 
                                        $this->disconnect();
479
 
                                        return false;
480
 
                                }
481
 
                        break;
482
 
 
483
 
                        case 'challenge':
484
 
                                // continue with authentication...a challenge literally -_-
485
 
                                $decoded = base64_decode($xml['challenge'][0]['#']);
486
 
                                $decoded = $this->parse_data($decoded);
487
 
 
488
 
                                if (!isset($decoded['digest-uri']))
489
 
                                {
490
 
                                        $decoded['digest-uri'] = 'xmpp/'. $this->server;
491
 
                                }
492
 
 
493
 
                                // better generate a cnonce, maybe it's needed
494
 
                                $str = '';
495
 
                                mt_srand((double)microtime()*10000000);
496
 
 
497
 
                                for ($i = 0; $i < 32; $i++)
498
 
                                {
499
 
                                        $str .= chr(mt_rand(0, 255));
500
 
                                }
501
 
                                $decoded['cnonce'] = base64_encode($str);
502
 
 
503
 
                                // second challenge?
504
 
                                if (isset($decoded['rspauth']))
505
 
                                {
506
 
                                        $this->send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>");
507
 
                                }
508
 
                                else
509
 
                                {
510
 
                                        // Make sure we only use 'auth' for qop (relevant for $this->encrypt_password())
511
 
                                        // If the <response> is choking up on the changed parameter we may need to adjust encrypt_password() directly
512
 
                                        if (isset($decoded['qop']) && $decoded['qop'] != 'auth' && strpos($decoded['qop'], 'auth') !== false)
513
 
                                        {
514
 
                                                $decoded['qop'] = 'auth';
515
 
                                        }
516
 
 
517
 
                                        $response = array(
518
 
                                                'username'      => $this->username,
519
 
                                                'response'      => $this->encrypt_password(array_merge($decoded, array('nc' => '00000001'))),
520
 
                                                'charset'       => 'utf-8',
521
 
                                                'nc'            => '00000001',
522
 
                                        );
523
 
 
524
 
                                        foreach (array('nonce', 'qop', 'digest-uri', 'realm', 'cnonce') as $key)
525
 
                                        {
526
 
                                                if (isset($decoded[$key]))
527
 
                                                {
528
 
                                                        $response[$key] = $decoded[$key];
529
 
                                                }
530
 
                                        }
531
 
 
532
 
                                        $this->send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" . base64_encode($this->implode_data($response)) . '</response>');
533
 
                                }
534
 
 
535
 
                                return $this->response($this->listen());
536
 
                        break;
537
 
 
538
 
                        case 'failure':
539
 
                                $this->add_to_log('Error: Server sent "failure".');
540
 
                                $this->disconnect();
541
 
                                return false;
542
 
                        break;
543
 
 
544
 
                        case 'proceed':
545
 
                                // continue switching to TLS
546
 
                                $meta = stream_get_meta_data($this->connection);
547
 
                                socket_set_blocking($this->connection, 1);
548
 
 
549
 
                                if (!stream_socket_enable_crypto($this->connection, true, STREAM_CRYPTO_METHOD_TLS_CLIENT))
550
 
                                {
551
 
                                        $this->add_to_log('Error: TLS mode change failed.');
552
 
                                        return false;
553
 
                                }
554
 
 
555
 
                                socket_set_blocking($this->connection, $meta['blocked']);
556
 
                                $this->session['tls'] = true;
557
 
 
558
 
                                // new stream
559
 
                                $this->send("<?xml version='1.0' encoding='UTF-8' ?" . ">\n");
560
 
                                $this->send("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
561
 
 
562
 
                                return $this->response($this->listen());
563
 
                        break;
564
 
 
565
 
                        case 'success':
566
 
                                // Yay, authentication successful.
567
 
                                $this->send("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
568
 
                                $this->session['authenticated'] = true;
569
 
 
570
 
                                // we have to wait for another response
571
 
                                return $this->response($this->listen());
572
 
                        break;
573
 
 
574
 
                        case 'iq':
575
 
                                // we are not interested in IQs we did not expect
576
 
                                if (!isset($xml['iq'][0]['@']['id']))
577
 
                                {
578
 
                                        return false;
579
 
                                }
580
 
 
581
 
                                // multiple possibilities here
582
 
                                switch ($xml['iq'][0]['@']['id'])
583
 
                                {
584
 
                                        case 'bind_1':
585
 
                                                $this->session['jid'] = $xml['iq'][0]['#']['bind'][0]['#']['jid'][0]['#'];
586
 
 
587
 
                                                // and (maybe) yet another request to be able to send messages *finally*
588
 
                                                if ($this->session['sess_required'])
589
 
                                                {
590
 
                                                        $this->send("<iq to='{$this->server}' type='set' id='sess_1'>
591
 
                                                                <session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
592
 
                                                                </iq>");
593
 
                                                        return $this->response($this->listen());
594
 
                                                }
595
 
 
596
 
                                                return true;
597
 
                                        break;
598
 
 
599
 
                                        case 'sess_1':
600
 
                                                return true;
601
 
                                        break;
602
 
 
603
 
                                        case 'reg_1':
604
 
                                                $this->send("<iq type='set' id='reg_2'>
605
 
                                                                <query xmlns='jabber:iq:register'>
606
 
                                                                        <username>" . utf8_htmlspecialchars($this->username) . "</username>
607
 
                                                                        <password>" . utf8_htmlspecialchars($this->password) . "</password>
608
 
                                                                </query>
609
 
                                                        </iq>");
610
 
                                                return $this->response($this->listen());
611
 
                                        break;
612
 
 
613
 
                                        case 'reg_2':
614
 
                                                // registration end
615
 
                                                if (isset($xml['iq'][0]['#']['error']))
616
 
                                                {
617
 
                                                        $this->add_to_log('Warning: Registration failed.');
618
 
                                                        return false;
619
 
                                                }
620
 
                                                return true;
621
 
                                        break;
622
 
 
623
 
                                        case 'unreg_1':
624
 
                                                return true;
625
 
                                        break;
626
 
 
627
 
                                        default:
628
 
                                                $this->add_to_log('Notice: Received unexpected IQ.');
629
 
                                                return false;
630
 
                                        break;
631
 
                                }
632
 
                        break;
633
 
 
634
 
                        case 'message':
635
 
                                // we are only interested in content...
636
 
                                if (!isset($xml['message'][0]['#']['body']))
637
 
                                {
638
 
                                        return false;
639
 
                                }
640
 
 
641
 
                                $message['body'] = $xml['message'][0]['#']['body'][0]['#'];
642
 
                                $message['from'] = $xml['message'][0]['@']['from'];
643
 
 
644
 
                                if (isset($xml['message'][0]['#']['subject']))
645
 
                                {
646
 
                                        $message['subject'] = $xml['message'][0]['#']['subject'][0]['#'];
647
 
                                }
648
 
                                $this->session['messages'][] = $message;
649
 
                        break;
650
 
 
651
 
                        default:
652
 
                                // hm...don't know this response
653
 
                                $this->add_to_log('Notice: Unknown server response (' . key($xml) . ')');
654
 
                                return false;
655
 
                        break;
656
 
                }
657
 
        }
658
 
 
659
 
        function send_message($to, $text, $subject = '', $type = 'normal')
660
 
        {
661
 
                if (!isset($this->session['jid']))
662
 
                {
663
 
                        return false;
664
 
                }
665
 
 
666
 
                if (!in_array($type, array('chat', 'normal', 'error', 'groupchat', 'headline')))
667
 
                {
668
 
                        $type = 'normal';
669
 
                }
670
 
 
671
 
                return $this->send("<message from='" . utf8_htmlspecialchars($this->session['jid']) . "' to='" . utf8_htmlspecialchars($to) . "' type='$type' id='" . uniqid('msg') . "'>
672
 
                        <subject>" . utf8_htmlspecialchars($subject) . "</subject>
673
 
                        <body>" . utf8_htmlspecialchars($text) . "</body>
674
 
                        </message>"
675
 
                );
676
 
        }
677
 
 
678
 
        /**
679
 
        * Encrypts a password as in RFC 2831
680
 
        * @param array $data Needs data from the client-server connection
681
 
        * @access public
682
 
        * @return string
683
 
        */
684
 
        function encrypt_password($data)
685
 
        {
686
 
                // let's me think about <challenge> again...
687
 
                foreach (array('realm', 'cnonce', 'digest-uri') as $key)
688
 
                {
689
 
                        if (!isset($data[$key]))
690
 
                        {
691
 
                                $data[$key] = '';
692
 
                        }
693
 
                }
694
 
 
695
 
                $pack = md5($this->username . ':' . $data['realm'] . ':' . $this->password);
696
 
 
697
 
                if (isset($data['authzid']))
698
 
                {
699
 
                        $a1 = pack('H32', $pack)  . sprintf(':%s:%s:%s', $data['nonce'], $data['cnonce'], $data['authzid']);
700
 
                }
701
 
                else
702
 
                {
703
 
                        $a1 = pack('H32', $pack)  . sprintf(':%s:%s', $data['nonce'], $data['cnonce']);
704
 
                }
705
 
 
706
 
                // should be: qop = auth
707
 
                $a2 = 'AUTHENTICATE:'. $data['digest-uri'];
708
 
 
709
 
                return md5(sprintf('%s:%s:%s:%s:%s:%s', md5($a1), $data['nonce'], $data['nc'], $data['cnonce'], $data['qop'], md5($a2)));
710
 
        }
711
 
 
712
 
        /**
713
 
        * parse_data like a="b",c="d",... or like a="a, b", c, d="e", f=g,...
714
 
        * @param string $data
715
 
        * @access public
716
 
        * @return array a => b ...
717
 
        */
718
 
        function parse_data($data)
719
 
        {
720
 
                $data = explode(',', $data);
721
 
                $pairs = array();
722
 
                $key = false;
723
 
 
724
 
                foreach ($data as $pair)
725
 
                {
726
 
                        $dd = strpos($pair, '=');
727
 
 
728
 
                        if ($dd)
729
 
                        {
730
 
                                $key = trim(substr($pair, 0, $dd));
731
 
                                $pairs[$key] = trim(trim(substr($pair, $dd + 1)), '"');
732
 
                        }
733
 
                        else if (strpos(strrev(trim($pair)), '"') === 0 && $key)
734
 
                        {
735
 
                                // We are actually having something left from "a, b" values, add it to the last one we handled.
736
 
                                $pairs[$key] .= ',' . trim(trim($pair), '"');
737
 
                                continue;
738
 
                        }
739
 
                }
740
 
 
741
 
                return $pairs;
742
 
        }
743
 
 
744
 
        /**
745
 
        * opposite of jabber::parse_data()
746
 
        * @param array $data
747
 
        * @access public
748
 
        * @return string
749
 
        */
750
 
        function implode_data($data)
751
 
        {
752
 
                $return = array();
753
 
                foreach ($data as $key => $value)
754
 
                {
755
 
                        $return[] = $key . '="' . $value . '"';
756
 
                }
757
 
                return implode(',', $return);
758
 
        }
759
 
 
760
 
        /**
761
 
        * xmlize()
762
 
        * @author Hans Anderson
763
 
        * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/
764
 
        */
765
 
        function xmlize($data, $skip_white = 1, $encoding = 'UTF-8')
766
 
        {
767
 
                $data = trim($data);
768
 
 
769
 
                if (substr($data, 0, 5) != '<?xml')
770
 
                {
771
 
                        // mod
772
 
                        $data = '<root>'. $data . '</root>';
773
 
                }
774
 
 
775
 
                $vals = $index = $array = array();
776
 
                $parser = xml_parser_create($encoding);
777
 
                xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
778
 
                xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, $skip_white);
779
 
                xml_parse_into_struct($parser, $data, $vals, $index);
780
 
                xml_parser_free($parser);
781
 
 
782
 
                $i = 0;
783
 
                $tagname = $vals[$i]['tag'];
784
 
 
785
 
                $array[$tagname][0]['@'] = (isset($vals[$i]['attributes'])) ? $vals[$i]['attributes'] : array();
786
 
                $array[$tagname][0]['#'] = $this->_xml_depth($vals, $i);
787
 
 
788
 
                if (substr($data, 0, 5) != '<?xml')
789
 
                {
790
 
                        $array = $array['root'][0]['#'];
791
 
                }
792
 
 
793
 
                return $array;
794
 
        }
795
 
 
796
 
        /**
797
 
        * _xml_depth()
798
 
        * @author Hans Anderson
799
 
        * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/
800
 
        */
801
 
        function _xml_depth($vals, &$i)
802
 
        {
803
 
                $children = array();
804
 
 
805
 
                if (isset($vals[$i]['value']))
806
 
                {
807
 
                        array_push($children, $vals[$i]['value']);
808
 
                }
809
 
 
810
 
                while (++$i < sizeof($vals))
811
 
                {
812
 
                        switch ($vals[$i]['type'])
813
 
                        {
814
 
                                case 'open':
815
 
 
816
 
                                        $tagname = (isset($vals[$i]['tag'])) ? $vals[$i]['tag'] : '';
817
 
                                        $size = (isset($children[$tagname])) ? sizeof($children[$tagname]) : 0;
818
 
 
819
 
                                        if (isset($vals[$i]['attributes']))
820
 
                                        {
821
 
                                                $children[$tagname][$size]['@'] = $vals[$i]['attributes'];
822
 
                                        }
823
 
 
824
 
                                        $children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i);
825
 
 
826
 
                                break;
827
 
 
828
 
                                case 'cdata':
829
 
                                        array_push($children, $vals[$i]['value']);
830
 
                                break;
831
 
 
832
 
                                case 'complete':
833
 
 
834
 
                                        $tagname = $vals[$i]['tag'];
835
 
                                        $size = (isset($children[$tagname])) ? sizeof($children[$tagname]) : 0;
836
 
                                        $children[$tagname][$size]['#'] = (isset($vals[$i]['value'])) ? $vals[$i]['value'] : array();
837
 
 
838
 
                                        if (isset($vals[$i]['attributes']))
839
 
                                        {
840
 
                                                $children[$tagname][$size]['@'] = $vals[$i]['attributes'];
841
 
                                        }
842
 
 
843
 
                                break;
844
 
 
845
 
                                case 'close':
846
 
                                        return $children;
847
 
                                break;
848
 
                        }
849
 
                }
850
 
 
851
 
                return $children;
852
 
        }
853
 
}
854
 
 
855
 
?>
 
 
b'\\ No newline at end of file'