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

« back to all changes in this revision

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

Merge setup-stuff.

phpBB is gone, configuration, setup and jail building are completely redone.

Please read doc/setup/install_proc.txt, or you'll not get far.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
/**
3
 
*
4
 
* @package phpBB3
5
 
* @version $Id: functions_messenger.php,v 1.102 2007/11/17 20:03:32 acydburn Exp $
6
 
* @copyright (c) 2005 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
 
* Messenger
21
 
* @package phpBB3
22
 
*/
23
 
class messenger
24
 
{
25
 
        var $vars, $msg, $extra_headers, $replyto, $from, $subject;
26
 
        var $addresses = array();
27
 
 
28
 
        var $mail_priority = MAIL_NORMAL_PRIORITY;
29
 
        var $use_queue = true;
30
 
        var $tpl_msg = array();
31
 
 
32
 
        /**
33
 
        * Constructor
34
 
        */
35
 
        function messenger($use_queue = true)
36
 
        {
37
 
                global $config;
38
 
 
39
 
                $this->use_queue = (!$config['email_package_size']) ? false : $use_queue;
40
 
                $this->subject = '';
41
 
        }
42
 
 
43
 
        /**
44
 
        * Resets all the data (address, template file, etc etc) to default
45
 
        */
46
 
        function reset()
47
 
        {
48
 
                $this->addresses = $this->extra_headers = array();
49
 
                $this->vars = $this->msg = $this->replyto = $this->from = '';
50
 
                $this->mail_priority = MAIL_NORMAL_PRIORITY;
51
 
        }
52
 
 
53
 
        /**
54
 
        * Sets an email address to send to
55
 
        */
56
 
        function to($address, $realname = '')
57
 
        {
58
 
                global $config;
59
 
 
60
 
                $pos = isset($this->addresses['to']) ? sizeof($this->addresses['to']) : 0;
61
 
 
62
 
                $this->addresses['to'][$pos]['email'] = trim($address);
63
 
 
64
 
                // If empty sendmail_path on windows, PHP changes the to line
65
 
                if (!$config['smtp_delivery'] && DIRECTORY_SEPARATOR == '\\')
66
 
                {
67
 
                        $this->addresses['to'][$pos]['name'] = '';
68
 
                }
69
 
                else
70
 
                {
71
 
                        $this->addresses['to'][$pos]['name'] = trim($realname);
72
 
                }
73
 
        }
74
 
 
75
 
        /**
76
 
        * Sets an cc address to send to
77
 
        */
78
 
        function cc($address, $realname = '')
79
 
        {
80
 
                $pos = isset($this->addresses['cc']) ? sizeof($this->addresses['cc']) : 0;
81
 
                $this->addresses['cc'][$pos]['email'] = trim($address);
82
 
                $this->addresses['cc'][$pos]['name'] = trim($realname);
83
 
        }
84
 
 
85
 
        /**
86
 
        * Sets an bcc address to send to
87
 
        */
88
 
        function bcc($address, $realname = '')
89
 
        {
90
 
                $pos = isset($this->addresses['bcc']) ? sizeof($this->addresses['bcc']) : 0;
91
 
                $this->addresses['bcc'][$pos]['email'] = trim($address);
92
 
                $this->addresses['bcc'][$pos]['name'] = trim($realname);
93
 
        }
94
 
 
95
 
        /**
96
 
        * Sets a im contact to send to
97
 
        */
98
 
        function im($address, $realname = '')
99
 
        {
100
 
                $pos = isset($this->addresses['im']) ? sizeof($this->addresses['im']) : 0;
101
 
                $this->addresses['im'][$pos]['uid'] = trim($address);
102
 
                $this->addresses['im'][$pos]['name'] = trim($realname);
103
 
        }
104
 
 
105
 
        /**
106
 
        * Set the reply to address
107
 
        */
108
 
        function replyto($address)
109
 
        {
110
 
                $this->replyto = trim($address);
111
 
        }
112
 
 
113
 
        /**
114
 
        * Set the from address
115
 
        */
116
 
        function from($address)
117
 
        {
118
 
                $this->from = trim($address);
119
 
        }
120
 
 
121
 
        /**
122
 
        * set up subject for mail
123
 
        */
124
 
        function subject($subject = '')
125
 
        {
126
 
                $this->subject = trim($subject);
127
 
        }
128
 
 
129
 
        /**
130
 
        * set up extra mail headers
131
 
        */
132
 
        function headers($headers)
133
 
        {
134
 
                $this->extra_headers[] = trim($headers);
135
 
        }
136
 
 
137
 
        /**
138
 
        * Set the email priority
139
 
        */
140
 
        function set_mail_priority($priority = MAIL_NORMAL_PRIORITY)
141
 
        {
142
 
                $this->mail_priority = $priority;
143
 
        }
144
 
 
145
 
        /**
146
 
        * Set email template to use
147
 
        */
148
 
        function template($template_file, $template_lang = '')
149
 
        {
150
 
                global $config, $phpbb_root_path;
151
 
 
152
 
                if (!trim($template_file))
153
 
                {
154
 
                        trigger_error('No template file set', E_USER_ERROR);
155
 
                }
156
 
 
157
 
                if (!trim($template_lang))
158
 
                {
159
 
                        $template_lang = basename($config['default_lang']);
160
 
                }
161
 
 
162
 
                if (empty($this->tpl_msg[$template_lang . $template_file]))
163
 
                {
164
 
                        $tpl_file = "{$phpbb_root_path}language/$template_lang/email/$template_file.txt";
165
 
 
166
 
                        if (!file_exists($tpl_file))
167
 
                        {
168
 
                                trigger_error("Could not find email template file [ $tpl_file ]", E_USER_ERROR);
169
 
                        }
170
 
 
171
 
                        if (($data = @file_get_contents($tpl_file)) === false)
172
 
                        {
173
 
                                trigger_error("Failed opening template file [ $tpl_file ]", E_USER_ERROR);
174
 
                        }
175
 
 
176
 
                        $this->tpl_msg[$template_lang . $template_file] = $data;
177
 
                }
178
 
 
179
 
                $this->msg = $this->tpl_msg[$template_lang . $template_file];
180
 
 
181
 
                return true;
182
 
        }
183
 
 
184
 
        /**
185
 
        * assign variables to email template
186
 
        */
187
 
        function assign_vars($vars)
188
 
        {
189
 
                $this->vars = (empty($this->vars)) ? $vars : $this->vars + $vars;
190
 
        }
191
 
 
192
 
        /**
193
 
        * Send the mail out to the recipients set previously in var $this->addresses
194
 
        */
195
 
        function send($method = NOTIFY_EMAIL, $break = false)
196
 
        {
197
 
                global $config, $user;
198
 
 
199
 
                // We add some standard variables we always use, no need to specify them always
200
 
                $this->vars['U_BOARD'] = (!isset($this->vars['U_BOARD'])) ? generate_board_url() : $this->vars['U_BOARD'];
201
 
                $this->vars['EMAIL_SIG'] = (!isset($this->vars['EMAIL_SIG'])) ? str_replace('<br />', "\n", "-- \n" . htmlspecialchars_decode($config['board_email_sig'])) : $this->vars['EMAIL_SIG'];
202
 
                $this->vars['SITENAME'] = (!isset($this->vars['SITENAME'])) ? htmlspecialchars_decode($config['sitename']) : $this->vars['SITENAME'];
203
 
 
204
 
                // Escape all quotes, else the eval will fail.
205
 
                $this->msg = str_replace ("'", "\'", $this->msg);
206
 
                $this->msg = preg_replace('#\{([a-z0-9\-_]*?)\}#is', "' . ((isset(\$this->vars['\\1'])) ? \$this->vars['\\1'] : '') . '", $this->msg);
207
 
 
208
 
                eval("\$this->msg = '$this->msg';");
209
 
 
210
 
                // We now try and pull a subject from the email body ... if it exists,
211
 
                // do this here because the subject may contain a variable
212
 
                $drop_header = '';
213
 
                $match = array();
214
 
                if (preg_match('#^(Subject:(.*?))$#m', $this->msg, $match))
215
 
                {
216
 
                        $this->subject = (trim($match[2]) != '') ? trim($match[2]) : (($this->subject != '') ? $this->subject : $user->lang['NO_EMAIL_SUBJECT']);
217
 
                        $drop_header .= '[\r\n]*?' . preg_quote($match[1], '#');
218
 
                }
219
 
                else
220
 
                {
221
 
                        $this->subject = (($this->subject != '') ? $this->subject : $user->lang['NO_EMAIL_SUBJECT']);
222
 
                }
223
 
 
224
 
                if ($drop_header)
225
 
                {
226
 
                        $this->msg = trim(preg_replace('#' . $drop_header . '#s', '', $this->msg));
227
 
                }
228
 
 
229
 
                if ($break)
230
 
                {
231
 
                        return true;
232
 
                }
233
 
 
234
 
                switch ($method)
235
 
                {
236
 
                        case NOTIFY_EMAIL:
237
 
                                $result = $this->msg_email();
238
 
                        break;
239
 
 
240
 
                        case NOTIFY_IM:
241
 
                                $result = $this->msg_jabber();
242
 
                        break;
243
 
 
244
 
                        case NOTIFY_BOTH:
245
 
                                $result = $this->msg_email();
246
 
                                $this->msg_jabber();
247
 
                        break;
248
 
                }
249
 
 
250
 
                $this->reset();
251
 
                return $result;
252
 
        }
253
 
 
254
 
        /**
255
 
        * Add error message to log
256
 
        */
257
 
        function error($type, $msg)
258
 
        {
259
 
                global $user, $phpEx, $phpbb_root_path, $config;
260
 
 
261
 
                // Session doesn't exist, create it
262
 
                if (!isset($user->session_id) || $user->session_id === '')
263
 
                {
264
 
                        $user->session_begin();
265
 
                }
266
 
 
267
 
                $calling_page = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : $_ENV['PHP_SELF'];
268
 
 
269
 
                $message = '';
270
 
                switch ($type)
271
 
                {
272
 
                        case 'EMAIL':
273
 
                                $message = '<strong>EMAIL/' . (($config['smtp_delivery']) ? 'SMTP' : 'PHP/' . $config['email_function_name'] . '()') . '</strong>';
274
 
                        break;
275
 
 
276
 
                        default:
277
 
                                $message = "<strong>$type</strong>";
278
 
                        break;
279
 
                }
280
 
 
281
 
                $message .= '<br /><em>' . htmlspecialchars($calling_page) . '</em><br /><br />' . $msg . '<br />';
282
 
                add_log('critical', 'LOG_ERROR_' . $type, $message);
283
 
        }
284
 
 
285
 
        /**
286
 
        * Save to queue
287
 
        */
288
 
        function save_queue()
289
 
        {
290
 
                global $config;
291
 
 
292
 
                if ($config['email_package_size'] && $this->use_queue && !empty($this->queue))
293
 
                {
294
 
                        $this->queue->save();
295
 
                        return;
296
 
                }
297
 
        }
298
 
 
299
 
        /**
300
 
        * Return email header
301
 
        */
302
 
        function build_header($to, $cc, $bcc)
303
 
        {
304
 
                global $config;
305
 
 
306
 
                $headers = array();
307
 
 
308
 
                $headers[] = 'From: ' . $this->from;
309
 
 
310
 
                if ($cc)
311
 
                {
312
 
                        $headers[] = 'Cc: ' . $cc;
313
 
                }
314
 
 
315
 
                if ($bcc)
316
 
                {
317
 
                        $headers[] = 'Bcc: ' . $bcc;
318
 
                }
319
 
 
320
 
                $headers[] = 'Reply-To: ' . $this->replyto;
321
 
                $headers[] = 'Return-Path: <' . $config['board_email'] . '>';
322
 
                $headers[] = 'Sender: <' . $config['board_email'] . '>';
323
 
                $headers[] = 'MIME-Version: 1.0';
324
 
                $headers[] = 'Message-ID: <' . md5(unique_id(time())) . '@' . $config['server_name'] . '>';
325
 
                $headers[] = 'Date: ' . date('r', time());
326
 
                $headers[] = 'Content-Type: text/plain; charset=UTF-8'; // format=flowed
327
 
                $headers[] = 'Content-Transfer-Encoding: 8bit'; // 7bit
328
 
 
329
 
                $headers[] = 'X-Priority: ' . $this->mail_priority;
330
 
                $headers[] = 'X-MSMail-Priority: ' . (($this->mail_priority == MAIL_LOW_PRIORITY) ? 'Low' : (($this->mail_priority == MAIL_NORMAL_PRIORITY) ? 'Normal' : 'High'));
331
 
                $headers[] = 'X-Mailer: PhpBB3';
332
 
                $headers[] = 'X-MimeOLE: phpBB3';
333
 
                $headers[] = 'X-phpBB-Origin: phpbb://' . str_replace(array('http://', 'https://'), array('', ''), generate_board_url());
334
 
 
335
 
                // We use \n here instead of \r\n because our smtp mailer is adjusting it to \r\n automatically, whereby the php mail function only works
336
 
                // if using \n.
337
 
 
338
 
                if (sizeof($this->extra_headers))
339
 
                {
340
 
                        $headers[] = implode("\n", $this->extra_headers);
341
 
                }
342
 
 
343
 
                return implode("\n", $headers);
344
 
        }
345
 
 
346
 
        /**
347
 
        * Send out emails
348
 
        */
349
 
        function msg_email()
350
 
        {
351
 
                global $config, $user;
352
 
 
353
 
                if (empty($config['email_enable']))
354
 
                {
355
 
                        return false;
356
 
                }
357
 
 
358
 
                $use_queue = false;
359
 
                if ($config['email_package_size'] && $this->use_queue)
360
 
                {
361
 
                        if (empty($this->queue))
362
 
                        {
363
 
                                $this->queue = new queue();
364
 
                                $this->queue->init('email', $config['email_package_size']);
365
 
                        }
366
 
                        $use_queue = true;
367
 
                }
368
 
 
369
 
                if (empty($this->replyto))
370
 
                {
371
 
                        $this->replyto = '<' . $config['board_contact'] . '>';
372
 
                }
373
 
 
374
 
                if (empty($this->from))
375
 
                {
376
 
                        $this->from = '<' . $config['board_contact'] . '>';
377
 
                }
378
 
 
379
 
                // Build to, cc and bcc strings
380
 
                $to = $cc = $bcc = '';
381
 
                foreach ($this->addresses as $type => $address_ary)
382
 
                {
383
 
                        if ($type == 'im')
384
 
                        {
385
 
                                continue;
386
 
                        }
387
 
 
388
 
                        foreach ($address_ary as $which_ary)
389
 
                        {
390
 
                                $$type .= (($$type != '') ? ', ' : '') . (($which_ary['name'] != '') ? '"' . mail_encode($which_ary['name']) . '" <' . $which_ary['email'] . '>' : $which_ary['email']);
391
 
                        }
392
 
                }
393
 
 
394
 
                // Build header
395
 
                $headers = $this->build_header($to, $cc, $bcc);
396
 
 
397
 
                // Send message ...
398
 
                if (!$use_queue)
399
 
                {
400
 
                        $mail_to = ($to == '') ? 'undisclosed-recipients:;' : $to;
401
 
                        $err_msg = '';
402
 
 
403
 
                        if ($config['smtp_delivery'])
404
 
                        {
405
 
                                $result = smtpmail($this->addresses, mail_encode($this->subject), wordwrap(utf8_wordwrap($this->msg), 997, "\n", true), $err_msg, $headers);
406
 
                        }
407
 
                        else
408
 
                        {
409
 
                                ob_start();
410
 
                                $result = $config['email_function_name']($mail_to, mail_encode($this->subject), wordwrap(utf8_wordwrap($this->msg), 997, "\n", true), $headers);
411
 
                                $err_msg = ob_get_clean();
412
 
                        }
413
 
 
414
 
                        if (!$result)
415
 
                        {
416
 
                                $this->error('EMAIL', $err_msg);
417
 
                                return false;
418
 
                        }
419
 
                }
420
 
                else
421
 
                {
422
 
                        $this->queue->put('email', array(
423
 
                                'to'                    => $to,
424
 
                                'addresses'             => $this->addresses,
425
 
                                'subject'               => $this->subject,
426
 
                                'msg'                   => $this->msg,
427
 
                                'headers'               => $headers)
428
 
                        );
429
 
                }
430
 
 
431
 
                return true;
432
 
        }
433
 
 
434
 
        /**
435
 
        * Send jabber message out
436
 
        */
437
 
        function msg_jabber()
438
 
        {
439
 
                global $config, $db, $user, $phpbb_root_path, $phpEx;
440
 
 
441
 
                if (empty($config['jab_enable']) || empty($config['jab_host']) || empty($config['jab_username']) || empty($config['jab_password']))
442
 
                {
443
 
                        return false;
444
 
                }
445
 
 
446
 
                $use_queue = false;
447
 
                if ($config['jab_package_size'] && $this->use_queue)
448
 
                {
449
 
                        if (empty($this->queue))
450
 
                        {
451
 
                                $this->queue = new queue();
452
 
                                $this->queue->init('jabber', $config['jab_package_size']);
453
 
                        }
454
 
                        $use_queue = true;
455
 
                }
456
 
 
457
 
                $addresses = array();
458
 
                foreach ($this->addresses['im'] as $type => $uid_ary)
459
 
                {
460
 
                        $addresses[] = $uid_ary['uid'];
461
 
                }
462
 
                $addresses = array_unique($addresses);
463
 
 
464
 
                if (!$use_queue)
465
 
                {
466
 
                        include_once($phpbb_root_path . 'includes/functions_jabber.' . $phpEx);
467
 
                        $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], $config['jab_password'], $config['jab_use_ssl']);
468
 
 
469
 
                        if (!$this->jabber->connect())
470
 
                        {
471
 
                                $this->error('JABBER', $user->lang['ERR_JAB_CONNECT'] . '<br />' . $this->jabber->get_log());
472
 
                                return false;
473
 
                        }
474
 
 
475
 
                        if (!$this->jabber->login())
476
 
                        {
477
 
                                $this->error('JABBER', $user->lang['ERR_JAB_AUTH'] . '<br />' . $this->jabber->get_log());
478
 
                                return false;
479
 
                        }
480
 
 
481
 
                        foreach ($addresses as $address)
482
 
                        {
483
 
                                $this->jabber->send_message($address, $this->msg, $this->subject);
484
 
                        }
485
 
 
486
 
                        $this->jabber->disconnect();
487
 
                }
