remove old readme
[atutor.git] / include / classes / phpmailer / class.phpmailer.php
1 <?php\r
2 ////////////////////////////////////////////////////\r
3 // PHPMailer - PHP email class\r
4 //\r
5 // Class for sending email using either\r
6 // sendmail, PHP mail(), or SMTP.  Methods are\r
7 // based upon the standard AspEmail(tm) classes.\r
8 //\r
9 // Copyright (C) 2001 - 2003  Brent R. Matzelle\r
10 //\r
11 // License: LGPL, see LICENSE\r
12 ////////////////////////////////////////////////////\r
13 \r
14 /**\r
15  * PHPMailer - PHP email transport class\r
16  * @package PHPMailer\r
17  * @author Brent R. Matzelle\r
18  * @copyright 2001 - 2003 Brent R. Matzelle\r
19  */\r
20 class PHPMailer\r
21 {\r
22     /////////////////////////////////////////////////\r
23     // PUBLIC VARIABLES\r
24     /////////////////////////////////////////////////\r
25 \r
26     /**\r
27      * Email priority (1 = High, 3 = Normal, 5 = low).\r
28      * @var int\r
29      */\r
30     var $Priority          = 3;\r
31 \r
32     /**\r
33      * Sets the CharSet of the message.\r
34      * @var string\r
35      */\r
36     var $CharSet           = "iso-8859-1";\r
37 \r
38     /**\r
39      * Sets the Content-type of the message.\r
40      * @var string\r
41      */\r
42     var $ContentType        = "text/plain";\r
43 \r
44     /**\r
45      * Sets the Encoding of the message. Options for this are "8bit",\r
46      * "7bit", "binary", "base64", and "quoted-printable".\r
47      * @var string\r
48      */\r
49     var $Encoding          = "8bit";\r
50 \r
51     /**\r
52      * Holds the most recent mailer error message.\r
53      * @var string\r
54      */\r
55     var $ErrorInfo         = "";\r
56 \r
57     /**\r
58      * Sets the From email address for the message.\r
59      * @var string\r
60      */\r
61     var $From               = "";\r
62 \r
63     /**\r
64      * Sets the From name of the message.\r
65      * @var string\r
66      */\r
67     var $FromName           = "";\r
68 \r
69     /**\r
70      * Sets the Sender email (Return-Path) of the message.  If not empty,\r
71      * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.\r
72      * @var string\r
73      */\r
74     var $Sender            = "";\r
75 \r
76     /**\r
77      * Sets the Subject of the message.\r
78      * @var string\r
79      */\r
80     var $Subject           = "";\r
81 \r
82     /**\r
83      * Sets the Body of the message.  This can be either an HTML or text body.\r
84      * If HTML then run IsHTML(true).\r
85      * @var string\r
86      */\r
87     var $Body               = "";\r
88 \r
89     /**\r
90      * Sets the text-only body of the message.  This automatically sets the\r
91      * email to multipart/alternative.  This body can be read by mail\r
92      * clients that do not have HTML email capability such as mutt. Clients\r
93      * that can read HTML will view the normal Body.\r
94      * @var string\r
95      */\r
96     var $AltBody           = "";\r
97 \r
98     /**\r
99      * Sets word wrapping on the body of the message to a given number of \r
100      * characters.\r
101      * @var int\r
102      */\r
103     var $WordWrap          = 0;\r
104 \r
105     /**\r
106      * Method to send mail: ("mail", "sendmail", or "smtp").\r
107      * @var string\r
108      */\r
109     var $Mailer            = "mail";\r
110 \r
111     /**\r
112      * Sets the path of the sendmail program.\r
113      * @var string\r
114      */\r
115     var $Sendmail          = "/usr/sbin/sendmail";\r
116     \r
117     /**\r
118      * Path to PHPMailer plugins.  This is now only useful if the SMTP class \r
119      * is in a different directory than the PHP include path.  \r
120      * @var string\r
121      */\r
122     var $PluginDir         = "";\r
123 \r
124     /**\r
125      *  Holds PHPMailer version.\r
126      *  @var string\r
127      */\r
128     var $Version           = "1.73";\r
129 \r
130     /**\r
131      * Sets the email address that a reading confirmation will be sent.\r
132      * @var string\r
133      */\r
134     var $ConfirmReadingTo  = "";\r
135 \r
136     /**\r
137      *  Sets the hostname to use in Message-Id and Received headers\r
138      *  and as default HELO string. If empty, the value returned\r
139      *  by SERVER_NAME is used or 'localhost.localdomain'.\r
140      *  @var string\r
141      */\r
142     var $Hostname          = "";\r
143 \r
144     /////////////////////////////////////////////////\r
145     // SMTP VARIABLES\r
146     /////////////////////////////////////////////////\r
147 \r
148     /**\r
149      *  Sets the SMTP hosts.  All hosts must be separated by a\r
150      *  semicolon.  You can also specify a different port\r
151      *  for each host by using this format: [hostname:port]\r
152      *  (e.g. "smtp1.example.com:25;smtp2.example.com").\r
153      *  Hosts will be tried in order.\r
154      *  @var string\r
155      */\r
156     var $Host        = "localhost";\r
157 \r
158     /**\r
159      *  Sets the default SMTP server port.\r
160      *  @var int\r
161      */\r
162     var $Port        = 25;\r
163 \r
164     /**\r
165      *  Sets the SMTP HELO of the message (Default is $Hostname).\r
166      *  @var string\r
167      */\r
168     var $Helo        = "";\r
169 \r
170     /**\r
171      *  Sets SMTP authentication. Utilizes the Username and Password variables.\r
172      *  @var bool\r
173      */\r
174     var $SMTPAuth     = false;\r
175 \r
176     /**\r
177      *  Sets SMTP username.\r
178      *  @var string\r
179      */\r
180     var $Username     = "";\r
181 \r
182     /**\r
183      *  Sets SMTP password.\r
184      *  @var string\r
185      */\r
186     var $Password     = "";\r
187 \r
188     /**\r
189      *  Sets the SMTP server timeout in seconds. This function will not \r
190      *  work with the win32 version.\r
191      *  @var int\r
192      */\r
193     var $Timeout      = 10;\r
194 \r
195     /**\r
196      *  Sets SMTP class debugging on or off.\r
197      *  @var bool\r
198      */\r
199     var $SMTPDebug    = false;\r
200 \r
201     /**\r
202      * Prevents the SMTP connection from being closed after each mail \r
203      * sending.  If this is set to true then to close the connection \r
204      * requires an explicit call to SmtpClose(). \r
205      * @var bool\r
206      */\r
207     var $SMTPKeepAlive = false;\r
208 \r
209     /**#@+\r
210      * @access private\r
211      */\r
212     var $smtp            = NULL;\r
213     var $to              = array();\r
214     var $cc              = array();\r
215     var $bcc             = array();\r
216     var $ReplyTo         = array();\r
217     var $attachment      = array();\r
218     var $CustomHeader    = array();\r
219     var $message_type    = "";\r
220     var $boundary        = array();\r
221     var $language        = array();\r
222     var $error_count     = 0;\r
223     var $LE              = "\n";\r
224     /**#@-*/\r
225     \r
226     /////////////////////////////////////////////////\r
227     // VARIABLE METHODS\r
228     /////////////////////////////////////////////////\r
229 \r
230     /**\r
231      * Sets message type to HTML.  \r
232      * @param bool $bool\r
233      * @return void\r
234      */\r
235     function IsHTML($bool) {\r
236         if($bool == true)\r
237             $this->ContentType = "text/html";\r
238         else\r
239             $this->ContentType = "text/plain";\r
240     }\r
241 \r
242     /**\r
243      * Sets Mailer to send message using SMTP.\r
244      * @return void\r
245      */\r
246     function IsSMTP() {\r
247         $this->Mailer = "smtp";\r
248     }\r
249 \r
250     /**\r
251      * Sets Mailer to send message using PHP mail() function.\r
252      * @return void\r
253      */\r
254     function IsMail() {\r
255         $this->Mailer = "mail";\r
256     }\r
257 \r
258     /**\r
259      * Sets Mailer to send message using the $Sendmail program.\r
260      * @return void\r
261      */\r
262     function IsSendmail() {\r
263         $this->Mailer = "sendmail";\r
264     }\r
265 \r
266     /**\r
267      * Sets Mailer to send message using the qmail MTA. \r
268      * @return void\r
269      */\r
270     function IsQmail() {\r
271         $this->Sendmail = "/var/qmail/bin/sendmail";\r
272         $this->Mailer = "sendmail";\r
273     }\r
274 \r
275 \r
276     /////////////////////////////////////////////////\r
277     // RECIPIENT METHODS\r
278     /////////////////////////////////////////////////\r
279 \r
280     /**\r
281      * Adds a "To" address.  \r
282      * @param string $address\r
283      * @param string $name\r
284      * @return void\r
285      */\r
286     function AddAddress($address, $name = "") {\r
287         $cur = count($this->to);\r
288         $this->to[$cur][0] = trim($address);\r
289         $this->to[$cur][1] = $name;\r
290     }\r
291 \r
292     /**\r
293      * Adds a "Cc" address. Note: this function works\r
294      * with the SMTP mailer on win32, not with the "mail"\r
295      * mailer.  \r
296      * @param string $address\r
297      * @param string $name\r
298      * @return void\r
299     */\r
300     function AddCC($address, $name = "") {\r
301         $cur = count($this->cc);\r
302         $this->cc[$cur][0] = trim($address);\r
303         $this->cc[$cur][1] = $name;\r
304     }\r
305 \r
306     /**\r
307      * Adds a "Bcc" address. Note: this function works\r
308      * with the SMTP mailer on win32, not with the "mail"\r
309      * mailer.  \r
310      * @param string $address\r
311      * @param string $name\r
312      * @return void\r
313      */\r
314     function AddBCC($address, $name = "") {\r
315         $cur = count($this->bcc);\r
316         $this->bcc[$cur][0] = trim($address);\r
317         $this->bcc[$cur][1] = $name;\r
318     }\r
319 \r
320     /**\r
321      * Adds a "Reply-to" address.  \r
322      * @param string $address\r
323      * @param string $name\r
324      * @return void\r
325      */\r
326     function AddReplyTo($address, $name = "") {\r
327         $cur = count($this->ReplyTo);\r
328         $this->ReplyTo[$cur][0] = trim($address);\r
329         $this->ReplyTo[$cur][1] = $name;\r
330     }\r
331 \r
332 \r
333     /////////////////////////////////////////////////\r
334     // MAIL SENDING METHODS\r
335     /////////////////////////////////////////////////\r
336 \r
337     /**\r
338      * Creates message and assigns Mailer. If the message is\r
339      * not sent successfully then it returns false.  Use the ErrorInfo\r
340      * variable to view description of the error.  \r
341      * @return bool\r
342      */\r
343     function Send() {\r
344         $header = "";\r
345         $body = "";\r
346         $result = true;\r
347 \r
348         if((count($this->to) + count($this->cc) + count($this->bcc)) < 1)\r
349         {\r
350             $this->SetError($this->Lang("provide_address"));\r
351             return false;\r
352         }\r
353 \r
354         // Set whether the message is multipart/alternative\r
355         if(!empty($this->AltBody))\r
356             $this->ContentType = "multipart/alternative";\r
357 \r
358         $this->error_count = 0; // reset errors\r
359         $this->SetMessageType();\r
360         $header .= $this->CreateHeader();\r
361         $body = $this->CreateBody();\r
362 \r
363         if($body == "") { return false; }\r
364 \r
365         // Choose the mailer\r
366         switch($this->Mailer)\r
367         {\r
368             case "sendmail":\r
369                 $result = $this->SendmailSend($header, $body);\r
370                 break;\r
371             case "mail":\r
372                 $result = $this->MailSend($header, $body);\r
373                 break;\r
374             case "smtp":\r
375                 $result = $this->SmtpSend($header, $body);\r
376                 break;\r
377             default:\r
378             $this->SetError($this->Mailer . $this->Lang("mailer_not_supported"));\r
379                 $result = false;\r
380                 break;\r
381         }\r
382 \r
383         return $result;\r
384     }\r
385     \r
386     /**\r
387      * Sends mail using the $Sendmail program.  \r
388      * @access private\r
389      * @return bool\r
390      */\r
391     function SendmailSend($header, $body) {\r
392         if ($this->Sender != "")\r
393             $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));\r
394         else\r
395             $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));\r
396 \r
397         if(!@$mail = popen($sendmail, "w"))\r
398         {\r
399             $this->SetError($this->Lang("execute") . $this->Sendmail);\r
400             return false;\r
401         }\r
402 \r
403         fputs($mail, $header);\r
404         fputs($mail, $body);\r
405         \r
406         $result = pclose($mail) >> 8 & 0xFF;\r
407         if($result != 0)\r
408         {\r
409             $this->SetError($this->Lang("execute") . $this->Sendmail);\r
410             return false;\r
411         }\r
412 \r
413         return true;\r
414     }\r
415 \r
416     /**\r
417      * Sends mail using the PHP mail() function.  \r
418      * @access private\r
419      * @return bool\r
420      */\r
421     function MailSend($header, $body) {\r
422         $to = "";\r
423         for($i = 0; $i < count($this->to); $i++)\r
424         {\r
425             if($i != 0) { $to .= ", "; }\r
426             $to .= $this->to[$i][0];\r
427         }\r
428 \r
429         if ($this->Sender != "" && strlen(ini_get("safe_mode"))< 1)\r
430         {\r
431             $old_from = ini_get("sendmail_from");\r
432             ini_set("sendmail_from", $this->Sender);\r
433             $params = sprintf("-oi -f %s", $this->Sender);\r
434             $rt = @mail($to, $this->EncodeHeader($this->Subject), $body, \r
435                         $header, $params);\r
436         }\r
437         else\r
438             $rt = @mail($to, $this->EncodeHeader($this->Subject), $body, $header);\r
439 \r
440         if (isset($old_from))\r
441             ini_set("sendmail_from", $old_from);\r
442 \r
443         if(!$rt)\r
444         {\r
445             $this->SetError($this->Lang("instantiate"));\r
446             return false;\r
447         }\r
448 \r
449         return true;\r
450     }\r
451 \r
452     /**\r
453      * Sends mail via SMTP using PhpSMTP (Author:\r
454      * Chris Ryan).  Returns bool.  Returns false if there is a\r
455      * bad MAIL FROM, RCPT, or DATA input.\r
456      * @access private\r
457      * @return bool\r
458      */\r
459     function SmtpSend($header, $body) {\r
460         include_once($this->PluginDir . "class.smtp.php");\r
461         $error = "";\r
462         $bad_rcpt = array();\r
463 \r
464         if(!$this->SmtpConnect())\r
465             return false;\r
466 \r
467         $smtp_from = ($this->Sender == "") ? $this->From : $this->Sender;\r
468         if(!$this->smtp->Mail($smtp_from))\r
469         {\r
470             $error = $this->Lang("from_failed") . $smtp_from;\r
471             $this->SetError($error);\r
472             $this->smtp->Reset();\r
473             return false;\r
474         }\r
475 \r
476         // Attempt to send attach all recipients\r
477         for($i = 0; $i < count($this->to); $i++)\r
478         {\r
479             if(!$this->smtp->Recipient($this->to[$i][0]))\r
480                 $bad_rcpt[] = $this->to[$i][0];\r
481         }\r
482         for($i = 0; $i < count($this->cc); $i++)\r
483         {\r
484             if(!$this->smtp->Recipient($this->cc[$i][0]))\r
485                 $bad_rcpt[] = $this->cc[$i][0];\r
486         }\r
487         for($i = 0; $i < count($this->bcc); $i++)\r
488         {\r
489             if(!$this->smtp->Recipient($this->bcc[$i][0]))\r
490                 $bad_rcpt[] = $this->bcc[$i][0];\r
491         }\r
492 \r
493         if(count($bad_rcpt) > 0) // Create error message\r
494         {\r
495             for($i = 0; $i < count($bad_rcpt); $i++)\r
496             {\r
497                 if($i != 0) { $error .= ", "; }\r
498                 $error .= $bad_rcpt[$i];\r
499             }\r
500             $error = $this->Lang("recipients_failed") . $error;\r
501             $this->SetError($error);\r
502             $this->smtp->Reset();\r
503             return false;\r
504         }\r
505 \r
506         if(!$this->smtp->Data($header . $body))\r
507         {\r
508             $this->SetError($this->Lang("data_not_accepted"));\r
509             $this->smtp->Reset();\r
510             return false;\r
511         }\r
512         if($this->SMTPKeepAlive == true)\r
513             $this->smtp->Reset();\r
514         else\r
515             $this->SmtpClose();\r
516 \r
517         return true;\r
518     }\r
519 \r
520     /**\r
521      * Initiates a connection to an SMTP server.  Returns false if the \r
522      * operation failed.\r
523      * @access private\r
524      * @return bool\r
525      */\r
526     function SmtpConnect() {\r
527         if($this->smtp == NULL) { $this->smtp = new SMTP(); }\r
528 \r
529         $this->smtp->do_debug = $this->SMTPDebug;\r
530         $hosts = explode(";", $this->Host);\r
531         $index = 0;\r
532         $connection = ($this->smtp->Connected()); \r
533 \r
534         // Retry while there is no connection\r
535         while($index < count($hosts) && $connection == false)\r
536         {\r
537             if(strstr($hosts[$index], ":"))\r
538                 list($host, $port) = explode(":", $hosts[$index]);\r
539             else\r
540             {\r
541                 $host = $hosts[$index];\r
542                 $port = $this->Port;\r
543             }\r
544 \r
545             if($this->smtp->Connect($host, $port, $this->Timeout))\r
546             {\r
547                 if ($this->Helo != '')\r
548                     $this->smtp->Hello($this->Helo);\r
549                 else\r
550                     $this->smtp->Hello($this->ServerHostname());\r
551         \r
552                 if($this->SMTPAuth)\r
553                 {\r
554                     if(!$this->smtp->Authenticate($this->Username, \r
555                                                   $this->Password))\r
556                     {\r
557                         $this->SetError($this->Lang("authenticate"));\r
558                         $this->smtp->Reset();\r
559                         $connection = false;\r
560                     }\r
561                 }\r
562                 $connection = true;\r
563             }\r
564             $index++;\r
565         }\r
566         if(!$connection)\r
567             $this->SetError($this->Lang("connect_host"));\r
568 \r
569         return $connection;\r
570     }\r
571 \r
572     /**\r
573      * Closes the active SMTP session if one exists.\r
574      * @return void\r
575      */\r
576     function SmtpClose() {\r
577         if($this->smtp != NULL)\r
578         {\r
579             if($this->smtp->Connected())\r
580             {\r
581                 $this->smtp->Quit();\r
582                 $this->smtp->Close();\r
583             }\r
584         }\r
585     }\r
586 \r
587     /**\r
588      * Sets the language for all class error messages.  Returns false \r
589      * if it cannot load the language file.  The default language type\r
590      * is English.\r
591      * @param string $lang_type Type of language (e.g. Portuguese: "br")\r
592      * @param string $lang_path Path to the language file directory\r
593      * @access public\r
594      * @return bool\r
595      */\r
596     function SetLanguage($lang_type, $lang_path = "language/") {\r
597         if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php'))\r
598             include($lang_path.'phpmailer.lang-'.$lang_type.'.php');\r
599         else if(file_exists($lang_path.'phpmailer.lang-en.php'))\r
600             include($lang_path.'phpmailer.lang-en.php');\r
601         else\r
602         {\r
603             $this->SetError("Could not load language file");\r
604             return false;\r
605         }\r
606         $this->language = $PHPMAILER_LANG;\r
607     \r
608         return true;\r
609     }\r
610 \r
611     /////////////////////////////////////////////////\r
612     // MESSAGE CREATION METHODS\r
613     /////////////////////////////////////////////////\r
614 \r
615     /**\r
616      * Creates recipient headers.  \r
617      * @access private\r
618      * @return string\r
619      */\r
620     function AddrAppend($type, $addr) {\r
621         $addr_str = $type . ": ";\r
622         $addr_str .= $this->AddrFormat($addr[0]);\r
623         if(count($addr) > 1)\r
624         {\r
625             for($i = 1; $i < count($addr); $i++)\r
626                 $addr_str .= ", " . $this->AddrFormat($addr[$i]);\r
627         }\r
628         $addr_str .= $this->LE;\r
629 \r
630         return $addr_str;\r
631     }\r
632     \r
633     /**\r
634      * Formats an address correctly. \r
635      * @access private\r
636      * @return string\r
637      */\r
638     function AddrFormat($addr) {\r
639         if(empty($addr[1]))\r
640             $formatted = $addr[0];\r
641         else\r
642         {\r
643             $formatted = $this->EncodeHeader($addr[1], 'phrase') . " <" . \r
644                          $addr[0] . ">";\r
645         }\r
646 \r
647         return $formatted;\r
648     }\r
649 \r
650     /**\r
651      * Wraps message for use with mailers that do not\r
652      * automatically perform wrapping and for quoted-printable.\r
653      * Original written by philippe.  \r
654      * @access private\r
655      * @return string\r
656      */\r
657     function WrapText($message, $length, $qp_mode = false) {\r
658         $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;\r
659 \r
660         $message = $this->FixEOL($message);\r
661         if (substr($message, -1) == $this->LE)\r
662             $message = substr($message, 0, -1);\r
663 \r
664         $line = explode($this->LE, $message);\r
665         $message = "";\r
666         for ($i=0 ;$i < count($line); $i++)\r
667         {\r
668           $line_part = explode(" ", $line[$i]);\r
669           $buf = "";\r
670           for ($e = 0; $e<count($line_part); $e++)\r
671           {\r
672               $word = $line_part[$e];\r
673               if ($qp_mode and (strlen($word) > $length))\r
674               {\r
675                 $space_left = $length - strlen($buf) - 1;\r
676                 if ($e != 0)\r
677                 {\r
678                     if ($space_left > 20)\r
679                     {\r
680                         $len = $space_left;\r
681                         if (substr($word, $len - 1, 1) == "=")\r
682                           $len--;\r
683                         elseif (substr($word, $len - 2, 1) == "=")\r
684                           $len -= 2;\r
685                         $part = substr($word, 0, $len);\r
686                         $word = substr($word, $len);\r
687                         $buf .= " " . $part;\r
688                         $message .= $buf . sprintf("=%s", $this->LE);\r
689                     }\r
690                     else\r
691                     {\r
692                         $message .= $buf . $soft_break;\r
693                     }\r
694                     $buf = "";\r
695                 }\r
696                 while (strlen($word) > 0)\r
697                 {\r
698                     $len = $length;\r
699                     if (substr($word, $len - 1, 1) == "=")\r
700                         $len--;\r
701                     elseif (substr($word, $len - 2, 1) == "=")\r
702                         $len -= 2;\r
703                     $part = substr($word, 0, $len);\r
704                     $word = substr($word, $len);\r
705 \r
706                     if (strlen($word) > 0)\r
707                         $message .= $part . sprintf("=%s", $this->LE);\r
708                     else\r
709                         $buf = $part;\r
710                 }\r
711               }\r
712               else\r
713               {\r
714                 $buf_o = $buf;\r
715                 $buf .= ($e == 0) ? $word : (" " . $word); \r
716 \r
717                 if (strlen($buf) > $length and $buf_o != "")\r
718                 {\r
719                     $message .= $buf_o . $soft_break;\r
720                     $buf = $word;\r
721                 }\r
722               }\r
723           }\r
724           $message .= $buf . $this->LE;\r
725         }\r
726 \r
727         return $message;\r
728     }\r
729     \r
730     /**\r
731      * Set the body wrapping.\r
732      * @access private\r
733      * @return void\r
734      */\r
735     function SetWordWrap() {\r
736         if($this->WordWrap < 1)\r
737             return;\r
738             \r
739         switch($this->message_type)\r
740         {\r
741            case "alt":\r
742               // fall through\r
743            case "alt_attachments":\r
744               $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);\r
745               break;\r
746            default:\r
747               $this->Body = $this->WrapText($this->Body, $this->WordWrap);\r
748               break;\r
749         }\r
750     }\r
751 \r
752     /**\r
753      * Assembles message header.  \r
754      * @access private\r
755      * @return string\r
756      */\r
757     function CreateHeader() {\r
758         $result = "";\r
759         \r
760         // Set the boundaries\r
761         $uniq_id = md5(uniqid(time()));\r
762         $this->boundary[1] = "b1_" . $uniq_id;\r
763         $this->boundary[2] = "b2_" . $uniq_id;\r
764 \r
765         $result .= $this->HeaderLine("Date", $this->RFCDate());\r
766         if($this->Sender == "")\r
767             $result .= $this->HeaderLine("Return-Path", trim($this->From));\r
768         else\r
769             $result .= $this->HeaderLine("Return-Path", trim($this->Sender));\r
770         \r
771         // To be created automatically by mail()\r
772         if($this->Mailer != "mail")\r
773         {\r
774             if(count($this->to) > 0)\r
775                 $result .= $this->AddrAppend("To", $this->to);\r
776             else if (count($this->cc) == 0)\r
777                 $result .= $this->HeaderLine("To", "undisclosed-recipients:;");\r
778             if(count($this->cc) > 0)\r
779                 $result .= $this->AddrAppend("Cc", $this->cc);\r
780         }\r
781 \r
782         $from = array();\r
783         $from[0][0] = trim($this->From);\r
784         $from[0][1] = $this->FromName;\r
785         $result .= $this->AddrAppend("From", $from); \r
786 \r
787         // sendmail and mail() extract Bcc from the header before sending\r
788         if((($this->Mailer == "sendmail") || ($this->Mailer == "mail")) && (count($this->bcc) > 0))\r
789             $result .= $this->AddrAppend("Bcc", $this->bcc);\r
790 \r
791         if(count($this->ReplyTo) > 0)\r
792             $result .= $this->AddrAppend("Reply-to", $this->ReplyTo);\r
793 \r
794         // mail() sets the subject itself\r
795         if($this->Mailer != "mail")\r
796             $result .= $this->HeaderLine("Subject", $this->EncodeHeader(trim($this->Subject)));\r
797 \r
798         $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);\r
799         $result .= $this->HeaderLine("X-Priority", $this->Priority);\r
800         $result .= $this->HeaderLine("X-Mailer", "PHPMailer [version " . $this->Version . "]");\r
801         \r
802         if($this->ConfirmReadingTo != "")\r
803         {\r
804             $result .= $this->HeaderLine("Disposition-Notification-To", \r
805                        "<" . trim($this->ConfirmReadingTo) . ">");\r
806         }\r
807 \r
808         // Add custom headers\r
809         for($index = 0; $index < count($this->CustomHeader); $index++)\r
810         {\r
811             $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), \r
812                        $this->EncodeHeader(trim($this->CustomHeader[$index][1])));\r
813         }\r
814         $result .= $this->HeaderLine("MIME-Version", "1.0");\r
815 \r
816         switch($this->message_type)\r
817         {\r
818             case "plain":\r
819                 $result .= $this->HeaderLine("Content-Transfer-Encoding", $this->Encoding);\r
820                 $result .= sprintf("Content-Type: %s; charset=\"%s\"",\r
821                                     $this->ContentType, $this->CharSet);\r
822                 break;\r
823             case "attachments":\r
824                 // fall through\r
825             case "alt_attachments":\r
826                 if($this->InlineImageExists())\r
827                 {\r
828                     $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", \r
829                                     "multipart/related", $this->LE, $this->LE, \r
830                                     $this->boundary[1], $this->LE);\r
831                 }\r
832                 else\r
833                 {\r
834                     $result .= $this->HeaderLine("Content-Type", "multipart/mixed;");\r
835                     $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');\r
836                 }\r
837                 break;\r
838             case "alt":\r
839                 $result .= $this->HeaderLine("Content-Type", "multipart/alternative;");\r
840                 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');\r
841                 break;\r
842         }\r
843 \r
844         if($this->Mailer != "mail")\r
845             $result .= $this->LE.$this->LE;\r
846 \r
847         return $result;\r
848     }\r
849 \r
850     /**\r
851      * Assembles the message body.  Returns an empty string on failure.\r
852      * @access private\r
853      * @return string\r
854      */\r
855     function CreateBody() {\r
856         $result = "";\r
857 \r
858         $this->SetWordWrap();\r
859 \r
860         switch($this->message_type)\r
861         {\r
862             case "alt":\r
863                 $result .= $this->GetBoundary($this->boundary[1], "", \r
864                                               "text/plain", "");\r
865                 $result .= $this->EncodeString($this->AltBody, $this->Encoding);\r
866                 $result .= $this->LE.$this->LE;\r
867                 $result .= $this->GetBoundary($this->boundary[1], "", \r
868                                               "text/html", "");\r
869                 \r
870                 $result .= $this->EncodeString($this->Body, $this->Encoding);\r
871                 $result .= $this->LE.$this->LE;\r
872     \r
873                 $result .= $this->EndBoundary($this->boundary[1]);\r
874                 break;\r
875             case "plain":\r
876                 $result .= $this->EncodeString($this->Body, $this->Encoding);\r
877                 break;\r
878             case "attachments":\r
879                 $result .= $this->GetBoundary($this->boundary[1], "", "", "");\r
880                 $result .= $this->EncodeString($this->Body, $this->Encoding);\r
881                 $result .= $this->LE;\r
882      \r
883                 $result .= $this->AttachAll();\r
884                 break;\r
885             case "alt_attachments":\r
886                 $result .= sprintf("--%s%s", $this->boundary[1], $this->LE);\r
887                 $result .= sprintf("Content-Type: %s;%s" .\r
888                                    "\tboundary=\"%s\"%s",\r
889                                    "multipart/alternative", $this->LE, \r
890                                    $this->boundary[2], $this->LE.$this->LE);\r
891     \r
892                 // Create text body\r
893                 $result .= $this->GetBoundary($this->boundary[2], "", \r
894                                               "text/plain", "") . $this->LE;\r
895 \r
896                 $result .= $this->EncodeString($this->AltBody, $this->Encoding);\r
897                 $result .= $this->LE.$this->LE;\r
898     \r
899                 // Create the HTML body\r
900                 $result .= $this->GetBoundary($this->boundary[2], "", \r
901                                               "text/html", "") . $this->LE;\r
902     \r
903                 $result .= $this->EncodeString($this->Body, $this->Encoding);\r
904                 $result .= $this->LE.$this->LE;\r
905 \r
906                 $result .= $this->EndBoundary($this->boundary[2]);\r
907                 \r
908                 $result .= $this->AttachAll();\r
909                 break;\r
910         }\r
911         if($this->IsError())\r
912             $result = "";\r
913 \r
914         return $result;\r
915     }\r
916 \r
917     /**\r
918      * Returns the start of a message boundary.\r
919      * @access private\r
920      */\r
921     function GetBoundary($boundary, $charSet, $contentType, $encoding) {\r
922         $result = "";\r
923         if($charSet == "") { $charSet = $this->CharSet; }\r
924         if($contentType == "") { $contentType = $this->ContentType; }\r
925         if($encoding == "") { $encoding = $this->Encoding; }\r
926 \r
927         $result .= $this->TextLine("--" . $boundary);\r
928         $result .= sprintf("Content-Type: %s; charset = \"%s\"", \r
929                             $contentType, $charSet);\r
930         $result .= $this->LE;\r
931         $result .= $this->HeaderLine("Content-Transfer-Encoding", $encoding);\r
932         $result .= $this->LE;\r
933        \r
934         return $result;\r
935     }\r
936     \r
937     /**\r
938      * Returns the end of a message boundary.\r
939      * @access private\r
940      */\r
941     function EndBoundary($boundary) {\r
942         return $this->LE . "--" . $boundary . "--" . $this->LE; \r
943     }\r
944     \r
945     /**\r
946      * Sets the message type.\r
947      * @access private\r
948      * @return void\r
949      */\r
950     function SetMessageType() {\r
951         if(count($this->attachment) < 1 && strlen($this->AltBody) < 1)\r
952             $this->message_type = "plain";\r
953         else\r
954         {\r
955             if(count($this->attachment) > 0)\r
956                 $this->message_type = "attachments";\r
957             if(strlen($this->AltBody) > 0 && count($this->attachment) < 1)\r
958                 $this->message_type = "alt";\r
959             if(strlen($this->AltBody) > 0 && count($this->attachment) > 0)\r
960                 $this->message_type = "alt_attachments";\r
961         }\r
962     }\r
963 \r
964     /**\r
965      * Returns a formatted header line.\r
966      * @access private\r
967      * @return string\r
968      */\r
969     function HeaderLine($name, $value) {\r
970         return $name . ": " . $value . $this->LE;\r
971     }\r
972 \r
973     /**\r
974      * Returns a formatted mail line.\r
975      * @access private\r
976      * @return string\r
977      */\r
978     function TextLine($value) {\r
979         return $value . $this->LE;\r
980     }\r
981 \r
982     /////////////////////////////////////////////////\r
983     // ATTACHMENT METHODS\r
984     /////////////////////////////////////////////////\r
985 \r
986     /**\r
987      * Adds an attachment from a path on the filesystem.\r
988      * Returns false if the file could not be found\r
989      * or accessed.\r
990      * @param string $path Path to the attachment.\r
991      * @param string $name Overrides the attachment name.\r
992      * @param string $encoding File encoding (see $Encoding).\r
993      * @param string $type File extension (MIME) type.\r
994      * @return bool\r
995      */\r
996     function AddAttachment($path, $name = "", $encoding = "base64", \r
997                            $type = "application/octet-stream") {\r
998         if(!@is_file($path))\r
999         {\r
1000             $this->SetError($this->Lang("file_access") . $path);\r
1001             return false;\r
1002         }\r
1003 \r
1004         $filename = basename($path);\r
1005         if($name == "")\r
1006             $name = $filename;\r
1007 \r
1008         $cur = count($this->attachment);\r
1009         $this->attachment[$cur][0] = $path;\r
1010         $this->attachment[$cur][1] = $filename;\r
1011         $this->attachment[$cur][2] = $name;\r
1012         $this->attachment[$cur][3] = $encoding;\r
1013         $this->attachment[$cur][4] = $type;\r
1014         $this->attachment[$cur][5] = false; // isStringAttachment\r
1015         $this->attachment[$cur][6] = "attachment";\r
1016         $this->attachment[$cur][7] = 0;\r
1017 \r
1018         return true;\r
1019     }\r
1020 \r
1021     /**\r
1022      * Attaches all fs, string, and binary attachments to the message.\r
1023      * Returns an empty string on failure.\r
1024      * @access private\r
1025      * @return string\r
1026      */\r
1027     function AttachAll() {\r
1028         // Return text of body\r
1029         $mime = array();\r
1030 \r
1031         // Add all attachments\r
1032         for($i = 0; $i < count($this->attachment); $i++)\r
1033         {\r
1034             // Check for string attachment\r
1035             $bString = $this->attachment[$i][5];\r
1036             if ($bString)\r
1037                 $string = $this->attachment[$i][0];\r
1038             else\r
1039                 $path = $this->attachment[$i][0];\r
1040 \r
1041             $filename    = $this->attachment[$i][1];\r
1042             $name        = $this->attachment[$i][2];\r
1043             $encoding    = $this->attachment[$i][3];\r
1044             $type        = $this->attachment[$i][4];\r
1045             $disposition = $this->attachment[$i][6];\r
1046             $cid         = $this->attachment[$i][7];\r
1047             \r
1048             $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);\r
1049             $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE);\r
1050             $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);\r
1051 \r
1052             if($disposition == "inline")\r
1053                 $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);\r
1054 \r
1055             $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", \r
1056                               $disposition, $name, $this->LE.$this->LE);\r
1057 \r
1058             // Encode as string attachment\r
1059             if($bString)\r
1060             {\r
1061                 $mime[] = $this->EncodeString($string, $encoding);\r
1062                 if($this->IsError()) { return ""; }\r
1063                 $mime[] = $this->LE.$this->LE;\r
1064             }\r
1065             else\r
1066             {\r
1067                 $mime[] = $this->EncodeFile($path, $encoding);                \r
1068                 if($this->IsError()) { return ""; }\r
1069                 $mime[] = $this->LE.$this->LE;\r
1070             }\r
1071         }\r
1072 \r
1073         $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);\r
1074 \r
1075         return join("", $mime);\r
1076     }\r
1077     \r
1078     /**\r
1079      * Encodes attachment in requested format.  Returns an\r
1080      * empty string on failure.\r
1081      * @access private\r
1082      * @return string\r
1083      */\r
1084     function EncodeFile ($path, $encoding = "base64") {\r
1085         if(!@$fd = fopen($path, "rb"))\r
1086         {\r
1087             $this->SetError($this->Lang("file_open") . $path);\r
1088             return "";\r
1089         }\r
1090         $magic_quotes = get_magic_quotes_runtime();\r
1091         set_magic_quotes_runtime(0);\r
1092         $file_buffer = fread($fd, filesize($path));\r
1093         $file_buffer = $this->EncodeString($file_buffer, $encoding);\r
1094         fclose($fd);\r
1095         set_magic_quotes_runtime($magic_quotes);\r
1096 \r
1097         return $file_buffer;\r
1098     }\r
1099 \r
1100     /**\r
1101      * Encodes string to requested format. Returns an\r
1102      * empty string on failure.\r
1103      * @access private\r
1104      * @return string\r
1105      */\r
1106     function EncodeString ($str, $encoding = "base64") {\r
1107         $encoded = "";\r
1108         switch(strtolower($encoding)) {\r
1109           case "base64":\r
1110               // chunk_split is found in PHP >= 3.0.6\r
1111               $encoded = chunk_split(base64_encode($str), 76, $this->LE);\r
1112               break;\r
1113           case "7bit":\r
1114           case "8bit":\r
1115               $encoded = $this->FixEOL($str);\r
1116               if (substr($encoded, -(strlen($this->LE))) != $this->LE)\r
1117                 $encoded .= $this->LE;\r
1118               break;\r
1119           case "binary":\r
1120               $encoded = $str;\r
1121               break;\r
1122           case "quoted-printable":\r
1123               $encoded = $this->EncodeQP($str);\r
1124               break;\r
1125           default:\r
1126               $this->SetError($this->Lang("encoding") . $encoding);\r
1127               break;\r
1128         }\r
1129         return $encoded;\r
1130     }\r
1131 \r
1132     /**\r
1133      * Encode a header string to best of Q, B, quoted or none.  \r
1134      * @access private\r
1135      * @return string\r
1136      */\r
1137     function EncodeHeader ($str, $position = 'text') {\r
1138       $x = 0;\r
1139       \r
1140       switch (strtolower($position)) {\r
1141         case 'phrase':\r
1142           if (!preg_match('/[\200-\377]/', $str)) {\r
1143             // Can't use addslashes as we don't know what value has magic_quotes_sybase.\r
1144             $encoded = addcslashes($str, "\0..\37\177\\\"");\r
1145 \r
1146             if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str))\r
1147               return ($encoded);\r
1148             else\r
1149               return ("\"$encoded\"");\r
1150           }\r
1151           $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);\r
1152           break;\r
1153         case 'comment':\r
1154           $x = preg_match_all('/[()"]/', $str, $matches);\r
1155           // Fall-through\r
1156         case 'text':\r
1157         default:\r
1158           $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);\r
1159           break;\r
1160       }\r
1161 \r
1162       if ($x == 0)\r
1163         return ($str);\r
1164 \r
1165       $maxlen = 75 - 7 - strlen($this->CharSet);\r
1166       // Try to select the encoding which should produce the shortest output\r
1167       if (strlen($str)/3 < $x) {\r
1168         $encoding = 'B';\r
1169         $encoded = base64_encode($str);\r
1170         $maxlen -= $maxlen % 4;\r
1171         $encoded = trim(chunk_split($encoded, $maxlen, "\n"));\r
1172       } else {\r
1173         $encoding = 'Q';\r
1174         $encoded = $this->EncodeQ($str, $position);\r
1175         $encoded = $this->WrapText($encoded, $maxlen, true);\r
1176         $encoded = str_replace("=".$this->LE, "\n", trim($encoded));\r
1177       }\r
1178 \r
1179       $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);\r
1180       $encoded = trim(str_replace("\n", $this->LE, $encoded));\r
1181       \r
1182       return $encoded;\r
1183     }\r
1184     \r
1185     /**\r
1186      * Encode string to quoted-printable.  \r
1187      * @access private\r
1188      * @return string\r
1189      */\r
1190     function EncodeQP ($str) {\r
1191         $encoded = $this->FixEOL($str);\r
1192         if (substr($encoded, -(strlen($this->LE))) != $this->LE)\r
1193             $encoded .= $this->LE;\r
1194 \r
1195         // Replace every high ascii, control and = characters\r
1196         $encoded = preg_replace('/([\000-\010\013\014\016-\037\075\177-\377])/e',\r
1197                   "'='.sprintf('%02X', ord('\\1'))", $encoded);\r
1198         // Replace every spaces and tabs when it's the last character on a line\r
1199         $encoded = preg_replace("/([\011\040])".$this->LE."/e",\r
1200                   "'='.sprintf('%02X', ord('\\1')).'".$this->LE."'", $encoded);\r
1201 \r
1202         // Maximum line length of 76 characters before CRLF (74 + space + '=')\r
1203         $encoded = $this->WrapText($encoded, 74, true);\r
1204 \r
1205         return $encoded;\r
1206     }\r
1207 \r
1208     /**\r
1209      * Encode string to q encoding.  \r
1210      * @access private\r
1211      * @return string\r
1212      */\r
1213     function EncodeQ ($str, $position = "text") {\r
1214         // There should not be any EOL in the string\r
1215         $encoded = preg_replace("[\r\n]", "", $str);\r
1216 \r
1217         switch (strtolower($position)) {\r
1218           case "phrase":\r
1219             $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);\r
1220             break;\r
1221           case "comment":\r
1222             $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);\r
1223           case "text":\r
1224           default:\r
1225             // Replace every high ascii, control =, ? and _ characters\r
1226             $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',\r
1227                   "'='.sprintf('%02X', ord('\\1'))", $encoded);\r
1228             break;\r
1229         }\r
1230         \r
1231         // Replace every spaces to _ (more readable than =20)\r
1232         $encoded = str_replace(" ", "_", $encoded);\r
1233 \r
1234         return $encoded;\r
1235     }\r
1236 \r
1237     /**\r
1238      * Adds a string or binary attachment (non-filesystem) to the list.\r
1239      * This method can be used to attach ascii or binary data,\r
1240      * such as a BLOB record from a database.\r
1241      * @param string $string String attachment data.\r
1242      * @param string $filename Name of the attachment.\r
1243      * @param string $encoding File encoding (see $Encoding).\r
1244      * @param string $type File extension (MIME) type.\r
1245      * @return void\r
1246      */\r
1247     function AddStringAttachment($string, $filename, $encoding = "base64", \r
1248                                  $type = "application/octet-stream") {\r
1249         // Append to $attachment array\r
1250         $cur = count($this->attachment);\r
1251         $this->attachment[$cur][0] = $string;\r
1252         $this->attachment[$cur][1] = $filename;\r
1253         $this->attachment[$cur][2] = $filename;\r
1254         $this->attachment[$cur][3] = $encoding;\r
1255         $this->attachment[$cur][4] = $type;\r
1256         $this->attachment[$cur][5] = true; // isString\r
1257         $this->attachment[$cur][6] = "attachment";\r
1258         $this->attachment[$cur][7] = 0;\r
1259     }\r
1260     \r
1261     /**\r
1262      * Adds an embedded attachment.  This can include images, sounds, and \r
1263      * just about any other document.  Make sure to set the $type to an \r
1264      * image type.  For JPEG images use "image/jpeg" and for GIF images \r
1265      * use "image/gif".\r
1266      * @param string $path Path to the attachment.\r
1267      * @param string $cid Content ID of the attachment.  Use this to identify \r
1268      *        the Id for accessing the image in an HTML form.\r
1269      * @param string $name Overrides the attachment name.\r
1270      * @param string $encoding File encoding (see $Encoding).\r
1271      * @param string $type File extension (MIME) type.  \r
1272      * @return bool\r
1273      */\r
1274     function AddEmbeddedImage($path, $cid, $name = "", $encoding = "base64", \r
1275                               $type = "application/octet-stream") {\r
1276     \r
1277         if(!@is_file($path))\r
1278         {\r
1279             $this->SetError($this->Lang("file_access") . $path);\r
1280             return false;\r
1281         }\r
1282 \r
1283         $filename = basename($path);\r
1284         if($name == "")\r
1285             $name = $filename;\r
1286 \r
1287         // Append to $attachment array\r
1288         $cur = count($this->attachment);\r
1289         $this->attachment[$cur][0] = $path;\r
1290         $this->attachment[$cur][1] = $filename;\r
1291         $this->attachment[$cur][2] = $name;\r
1292         $this->attachment[$cur][3] = $encoding;\r
1293         $this->attachment[$cur][4] = $type;\r
1294         $this->attachment[$cur][5] = false; // isStringAttachment\r
1295         $this->attachment[$cur][6] = "inline";\r
1296         $this->attachment[$cur][7] = $cid;\r
1297     \r
1298         return true;\r
1299     }\r
1300     \r
1301     /**\r
1302      * Returns true if an inline attachment is present.\r
1303      * @access private\r
1304      * @return bool\r
1305      */\r
1306     function InlineImageExists() {\r
1307         $result = false;\r
1308         for($i = 0; $i < count($this->attachment); $i++)\r
1309         {\r
1310             if($this->attachment[$i][6] == "inline")\r
1311             {\r
1312                 $result = true;\r
1313                 break;\r
1314             }\r
1315         }\r
1316         \r
1317         return $result;\r
1318     }\r
1319 \r
1320     /////////////////////////////////////////////////\r
1321     // MESSAGE RESET METHODS\r
1322     /////////////////////////////////////////////////\r
1323 \r
1324     /**\r
1325      * Clears all recipients assigned in the TO array.  Returns void.\r
1326      * @return void\r
1327      */\r
1328     function ClearAddresses() {\r
1329         $this->to = array();\r
1330     }\r
1331 \r
1332     /**\r
1333      * Clears all recipients assigned in the CC array.  Returns void.\r
1334      * @return void\r
1335      */\r
1336     function ClearCCs() {\r
1337         $this->cc = array();\r
1338     }\r
1339 \r
1340     /**\r
1341      * Clears all recipients assigned in the BCC array.  Returns void.\r
1342      * @return void\r
1343      */\r
1344     function ClearBCCs() {\r
1345         $this->bcc = array();\r
1346     }\r
1347 \r
1348     /**\r
1349      * Clears all recipients assigned in the ReplyTo array.  Returns void.\r
1350      * @return void\r
1351      */\r
1352     function ClearReplyTos() {\r
1353         $this->ReplyTo = array();\r
1354     }\r
1355 \r
1356     /**\r
1357      * Clears all recipients assigned in the TO, CC and BCC\r
1358      * array.  Returns void.\r
1359      * @return void\r
1360      */\r
1361     function ClearAllRecipients() {\r
1362         $this->to = array();\r
1363         $this->cc = array();\r
1364         $this->bcc = array();\r
1365     }\r
1366 \r
1367     /**\r
1368      * Clears all previously set filesystem, string, and binary\r
1369      * attachments.  Returns void.\r
1370      * @return void\r
1371      */\r
1372     function ClearAttachments() {\r
1373         $this->attachment = array();\r
1374     }\r
1375 \r
1376     /**\r
1377      * Clears all custom headers.  Returns void.\r
1378      * @return void\r
1379      */\r
1380     function ClearCustomHeaders() {\r
1381         $this->CustomHeader = array();\r
1382     }\r
1383 \r
1384 \r
1385     /////////////////////////////////////////////////\r
1386     // MISCELLANEOUS METHODS\r
1387     /////////////////////////////////////////////////\r
1388 \r
1389     /**\r
1390      * Adds the error message to the error container.\r
1391      * Returns void.\r
1392      * @access private\r
1393      * @return void\r
1394      */\r
1395     function SetError($msg) {\r
1396         $this->error_count++;\r
1397         $this->ErrorInfo = $msg;\r
1398     }\r
1399 \r
1400     /**\r
1401      * Returns the proper RFC 822 formatted date. \r
1402      * @access private\r
1403      * @return string\r
1404      */\r
1405     function RFCDate() {\r
1406         $tz = date("Z");\r
1407         $tzs = ($tz < 0) ? "-" : "+";\r
1408         $tz = abs($tz);\r
1409         $tz = ($tz/3600)*100 + ($tz%3600)/60;\r
1410         $result = sprintf("%s %s%04d", date("D, j M Y H:i:s"), $tzs, $tz);\r
1411 \r
1412         return $result;\r
1413     }\r
1414     \r
1415     /**\r
1416      * Returns the appropriate server variable.  Should work with both \r
1417      * PHP 4.1.0+ as well as older versions.  Returns an empty string \r
1418      * if nothing is found.\r
1419      * @access private\r
1420      * @return mixed\r
1421      */\r
1422     function ServerVar($varName) {\r
1423         global $HTTP_SERVER_VARS;\r
1424         global $HTTP_ENV_VARS;\r
1425 \r
1426         if(!isset($_SERVER))\r
1427         {\r
1428             $_SERVER = $HTTP_SERVER_VARS;\r
1429             if(!isset($_SERVER["REMOTE_ADDR"]))\r
1430                 $_SERVER = $HTTP_ENV_VARS; // must be Apache\r
1431         }\r
1432         \r
1433         if(isset($_SERVER[$varName]))\r
1434             return $_SERVER[$varName];\r
1435         else\r
1436             return "";\r
1437     }\r
1438 \r
1439     /**\r
1440      * Returns the server hostname or 'localhost.localdomain' if unknown.\r
1441      * @access private\r
1442      * @return string\r
1443      */\r
1444     function ServerHostname() {\r
1445         if ($this->Hostname != "")\r
1446             $result = $this->Hostname;\r
1447         elseif ($this->ServerVar('SERVER_NAME') != "")\r
1448             $result = $this->ServerVar('SERVER_NAME');\r
1449         else\r
1450             $result = "localhost.localdomain";\r
1451 \r
1452         return $result;\r
1453     }\r
1454 \r
1455     /**\r
1456      * Returns a message in the appropriate language.\r
1457      * @access private\r
1458      * @return string\r
1459      */\r
1460     function Lang($key) {\r
1461         if(count($this->language) < 1)\r
1462             $this->SetLanguage("en"); // set the default language\r
1463     \r
1464         if(isset($this->language[$key]))\r
1465             return $this->language[$key];\r
1466         else\r
1467             return "Language string failed to load: " . $key;\r
1468     }\r
1469     \r
1470     /**\r
1471      * Returns true if an error occurred.\r
1472      * @return bool\r
1473      */\r
1474     function IsError() {\r
1475         return ($this->error_count > 0);\r
1476     }\r
1477 \r
1478     /**\r
1479      * Changes every end of line from CR or LF to CRLF.  \r
1480      * @access private\r
1481      * @return string\r
1482      */\r
1483     function FixEOL($str) {\r
1484         $str = str_replace("\r\n", "\n", $str);\r
1485         $str = str_replace("\r", "\n", $str);\r
1486         $str = str_replace("\n", $this->LE, $str);\r
1487         return $str;\r
1488     }\r
1489 \r
1490     /**\r
1491      * Adds a custom header. \r
1492      * @return void\r
1493      */\r
1494     function AddCustomHeader($custom_header) {\r
1495         $this->CustomHeader[] = explode(":", $custom_header, 2);\r
1496     }\r
1497 }\r
1498 \r
1499 ?>