488
 
                else
489
 
                {
490
 
                        $this->queue->put('jabber', array(
491
 
                                'addresses'             => $addresses,
492
 
                                'subject'               => $this->subject,
493
 
                                'msg'                   => $this->msg)
494
 
                        );
495
 
                }
496
 
                unset($addresses);
497
 
                return true;
498
 
        }
499
 
}
500
 
 
501
 
/**
502
 
* handling email and jabber queue
503
 
* @package phpBB3
504
 
*/
505
 
class queue
506
 
{
507
 
        var $data = array();
508
 
        var $queue_data = array();
509
 
        var $package_size = 0;
510
 
        var $cache_file = '';
511
 
 
512
 
        /**
513
 
        * constructor
514
 
        */
515
 
        function queue()
516
 
        {
517
 
                global $phpEx, $phpbb_root_path;
518
 
 
519
 
                $this->data = array();
520
 
                $this->cache_file = "{$phpbb_root_path}cache/queue.$phpEx";
521
 
        }
522
 
 
523
 
        /**
524
 
        * Init a queue object
525
 
        */
526
 
        function init($object, $package_size)
527
 
        {
528
 
                $this->data[$object] = array();
529
 
                $this->data[$object]['package_size'] = $package_size;
530
 
                $this->data[$object]['data'] = array();
531
 
        }
532
 
 
533
 
        /**
534
 
        * Put object in queue
535
 
        */
536
 
        function put($object, $scope)
537
 
        {
538
 
                $this->data[$object]['data'][] = $scope;
539
 
        }
540
 
 
541
 
        /**
542
 
        * Process queue
543
 
        * Using lock file
544
 
        */
545
 
        function process()
546
 
        {
547
 
                global $db, $config, $phpEx, $phpbb_root_path, $user;
548
 
 
549
 
                set_config('last_queue_run', time(), true);
550
 
 
551
 
                // Delete stale lock file
552
 
                if (file_exists($this->cache_file . '.lock') && !file_exists($this->cache_file))
553
 
                {
554
 
                        @unlink($this->cache_file . '.lock');
555
 
                        return;
556
 
                }
557
 
 
558
 
                if (!file_exists($this->cache_file) || (file_exists($this->cache_file . '.lock') && filemtime($this->cache_file) > time() - $config['queue_interval']))
559
 
                {
560
 
                        return;
561
 
                }
562
 
 
563
 
                $fp = @fopen($this->cache_file . '.lock', 'wb');
564
 
                fclose($fp);
565
 
                @chmod($this->cache_file . '.lock', 0666);
566
 
 
567
 
                include($this->cache_file);
568
 
 
569
 
                foreach ($this->queue_data as $object => $data_ary)
570
 
                {
571
 
                        @set_time_limit(0);
572
 
 
573
 
                        if (!isset($data_ary['package_size']))
574
 
                        {
575
 
                                $data_ary['package_size'] = 0;
576
 
                        }
577
 
 
578
 
                        $package_size = $data_ary['package_size'];
579
 
                        $num_items = (!$package_size || sizeof($data_ary['data']) < $package_size) ? sizeof($data_ary['data']) : $package_size;
580
 
 
581
 
                        // If the amount of emails to be sent is way more than package_size than we need to increase it to prevent backlogs...
582
 
                        if (sizeof($data_ary['data']) > $package_size * 2.5)
583
 
                        {
584
 
                                $num_items = sizeof($data_ary['data']);
585
 
                        }
586
 
 
587
 
                        switch ($object)
588
 
                        {
589
 
                                case 'email':
590
 
                                        // Delete the email queued objects if mailing is disabled
591
 
                                        if (!$config['email_enable'])
592
 
                                        {
593
 
                                                unset($this->queue_data['email']);
594
 
                                                continue 2;
595
 
                                        }
596
 
                                break;
597
 
 
598
 
                                case 'jabber':
599
 
                                        if (!$config['jab_enable'])
600
 
                                        {
601
 
                                                unset($this->queue_data['jabber']);
602
 
                                                continue 2;
603
 
                                        }
604
 
 
605
 
                                        include_once($phpbb_root_path . 'includes/functions_jabber.' . $phpEx);
606
 
                                        $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], $config['jab_password'], $config['jab_use_ssl']);
607
 
 
608
 
                                        if (!$this->jabber->connect())
609
 
                                        {
610
 
                                                messenger::error('JABBER', $user->lang['ERR_JAB_CONNECT']);
611
 
                                                continue 2;
612
 
                                        }
613
 
 
614
 
                                        if (!$this->jabber->login())
615
 
                                        {
616
 
                                                messenger::error('JABBER', $user->lang['ERR_JAB_AUTH']);
617
 
                                                continue 2;
618
 
                                        }
619
 
 
620
 
                                break;
621
 
 
622
 
                                default:
623
 
                                        return;
624
 
                        }
625
 
 
626
 
                        for ($i = 0; $i < $num_items; $i++)
627
 
                        {
628
 
                                // Make variables available...
629
 
                                extract(array_shift($this->queue_data[$object]['data']));
630
 
 
631
 
                                switch ($object)
632
 
                                {
633
 
                                        case 'email':
634
 
                                                $err_msg = '';
635
 
                                                $to = (!$to) ? 'undisclosed-recipients:;' : $to;
636
 
 
637
 
                                                if ($config['smtp_delivery'])
638
 
                                                {
639
 
                                                        $result = smtpmail($addresses, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $err_msg, $headers);
640
 
                                                }
641
 
                                                else
642
 
                                                {
643
 
                                                        ob_start();
644
 
                                                        $result = $config['email_function_name']($to, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers);
645
 
                                                        $err_msg = ob_get_clean();
646
 
                                                }
647
 
 
648
 
                                                if (!$result)
649
 
                                                {
650
 
                                                        @unlink($this->cache_file . '.lock');
651
 
 
652
 
                                                        messenger::error('EMAIL', $err_msg);
653
 
                                                        continue 2;
654
 
                                                }
655
 
                                        break;
656
 
 
657
 
                                        case 'jabber':
658
 
                                                foreach ($addresses as $address)
659
 
                                                {
660
 
                                                        if ($this->jabber->send_message($address, $msg, $subject) === false)
661
 
                                                        {
662
 
                                                                messenger::error('JABBER', $this->jabber->get_log());
663
 
                                                                continue 3;
664
 
                                                        }
665
 
                                                }
666
 
                                        break;
667
 
                                }
668
 
                        }
669
 
 
670
 
                        // No more data for this object? Unset it
671
 
                        if (!sizeof($this->queue_data[$object]['data']))
672
 
                        {
673
 
                                unset($this->queue_data[$object]);
674
 
                        }
675
 
 
676
 
                        // Post-object processing
677
 
                        switch ($object)
678
 
                        {
679
 
                                case 'jabber':
680
 
                                        // Hang about a couple of secs to ensure the messages are
681
 
                                        // handled, then disconnect
682
 
                                        $this->jabber->disconnect();
683
 
                                break;
684
 
                        }
685
 
                }
686
 
        
687
 
                if (!sizeof($this->queue_data))
688
 
                {
689
 
                        @unlink($this->cache_file);
690
 
                }
691
 
                else
692
 
                {
693
 
                        if ($fp = @fopen($this->cache_file, 'w'))
694
 
                        {
695
 
                                @flock($fp, LOCK_EX);
696
 
                                fwrite($fp, "<?php\n\$this->queue_data = " . var_export($this->queue_data, true) . ";\n?>");
697
 
                                @flock($fp, LOCK_UN);
698
 
                                fclose($fp);
699
 
 
700
 
                                @chmod($this->cache_file, 0666);
701
 
                        }
702
 
                }
703
 
 
704
 
                @unlink($this->cache_file . '.lock');
705
 
        }
706
 
 
707
 
        /**
708
 
        * Save queue
709
 
        */
710
 
        function save()
711
 
        {
712
 
                if (!sizeof($this->data))
713
 
                {
714
 
                        return;
715
 
                }
716
 
                
717
 
                if (file_exists($this->cache_file))
718
 
                {
719
 
                        include($this->cache_file);
720
 
                        
721
 
                        foreach ($this->queue_data as $object => $data_ary)
722
 
                        {
723
 
                                if (isset($this->data[$object]) && sizeof($this->data[$object]))
724
 
                                {
725
 
                                        $this->data[$object]['data'] = array_merge($data_ary['data'], $this->data[$object]['data']);
726
 
                                }
727
 
                                else
728
 
                                {
729
 
                                        $this->data[$object]['data'] = $data_ary['data'];
730
 
                                }
731
 
                        }
732
 
                }
733
 
 
734
 
                if ($fp = @fopen($this->cache_file, 'w'))
735
 
                {
736
 
                        @flock($fp, LOCK_EX);
737
 
                        fwrite($fp, "<?php\n\$this->queue_data = " . var_export($this->data, true) . ";\n?>");
738
 
                        @flock($fp, LOCK_UN);
739
 
                        fclose($fp);
740
 
 
741
 
                        @chmod($this->cache_file, 0666);
742
 
                }
743
 
        }
744
 
}
745
 
 
746
 
/**
747
 
* Replacement or substitute for PHP's mail command
748
 
*/
749
 
function smtpmail($addresses, $subject, $message, &$err_msg, $headers = '')
750
 
{
751
 
        global $config, $user;
752
 
 
753
 
        // Fix any bare linefeeds in the message to make it RFC821 Compliant.
754
 
        $message = preg_replace("#(?<!\r)\n#si", "\r\n", $message);
755
 
 
756
 
        if ($headers != '')
757
 
        {
758
 
                if (is_array($headers))
759
 
                {
760
 
                        $headers = (sizeof($headers) > 1) ? join("\n", $headers) : $headers[0];
761
 
                }
762
 
                $headers = chop($headers);
763
 
 
764
 
                // Make sure there are no bare linefeeds in the headers
765
 
                $headers = preg_replace('#(?<!\r)\n#si', "\r\n", $headers);
766
 
 
767
 
                // Ok this is rather confusing all things considered,
768
 
                // but we have to grab bcc and cc headers and treat them differently
769
 
                // Something we really didn't take into consideration originally
770
 
                $header_array = explode("\r\n", $headers);
771
 
                $headers = '';
772
 
 
773
 
                foreach ($header_array as $header)
774
 
                {
775
 
                        if (strpos(strtolower($header), 'cc:') === 0 || strpos(strtolower($header), 'bcc:') === 0)
776
 
                        {
777
 
                                $header = '';
778
 
                        }
779
 
                        $headers .= ($header != '') ? $header . "\r\n" : '';
780
 
                }
781
 
 
782
 
                $headers = chop($headers);
783
 
        }
784
 
 
785
 
        if (trim($subject) == '')
786
 
        {
787
 
                $err_msg = (isset($user->lang['NO_EMAIL_SUBJECT'])) ? $user->lang['NO_EMAIL_SUBJECT'] : 'No email subject specified';
788
 
                return false;
789
 
        }
790
 
 
791
 
        if (trim($message) == '')
792
 
        {
793
 
                $err_msg = (isset($user->lang['NO_EMAIL_MESSAGE'])) ? $user->lang['NO_EMAIL_MESSAGE'] : 'Email message was blank';
794
 
                return false;
795
 
        }
796
 
 
797
 
        $mail_rcpt = $mail_to = $mail_cc = array();
798
 
 
799
 
        // Build correct addresses for RCPT TO command and the client side display (TO, CC)
800
 
        if (isset($addresses['to']) && sizeof($addresses['to']))
801
 
        {
802
 
                foreach ($addresses['to'] as $which_ary)
803
 
                {
804
 
                        $mail_to[] = ($which_ary['name'] != '') ? mail_encode(trim($which_ary['name'])) . ' <' . trim($which_ary['email']) . '>' : '<' . trim($which_ary['email']) . '>';
805
 
                        $mail_rcpt['to'][] = '<' . trim($which_ary['email']) . '>';
806
 
                }
807
 
        }
808
 
 
809
 
        if (isset($addresses['bcc']) && sizeof($addresses['bcc']))
810
 
        {
811
 
                foreach ($addresses['bcc'] as $which_ary)
812
 
                {
813
 
                        $mail_rcpt['bcc'][] = '<' . trim($which_ary['email']) . '>';
814
 
                }
815
 
        }
816
 
 
817
 
        if (isset($addresses['cc']) && sizeof($addresses['cc']))
818
 
        {
819
 
                foreach ($addresses['cc'] as $which_ary)
820
 
                {
821
 
                        $mail_cc[] = ($which_ary['name'] != '') ? mail_encode(trim($which_ary['name'])) . ' <' . trim($which_ary['email']) . '>' : '<' . trim($which_ary['email']) . '>';
822
 
                        $mail_rcpt['cc'][] = '<' . trim($which_ary['email']) . '>';
823
 
                }
824
 
        }
825
 
 
826
 
        $smtp = new smtp_class();
827
 
 
828
 
        $errno = 0;
829
 
        $errstr = '';
830
 
 
831
 
        $smtp->add_backtrace('Connecting to ' . $config['smtp_host'] . ':' . $config['smtp_port']);
832
 
 
833
 
        // Ok we have error checked as much as we can to this point let's get on it already.
834
 
        ob_start();
835
 
        $smtp->socket = fsockopen($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 20);
836
 
        $error_contents = ob_get_clean();
837
 
 
838
 
        if (!$smtp->socket)
839
 
        {
840
 
                if ($errstr)
841
 
                {
842
 
                        $errstr = utf8_convert_message($errstr);
843
 
                }
844
 
 
845
 
                $err_msg = (isset($user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf($user->lang['NO_CONNECT_TO_SMTP_HOST'], $errno, $errstr) : "Could not connect to smtp host : $errno : $errstr";
846
 
                $err_msg .= ($error_contents) ? '<br /><br />' . htmlspecialchars($error_contents) : '';
847
 
                return false;
848
 
        }
849
 
 
850
 
        // Wait for reply
851
 
        if ($err_msg = $smtp->server_parse('220', __LINE__))
852
 
        {
853
 
                $smtp->close_session($err_msg);
854
 
                return false;
855
 
        }
856
 
 
857
 
        // Let me in. This function handles the complete authentication process
858
 
        if ($err_msg = $smtp->log_into_server($config['smtp_host'], $config['smtp_username'], $config['smtp_password'], $config['smtp_auth_method']))
859
 
        {
860
 
                $smtp->close_session($err_msg);
861
 
                return false;
862
 
        }
863
 
 
864
 
        // From this point onward most server response codes should be 250
865
 
        // Specify who the mail is from....
866
 
        $smtp->server_send('MAIL FROM:<' . $config['board_email'] . '>');
867
 
        if ($err_msg = $smtp->server_parse('250', __LINE__))
868
 
        {
869
 
                $smtp->close_session($err_msg);
870
 
                return false;
871
 
        }
872
 
 
873
 
        // Specify each user to send to and build to header.
874
 
        $to_header = implode(', ', $mail_to);
875
 
        $cc_header = implode(', ', $mail_cc);
876
 
 
877
 
        // Now tell the MTA to send the Message to the following people... [TO, BCC, CC]
878
 
        $rcpt = false;
879
 
        foreach ($mail_rcpt as $type => $mail_to_addresses)
880
 
        {
881
 
                foreach ($mail_to_addresses as $mail_to_address)
882
 
                {
883
 
                        // Add an additional bit of error checking to the To field.
884
 
                        if (preg_match('#[^ ]+\@[^ ]+#', $mail_to_address))
885
 
                        {
886
 
                                $smtp->server_send("RCPT TO:$mail_to_address");
887
 
                                if ($err_msg = $smtp->server_parse('250', __LINE__))
888
 
                                {
889
 
                                        // We continue... if users are not resolved we do not care
890
 
                                        if ($smtp->numeric_response_code != 550)
891
 
                                        {
892
 
                                                $smtp->close_session($err_msg);
893
 
                                                return false;
894
 
                                        }
895
 
                                }
896
 
                                else
897
 
                                {
898
 
                                        $rcpt = true;
899
 
                                }
900
 
                        }
901
 
                }
902
 
        }
903
 
 
904
 
        // We try to send messages even if a few people do not seem to have valid email addresses, but if no one has, we have to exit here.
905
 
        if (!$rcpt)
906
 
        {
907
 
                $user->session_begin();
908
 
                $err_msg .= '<br /><br />';
909
 
                $err_msg .= (isset($user->lang['INVALID_EMAIL_LOG'])) ? sprintf($user->lang['INVALID_EMAIL_LOG'], htmlspecialchars($mail_to_address)) : '<strong>' . htmlspecialchars($mail_to_address) . '</strong> possibly an invalid email address?';
910
 
                $smtp->close_session($err_msg);
911
 
                return false;
912
 
        }
913
 
 
914
 
        // Ok now we tell the server we are ready to start sending data
915
 
        $smtp->server_send('DATA');
916
 
 
917
 
        // This is the last response code we look for until the end of the message.
918
 
        if ($err_msg = $smtp->server_parse('354', __LINE__))
919
 
        {
920
 
                $smtp->close_session($err_msg);
921
 
                return false;
922
 
        }
923
 
 
924
 
        // Send the Subject Line...
925
 
        $smtp->server_send("Subject: $subject");
926
 
 
927
 
        // Now the To Header.
928
 
        $to_header = ($to_header == '') ? 'undisclosed-recipients:;' : $to_header;
929
 
        $smtp->server_send("To: $to_header");
930
 
 
931
 
        // Now the CC Header.
932
 
        if ($cc_header != '')
933
 
        {
934
 
                $smtp->server_send("CC: $cc_header");
935
 
        }
936
 
 
937
 
        // Now any custom headers....
938
 
        $smtp->server_send("$headers\r\n");
939
 
 
940
 
        // Ok now we are ready for the message...
941
 
        $smtp->server_send($message);
942
 
 
943
 
        // Ok the all the ingredients are mixed in let's cook this puppy...
944
 
        $smtp->server_send('.');
945
 
        if ($err_msg = $smtp->server_parse('250', __LINE__))
946
 
        {
947
 
                $smtp->close_session($err_msg);
948
 
                return false;
949
 
        }
950
 
 
951
 
        // Now tell the server we are done and close the socket...
952
 
        $smtp->server_send('QUIT');
953
 
        $smtp->close_session($err_msg);
954
 
 
955
 
        return true;
956
 
}
957
 
 
958
 
/**
959
 
* SMTP Class
960
 
* Auth Mechanisms originally taken from the AUTH Modules found within the PHP Extension and Application Repository (PEAR)
961
 
* See docs/AUTHORS for more details
962
 
* @package phpBB3
963
 
*/
964
 
class smtp_class
965
 
{
966
 
        var $server_response = '';
967
 
        var $socket = 0;
968
 
        var $responses = array();
969
 
        var $commands = array();
970
 
        var $numeric_response_code = 0;
971
 
 
972
 
        var $backtrace = false;
973
 
        var $backtrace_log = array();
974
 
 
975
 
        function smtp_class()
976
 
        {
977
 
                // Always create a backtrace for admins to identify SMTP problems
978
 
                $this->backtrace = true;
979
 
                $this->backtrace_log = array();
980
 
        }
981
 
 
982
 
        /**
983
 
        * Add backtrace message for debugging
984
 
        */
985
 
        function add_backtrace($message)
986
 
        {
987
 
                if ($this->backtrace)
988
 
                {
989
 
                        $this->backtrace_log[] = utf8_htmlspecialchars($message);
990
 
                }
991
 
        }
992
 
 
993
 
        /**
994
 
        * Send command to smtp server
995
 
        */
996
 
        function server_send($command, $private_info = false)
997
 
        {
998
 
                fputs($this->socket, $command . "\r\n");
999
 
 
1000
 
                (!$private_info) ? $this->add_backtrace("# $command") : $this->add_backtrace('# Omitting sensitive information');
1001
 
 
1002
 
                // We could put additional code here
1003
 
        }
1004
 
 
1005
 
        /**
1006
 
        * We use the line to give the support people an indication at which command the error occurred
1007
 
        */
1008
 
        function server_parse($response, $line)
1009
 
        {
1010
 
                global $user;
1011
 
 
1012
 
                $this->server_response = '';
1013
 
                $this->responses = array();
1014
 
                $this->numeric_response_code = 0;
1015
 
 
1016
 
                while (substr($this->server_response, 3, 1) != ' ')
1017
 
                {
1018
 
                        if (!($this->server_response = fgets($this->socket, 256)))
1019
 
                        {
1020
 
                                return (isset($user->lang['NO_EMAIL_RESPONSE_CODE'])) ? $user->lang['NO_EMAIL_RESPONSE_CODE'] : 'Could not get mail server response codes';
1021
 
                        }
1022
 
                        $this->responses[] = substr(rtrim($this->server_response), 4);
1023
 
                        $this->numeric_response_code = (int) substr($this->server_response, 0, 3);
1024
 
 
1025
 
                        $this->add_backtrace("LINE: $line <- {$this->server_response}");
1026
 
                }
1027
 
 
1028
 
                if (!(substr($this->server_response, 0, 3) == $response))
1029
 
                {
1030
 
                        $this->numeric_response_code = (int) substr($this->server_response, 0, 3);
1031
 
                        return (isset($user->lang['EMAIL_SMTP_ERROR_RESPONSE'])) ? sprintf($user->lang['EMAIL_SMTP_ERROR_RESPONSE'], $line, $this->server_response) : "Ran into problems sending Mail at <strong>Line $line</strong>. Response: $this->server_response";
1032
 
                }
1033
 
 
1034
 
                return 0;
1035
 
        }
1036
 
 
1037
 
        /**
1038
 
        * Close session
1039
 
        */
1040
 
        function close_session(&$err_msg)
1041
 
        {
1042
 
                fclose($this->socket);
1043
 
 
1044
 
                if ($this->backtrace)
1045
 
                {
1046
 
                        $message = '<h1>Backtrace</h1><p>' . implode('<br />', $this->backtrace_log) . '</p>';
1047
 
                        $err_msg .= $message;
1048
 
                }
1049
 
        }
1050
 
        
1051
 
        /**
1052
 
        * Log into server and get possible auth codes if neccessary
1053
 
        */
1054
 
        function log_into_server($hostname, $username, $password, $default_auth_method)
1055
 
        {
1056
 
                global $user;
1057
 
 
1058
 
                $err_msg = '';
1059
 
                $local_host = php_uname('n');
1060
 
                $local_host = (empty($local_host)) ? 'localhost' : $local_host;
1061
 
 
1062
 
                // If we are authenticating through pop-before-smtp, we
1063
 
                // have to login ones before we get authenticated
1064
 
                // NOTE: on some configurations the time between an update of the auth database takes so
1065
 
                // long that the first email send does not work. This is not a biggie on a live board (only
1066
 
                // the install mail will most likely fail) - but on a dynamic ip connection this might produce
1067
 
                // severe problems and is not fixable!
1068
 
                if ($default_auth_method == 'POP-BEFORE-SMTP' && $username && $password)
1069
 
                {
1070
 
                        global $config;
1071
 
 
1072
 
                        $errno = 0;
1073
 
                        $errstr = '';
1074
 
 
1075
 
                        $this->server_send("QUIT");
1076
 
                        fclose($this->socket);
1077
 
 
1078
 
                        $result = $this->pop_before_smtp($hostname, $username, $password);
1079
 
                        $username = $password = $default_auth_method = '';
1080
 
 
1081
 
                        // We need to close the previous session, else the server is not
1082
 
                        // able to get our ip for matching...
1083
 
                        if (!$this->socket = @fsockopen($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 10))
1084
 
                        {
1085
 
                                if ($errstr)
1086
 
                                {
1087
 
                                        $errstr = utf8_convert_message($errstr);
1088
 
                                }
1089
 
 
1090
 
                                $err_msg = (isset($user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf($user->lang['NO_CONNECT_TO_SMTP_HOST'], $errno, $errstr) : "Could not connect to smtp host : $errno : $errstr";
1091
 
                                return $err_msg;
1092
 
                        }
1093
 
 
1094
 
                        // Wait for reply
1095
 
                        if ($err_msg = $this->server_parse('220', __LINE__))
1096
 
                        {
1097
 
                                $this->close_session($err_msg);
1098
 
                                return $err_msg;
1099
 
                        }
1100
 
                }
1101
 
 
1102
 
                // Try EHLO first
1103
 
                $this->server_send("EHLO {$local_host}");
1104
 
                if ($err_msg = $this->server_parse('250', __LINE__))
1105
 
                {
1106
 
                        // a 503 response code means that we're already authenticated
1107
 
                        if ($this->numeric_response_code == 503)
1108
 
                        {
1109
 
                                return false;
1110
 
                        }
1111
 
 
1112
 
                        // If EHLO fails, we try HELO                   
1113
 
                        $this->server_send("HELO {$local_host}");
1114
 
                        if ($err_msg = $this->server_parse('250', __LINE__))
1115
 
                        {
1116
 
                                return ($this->numeric_response_code == 503) ? false : $err_msg;
1117
 
                        }
1118
 
                }
1119
 
 
1120
 
                foreach ($this->responses as $response)
1121
 
                {
1122
 
                        $response = explode(' ', $response);
1123
 
                        $response_code = $response[0];
1124
 
                        unset($response[0]);
1125
 
                        $this->commands[$response_code] = implode(' ', $response);
1126
 
                }
1127
 
 
1128
 
                // If we are not authenticated yet, something might be wrong if no username and passwd passed
1129
 
                if (!$username || !$password)
1130
 
                {
1131
 
                        return false;
1132
 
                }
1133
 
                
1134
 
                if (!isset($this->commands['AUTH']))
1135
 
                {
1136
 
                        return (isset($user->lang['SMTP_NO_AUTH_SUPPORT'])) ? $user->lang['SMTP_NO_AUTH_SUPPORT'] : 'SMTP server does not support authentication';
1137
 
                }
1138
 
 
1139
 
                // Get best authentication method
1140
 
                $available_methods = explode(' ', $this->commands['AUTH']);
1141
 
 
1142
 
                // Define the auth ordering if the default auth method was not found
1143
 
                $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5');
1144
 
                $method = '';
1145
 
 
1146
 
                if (in_array($default_auth_method, $available_methods))
1147
 
                {
1148
 
                        $method = $default_auth_method;
1149
 
                }
1150
 
                else
1151
 
                {
1152
 
                        foreach ($auth_methods as $_method)
1153
 
                        {
1154
 
                                if (in_array($_method, $available_methods))
1155
 
                                {
1156
 
                                        $method = $_method;
1157
 
                                        break;
1158
 
                                }
1159
 
                        }
1160
 
                }
1161
 
 
1162
 
                if (!$method)
1163
 
                {
1164
 
                        return (isset($user->lang['NO_SUPPORTED_AUTH_METHODS'])) ? $user->lang['NO_SUPPORTED_AUTH_METHODS'] : 'No supported authentication methods';
1165
 
                }
1166
 
 
1167
 
                $method = strtolower(str_replace('-', '_', $method));
1168
 
                return $this->$method($username, $password);
1169
 
        }
1170
 
 
1171
 
        /**
1172
 
        * Pop before smtp authentication
1173
 
        */
1174
 
        function pop_before_smtp($hostname, $username, $password)
1175
 
        {
1176
 
                global $user;
1177
 
 
1178
 
                if (!$this->socket = @fsockopen($hostname, 110, $errno, $errstr, 10))
1179
 
                {
1180
 
                        if ($errstr)
1181
 
                        {
1182
 
                                $errstr = utf8_convert_message($errstr);
1183
 
                        }
1184
 
 
1185
 
                        return (isset($user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf($user->lang['NO_CONNECT_TO_SMTP_HOST'], $errno, $errstr) : "Could not connect to smtp host : $errno : $errstr";
1186
 
                }
1187
 
 
1188
 
                $this->server_send("USER $username", true);
1189
 
                if ($err_msg = $this->server_parse('+OK', __LINE__))
1190
 
                {
1191
 
                        return $err_msg;
1192
 
                }
1193
 
 
1194
 
                $this->server_send("PASS $password", true);
1195
 
                if ($err_msg = $this->server_parse('+OK', __LINE__))
1196
 
                {
1197
 
                        return $err_msg;
1198
 
                }
1199
 
 
1200
 
                $this->server_send('QUIT');
1201
 
                fclose($this->socket);
1202
 
 
1203
 
                return false;
1204
 
        }
1205
 
 
1206
 
        /**
1207
 
        * Plain authentication method
1208
 
        */
1209
 
        function plain($username, $password)
1210
 
        {
1211
 
                $this->server_send('AUTH PLAIN');
1212
 
                if ($err_msg = $this->server_parse('334', __LINE__))
1213
 
                {
1214
 
                        return ($this->numeric_response_code == 503) ? false : $err_msg;
1215
 
                }
1216
 
 
1217
 
                $base64_method_plain = base64_encode("\0" . $username . "\0" . $password);
1218
 
                $this->server_send($base64_method_plain, true);
1219
 
                if ($err_msg = $this->server_parse('235', __LINE__))
1220
 
                {
1221
 
                        return $err_msg;
1222
 
                }
1223
 
 
1224
 
                return false;
1225
 
        }
1226
 
 
1227
 
        /**
1228
 
        * Login authentication method
1229
 
        */
1230
 
        function login($username, $password)
1231
 
        {
1232
 
                $this->server_send('AUTH LOGIN');
1233
 
                if ($err_msg = $this->server_parse('334', __LINE__))
1234
 
                {
1235
 
                        return ($this->numeric_response_code == 503) ? false : $err_msg;
1236
 
                }
1237
 
 
1238
 
                $this->server_send(base64_encode($username), true);
1239
 
                if ($err_msg = $this->server_parse('334', __LINE__))
1240
 
                {
1241
 
                        return $err_msg;
1242
 
                }
1243
 
 
1244
 
                $this->server_send(base64_encode($password), true);
1245
 
                if ($err_msg = $this->server_parse('235', __LINE__))
1246
 
                {
1247
 
                        return $err_msg;
1248
 
                }
1249
 
 
1250
 
                return false;
1251
 
        }
1252
 
 
1253
 
        /**
1254
 
        * cram_md5 authentication method
1255
 
        */
1256
 
        function cram_md5($username, $password)
1257
 
        {
1258
 
                $this->server_send('AUTH CRAM-MD5');
1259
 
                if ($err_msg = $this->server_parse('334', __LINE__))
1260
 
                {
1261
 
                        return ($this->numeric_response_code == 503) ? false : $err_msg;
1262
 
                }
1263
 
 
1264
 
                $md5_challenge = base64_decode($this->responses[0]);
1265
 
                $password = (strlen($password) > 64) ? pack('H32', md5($password)) : ((strlen($password) < 64) ? str_pad($password, 64, chr(0)) : $password);
1266
 
                $md5_digest = md5((substr($password, 0, 64) ^ str_repeat(chr(0x5C), 64)) . (pack('H32', md5((substr($password, 0, 64) ^ str_repeat(chr(0x36), 64)) . $md5_challenge))));
1267
 
 
1268
 
                $base64_method_cram_md5 = base64_encode($username . ' ' . $md5_digest);
1269
 
 
1270
 
                $this->server_send($base64_method_cram_md5, true);
1271
 
                if ($err_msg = $this->server_parse('235', __LINE__))
1272
 
                {
1273
 
                        return $err_msg;
1274
 
                }
1275
 
 
1276
 
                return false;
1277
 
        }
1278
 
 
1279
 
        /**
1280
 
        * digest_md5 authentication method
1281
 
        * A real pain in the ***
1282
 
        */
1283
 
        function digest_md5($username, $password)
1284
 
        {
1285
 
                global $config, $user;
1286
 
 
1287
 
                $this->server_send('AUTH DIGEST-MD5');
1288
 
                if ($err_msg = $this->server_parse('334', __LINE__))
1289
 
                {
1290
 
                        return ($this->numeric_response_code == 503) ? false : $err_msg;
1291
 
                }
1292
 
 
1293
 
                $md5_challenge = base64_decode($this->responses[0]);
1294
 
                
1295
 
                // Parse the md5 challenge - from AUTH_SASL (PEAR)
1296
 
                $tokens = array();
1297
 
                while (preg_match('/^([a-z-]+)=("[^"]+(?<!\\\)"|[^,]+)/i', $md5_challenge, $matches))
1298
 
                {
1299
 
                        // Ignore these as per rfc2831
1300
 
                        if ($matches[1] == 'opaque' || $matches[1] == 'domain')
1301
 
                        {
1302
 
                                $md5_challenge = substr($md5_challenge, strlen($matches[0]) + 1);
1303
 
                                continue;
1304
 
                        }
1305
 
 
1306
 
                        // Allowed multiple "realm" and "auth-param"
1307
 
                        if (!empty($tokens[$matches[1]]) && ($matches[1] == 'realm' || $matches[1] == 'auth-param'))
1308
 
                        {
1309
 
                                if (is_array($tokens[$matches[1]]))
1310
 
                                {
1311
 
                                        $tokens[$matches[1]][] = preg_replace('/^"(.*)"$/', '\\1', $matches[2]);
1312
 
                                }
1313
 
                                else
1314
 
                                {
1315
 
                                        $tokens[$matches[1]] = array($tokens[$matches[1]], preg_replace('/^"(.*)"$/', '\\1', $matches[2]));
1316
 
                                }
1317
 
                        }
1318
 
                        else if (!empty($tokens[$matches[1]])) // Any other multiple instance = failure
1319
 
                        {
1320
 
                                $tokens = array();
1321
 
                                break;
1322
 
                        }
1323
 
                        else
1324
 
                        {
1325
 
                                $tokens[$matches[1]] = preg_replace('/^"(.*)"$/', '\\1', $matches[2]);
1326
 
                        }
1327
 
 
1328
 
                        // Remove the just parsed directive from the challenge
1329
 
                        $md5_challenge = substr($md5_challenge, strlen($matches[0]) + 1);
1330
 
                }
1331
 
 
1332
 
                // Realm
1333
 
                if (empty($tokens['realm']))
1334
 
                {
1335
 
                        $tokens['realm'] = php_uname('n');
1336
 
                }
1337
 
 
1338
 
                // Maxbuf
1339
 
                if (empty($tokens['maxbuf']))
1340
 
                {
1341
 
                        $tokens['maxbuf'] = 65536;
1342
 
                }
1343
 
 
1344
 
                // Required: nonce, algorithm
1345
 
                if (empty($tokens['nonce']) || empty($tokens['algorithm']))
1346
 
                {
1347
 
                        $tokens = array();
1348
 
                }
1349
 
                $md5_challenge = $tokens;
1350
 
 
1351
 
                if (!empty($md5_challenge))
1352
 
                {
1353
 
                        $str = '';
1354
 
                        for ($i = 0; $i < 32; $i++)
1355
 
                        {
1356
 
                                $str .= chr(mt_rand(0, 255));
1357
 
                        }
1358
 
                        $cnonce = base64_encode($str);
1359
 
 
1360
 
                        $digest_uri = 'smtp/' . $config['smtp_host'];
1361
 
 
1362
 
                        $auth_1 = sprintf('%s:%s:%s', pack('H32', md5(sprintf('%s:%s:%s', $username, $md5_challenge['realm'], $password))), $md5_challenge['nonce'], $cnonce);
1363
 
                        $auth_2 = 'AUTHENTICATE:' . $digest_uri;
1364
 
                        $response_value = md5(sprintf('%s:%s:00000001:%s:auth:%s', md5($auth_1), $md5_challenge['nonce'], $cnonce, md5($auth_2)));
1365
 
 
1366
 
                        $input_string = sprintf('username="%s",realm="%s",nonce="%s",cnonce="%s",nc="00000001",qop=auth,digest-uri="%s",response=%s,%d', $username, $md5_challenge['realm'], $md5_challenge['nonce'], $cnonce, $digest_uri, $response_value, $md5_challenge['maxbuf']);
1367
 
                }
1368
 
                else
1369
 
                {
1370
 
                        return (isset($user->lang['INVALID_DIGEST_CHALLENGE'])) ? $user->lang['INVALID_DIGEST_CHALLENGE'] : 'Invalid digest challenge';
1371
 
                }
1372
 
 
1373
 
                $base64_method_digest_md5 = base64_encode($input_string);
1374
 
                $this->server_send($base64_method_digest_md5, true);
1375
 
                if ($err_msg = $this->server_parse('334', __LINE__))
1376
 
                {
1377
 
                        return $err_msg;
1378
 
                }
1379
 
 
1380
 
                $this->server_send(' ');
1381
 
                if ($err_msg = $this->server_parse('235', __LINE__))
1382
 
                {
1383
 
                        return $err_msg;
1384
 
                }
1385
 
 
1386
 
                return false;
1387
 
        }
1388
 
}
1389
 
 
1390
 
/**
1391
 
* Encodes the given string for proper display in UTF-8.
1392
 
*
1393
 
* This version is using base64 encoded data. The downside of this
1394
 
* is if the mail client does not understand this encoding the user
1395
 
* is basically doomed with an unreadable subject.
1396
 
*
1397
 
* Please note that this version fully supports RFC 2045 section 6.8.
1398
 
*/
1399
 
function mail_encode($str)
1400
 
{
1401
 
        // define start delimimter, end delimiter and spacer
1402
 
        $start = "=?UTF-8?B?";
1403
 
        $end = "?=";
1404
 
        $spacer = $end . ' ' . $start;
1405
 
        $split_length = 64;
1406
 
 
1407
 
        $encoded_str = base64_encode($str);
1408
 
 
1409
 
        // If encoded string meets the limits, we just return with the correct data.
1410
 
        if (strlen($encoded_str) <= $split_length)
1411
 
        {
1412
 
                return $start . $encoded_str . $end;
1413
 
        }
1414
 
 
1415
 
        // If there is only ASCII data, we just return what we want, correctly splitting the lines.
1416
 
        if (strlen($str) === utf8_strlen($str))
1417
 
        {
1418
 
                return $start . implode($spacer, str_split($encoded_str, $split_length)) . $end;
1419
 
        }
1420
 
 
1421
 
        // UTF-8 data, compose encoded lines
1422
 
        $array = utf8_str_split($str);
1423
 
        $str = '';
1424
 
 
1425
 
        while (sizeof($array))
1426
 
        {
1427
 
                $text = '';
1428
 
 
1429
 
                while (sizeof($array) && intval((strlen($text . $array[0]) + 2) / 3) << 2 <= $split_length)
1430
 
                {
1431
 
                        $text .= array_shift($array);
1432
 
                }
1433
 
 
1434
 
                $str .= $start . base64_encode($text) . $end . ' ';
1435
 
        }
1436
 
 
1437
 
        return substr($str, 0, -1);
1438
 
}
1439
 
 
1440
 
?>
 
 
b'\\ No newline at end of file'