Xataface Email Module 0.3
Email/Mailmerge Module for Xataface
lib/XPM/PHP5/MIME5.php
Go to the documentation of this file.
00001 <?php
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  *                                                                                         *
00005  *  XPertMailer is a PHP Mail Class that can send and read messages in MIME format.        *
00006  *  This file is part of the XPertMailer package (http://xpertmailer.sourceforge.net/)     *
00007  *  Copyright (C) 2007 Tanase Laurentiu Iulian                                             *
00008  *                                                                                         *
00009  *  This library is free software; you can redistribute it and/or modify it under the      *
00010  *  terms of the GNU Lesser General Public License as published by the Free Software       *
00011  *  Foundation; either version 2.1 of the License, or (at your option) any later version.  *
00012  *                                                                                         *
00013  *  This library is distributed in the hope that it will be useful, but WITHOUT ANY        *
00014  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A        *
00015  *  PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.        *
00016  *                                                                                         *
00017  *  You should have received a copy of the GNU Lesser General Public License along with    *
00018  *  this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, *
00019  *  Fifth Floor, Boston, MA 02110-1301, USA                                                *
00020  *                                                                                         *
00021  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00022 
00023 if (!class_exists('FUNC5')) require_once 'FUNC5.php';
00024 
00025 class MIME5 {
00026 
00027         const LE = PHP_EOL;
00028         const HLEN = 52;
00029         const MLEN = 73;
00030 
00031         const HCHARSET = 'utf-8';
00032         const MCHARSET = 'us-ascii';
00033 
00034         const HENCDEF = 'quoted-printable';
00035         const MENCDEF = 'quoted-printable';
00036 
00037         static public $hencarr = array('quoted-printable' => '', 'base64' => '');
00038         static public $mencarr = array('7bit' => '', '8bit' => '', 'quoted-printable' => '', 'base64' => '', 'binary' => '');
00039 
00040         static public $qpkeys = array(
00041                         "\x00","\x01","\x02","\x03","\x04","\x05","\x06","\x07",
00042                         "\x08","\x09","\x0A","\x0B","\x0C","\x0D","\x0E","\x0F",
00043                         "\x10","\x11","\x12","\x13","\x14","\x15","\x16","\x17",
00044                         "\x18","\x19","\x1A","\x1B","\x1C","\x1D","\x1E","\x1F",
00045                         "\x7F","\x80","\x81","\x82","\x83","\x84","\x85","\x86",
00046                         "\x87","\x88","\x89","\x8A","\x8B","\x8C","\x8D","\x8E",
00047                         "\x8F","\x90","\x91","\x92","\x93","\x94","\x95","\x96",
00048                         "\x97","\x98","\x99","\x9A","\x9B","\x9C","\x9D","\x9E",
00049                         "\x9F","\xA0","\xA1","\xA2","\xA3","\xA4","\xA5","\xA6",
00050                         "\xA7","\xA8","\xA9","\xAA","\xAB","\xAC","\xAD","\xAE",
00051                         "\xAF","\xB0","\xB1","\xB2","\xB3","\xB4","\xB5","\xB6",
00052                         "\xB7","\xB8","\xB9","\xBA","\xBB","\xBC","\xBD","\xBE",
00053                         "\xBF","\xC0","\xC1","\xC2","\xC3","\xC4","\xC5","\xC6",
00054                         "\xC7","\xC8","\xC9","\xCA","\xCB","\xCC","\xCD","\xCE",
00055                         "\xCF","\xD0","\xD1","\xD2","\xD3","\xD4","\xD5","\xD6",
00056                         "\xD7","\xD8","\xD9","\xDA","\xDB","\xDC","\xDD","\xDE",
00057                         "\xDF","\xE0","\xE1","\xE2","\xE3","\xE4","\xE5","\xE6",
00058                         "\xE7","\xE8","\xE9","\xEA","\xEB","\xEC","\xED","\xEE",
00059                         "\xEF","\xF0","\xF1","\xF2","\xF3","\xF4","\xF5","\xF6",
00060                         "\xF7","\xF8","\xF9","\xFA","\xFB","\xFC","\xFD","\xFE",
00061                         "\xFF");
00062 
00063         static public $qpvrep = array(
00064                         "=00","=01","=02","=03","=04","=05","=06","=07",
00065                         "=08","=09","=0A","=0B","=0C","=0D","=0E","=0F",
00066                         "=10","=11","=12","=13","=14","=15","=16","=17",
00067                         "=18","=19","=1A","=1B","=1C","=1D","=1E","=1F",
00068                         "=7F","=80","=81","=82","=83","=84","=85","=86",
00069                         "=87","=88","=89","=8A","=8B","=8C","=8D","=8E",
00070                         "=8F","=90","=91","=92","=93","=94","=95","=96",
00071                         "=97","=98","=99","=9A","=9B","=9C","=9D","=9E",
00072                         "=9F","=A0","=A1","=A2","=A3","=A4","=A5","=A6",
00073                         "=A7","=A8","=A9","=AA","=AB","=AC","=AD","=AE",
00074                         "=AF","=B0","=B1","=B2","=B3","=B4","=B5","=B6",
00075                         "=B7","=B8","=B9","=BA","=BB","=BC","=BD","=BE",
00076                         "=BF","=C0","=C1","=C2","=C3","=C4","=C5","=C6",
00077                         "=C7","=C8","=C9","=CA","=CB","=CC","=CD","=CE",
00078                         "=CF","=D0","=D1","=D2","=D3","=D4","=D5","=D6",
00079                         "=D7","=D8","=D9","=DA","=DB","=DC","=DD","=DE",
00080                         "=DF","=E0","=E1","=E2","=E3","=E4","=E5","=E6",
00081                         "=E7","=E8","=E9","=EA","=EB","=EC","=ED","=EE",
00082                         "=EF","=F0","=F1","=F2","=F3","=F4","=F5","=F6",
00083                         "=F7","=F8","=F9","=FA","=FB","=FC","=FD","=FE",
00084                         "=FF");
00085 
00086         static public function unique($add = null) {
00087                 return md5(microtime(true).$add);
00088         }
00089 
00090         static public function is_printable($str = null, $debug = null) {
00091                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00092                 if (!is_string($str)) FUNC5::trace($debug, 'invalid argument type');
00093                 else {
00094                         $contain = implode('', self::$qpkeys);
00095                         return (strcspn($str, $contain) == strlen($str));
00096                 }
00097         }
00098 
00099         static public function qp_encode($str = null, $len = null, $end = null, $debug = null) {
00100                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00101                 $err = array();
00102                 if (!is_string($str)) $err[] = 'invalid argument type';
00103                 if ($len == null) $len = self::MLEN;
00104                 else if (!(is_int($len) && $len > 1)) $err[] = 'invalid line length value';
00105                 if ($end == null) $end = self::LE;
00106                 else if (!is_string($end)) $err[] = 'invalid line end value';
00107                 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err));
00108                 else {
00109                         if ($str == '') return $str;
00110                         else {
00111                                 $out = array();
00112                                 foreach (explode($end, $str) as $line) {
00113                                         if ($line == '') $out[] = '';
00114                                         else {
00115                                                 $line = str_replace('=', '=3D', $line);
00116                                                 $line = str_replace(self::$qpkeys, self::$qpvrep, $line);
00117                                                 preg_match_all('/.{1,'.$len.'}([^=]{0,2})?/', $line, $match);
00118                                                 $mcnt = count($match[0]);
00119                                                 for ($i = 0; $i < $mcnt; $i++) {
00120                                                         $line = (substr($match[0][$i], -1) == ' ') ? substr($match[0][$i], 0, -1).'=20' : $match[0][$i];
00121                                                         if (($i+1) < $mcnt) $line .= '=';
00122                                                         $out[] = $line;
00123                                                 }
00124                                         }
00125                                 }
00126                                 return implode($end, $out);
00127                         }
00128                 }
00129         }
00130 
00131         static public function encode_header($str = null, $charset = null, $encoding = null, $len = null, $end = null, $debug = null) {
00132                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00133                 $err = array();
00134                 if (!is_string($str)) $err[] = 'invalid argument type';
00135                 if ($charset == null) $charset = self::HCHARSET;
00136                 else if (!is_string($charset)) $err[] = 'invalid charset type';
00137                 else if (!(strlen($charset) >= 2 && FUNC5::is_alpha($charset, true, '-'))) $err[] = 'invalid charset value';
00138                 if ($encoding == null) $encoding = self::HENCDEF;
00139                 else if (!is_string($encoding)) $err[] = 'invalid encoding type';
00140                 else {
00141                         $encoding = strtolower(FUNC5::str_clear($encoding));
00142                         if (!isset(self::$hencarr[$encoding])) $err[] = 'invalid encoding value';
00143                 }
00144                 if ($len == null) $len = self::HLEN;
00145                 else if (!(is_int($len) && $len > 1)) $err[] = 'invalid line length value';
00146                 if ($end == null) $end = self::LE;
00147                 else if (!is_string($end)) $err[] = 'invalid line end value';
00148                 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err));
00149                 else {
00150                         if ($str == '') return $str;
00151                         else {
00152                                 $enc = false;
00153                                 $dif = $len - strlen('=?'.$charset.'?X??=');
00154                                 if ($encoding == 'quoted-printable') {
00155                                         if (!self::is_printable($str)) {
00156                                                 $new = (($dif-4) > 2) ? ($dif-4) : $len;
00157                                                 $enc = self::qp_encode($str, $new, $end);
00158                                                 $enc = str_replace(array('?', ' ', '='.$end), array('=3F', '_', $end), $enc);
00159                                         }
00160                                 } else if ($encoding == 'base64') {
00161                                         $new = ($dif > 3) ? $dif : $len;
00162                                         if ($new > 3) {
00163                                                 for ($i = $new; $i > 2; $i--) {
00164                                                         $crt = '';
00165                                                         for ($j = 0; $j <= $i; $j++) $crt .= 'x';
00166                                                         if (strlen(base64_encode($crt)) <= $new) {
00167                                                                 $new = $i;
00168                                                                 break;
00169                                                         }
00170                                                 }
00171                                         }
00172                                         $cnk = rtrim(chunk_split($str, $new, $end));
00173                                         $imp = array();
00174                                         foreach (explode($end, $cnk) as $line) if ($line != '') $imp[] = base64_encode($line);
00175                                         $enc = implode($end, $imp);
00176                                 }
00177                                 $res = array();
00178                                 if ($enc) {
00179                                         $chr = ($encoding == 'base64') ? 'B' : 'Q';
00180                                         foreach (explode($end, $enc) as $val) if ($val != '') $res[] = '=?'.$charset.'?'.$chr.'?'.$val.'?=';
00181                                 } else {
00182                                         $cnk = rtrim(chunk_split($str, $len, $end));
00183                                         foreach (explode($end, $cnk) as $val) if ($val != '') $res[] = $val;
00184                                 }
00185                                 return implode($end."\t", $res);
00186                         }
00187                 }
00188         }
00189 
00190         static public function decode_header($str = null, $debug = null) {
00191                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00192                 if (!is_string($str)) FUNC5::trace($debug, 'invalid argument type');
00193                 else {
00194                         $str = trim(FUNC5::str_clear($str));
00195                         $arr = array();
00196                         if ($str == '') $arr[] = array('charset' => self::HCHARSET, 'value' => '');
00197                         else {
00198                                 foreach (preg_split('/(?<!\\?(?i)q)\\?\\=/', $str, -1, PREG_SPLIT_NO_EMPTY) as $str1) {
00199                                         foreach (explode('=?', $str1, 2) as $str2) {
00200                                                 $def = false;
00201                                                 if (count($exp = explode('?B?', $str2)) == 2) {
00202                                                         if (strlen($exp[0]) >= 2 && FUNC5::is_alpha($exp[0], true, '-') && trim($exp[1]) != '') $def = array('charset' => $exp[0], 'value' => base64_decode(trim($exp[1])));
00203                                                 } else if (count($exp = explode('?b?', $str2)) == 2) {
00204                                                         if (strlen($exp[0]) >= 2 && FUNC5::is_alpha($exp[0], true, '-') && trim($exp[1]) != '') $def = array('charset' => $exp[0], 'value' => base64_decode(trim($exp[1])));
00205                                                 } else if (count($exp = explode('?Q?', $str2)) == 2) {
00206                                                         if (strlen($exp[0]) >= 2 && FUNC5::is_alpha($exp[0], true, '-') && $exp[1] != '') $def = array('charset' => $exp[0], 'value' => quoted_printable_decode(str_replace('_', ' ', $exp[1])));
00207                                                 } else if (count($exp = explode('?q?', $str2)) == 2) {
00208                                                         if (strlen($exp[0]) >= 2 && FUNC5::is_alpha($exp[0], true, '-') && $exp[1] != '') $def = array('charset' => $exp[0], 'value' => quoted_printable_decode(str_replace('_', ' ', $exp[1])));
00209                                                 }
00210                                                 if ($def) {
00211                                                         if ($def['value'] != '') $arr[] = array('charset' => $def['charset'], 'value' => $def['value']);
00212                                                 } else {
00213                                                         if ($str2 != '') $arr[] = array('charset' => self::HCHARSET, 'value' => $str2);
00214                                                 }
00215                                         }
00216                                 }
00217                         }
00218                         return $arr;
00219                 }
00220         }
00221 
00222         static public function decode_content($str = null, $encoding = null, $debug = null) {
00223                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00224                 $err = array();
00225                 if (!is_string($str)) $err[] = 'invalid content type';
00226                 if ($encoding == null) $encoding = '7bit';
00227                 else if (!is_string($encoding)) $err[] = 'invalid encoding type';
00228                 else {
00229                         $encoding = strtolower($encoding);
00230                         if (!isset(self::$mencarr[$encoding])) $err[] = 'invalid encoding value';
00231                 }
00232                 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err));
00233                 else {
00234                         if ($encoding == 'base64') {
00235                                 $str = trim(FUNC5::str_clear($str));
00236                                 return base64_decode($str);
00237                         } else if ($encoding == 'quoted-printable') {
00238                                 return quoted_printable_decode($str);
00239                         } else return $str;
00240                 }
00241         }
00242 
00243         static public function message($content = null, $type = null, $name = null, $charset = null, $encoding = null, $disposition = null, $id = null, $len = null, $end = null, $debug = null) {
00244                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00245                 $err = array();
00246                 if (!(is_string($content) && $content != '')) $err[] = 'invalid content type';
00247                 if ($type == null) $type = 'application/octet-stream';
00248                 else if (is_string($type)) {
00249                         $type = trim(FUNC5::str_clear($type));
00250                         if (strlen($type) < 4) $err[] = 'invalid type value';
00251                 } else $err[] = 'invalid type';
00252                 if (is_string($name)) {
00253                         $name = trim(FUNC5::str_clear($name));
00254                         if ($name == '') $err[] = 'invalid name value';
00255                 } else if ($name != null) $err[] = 'invalid name type';
00256                 if ($charset == null) $charset = self::MCHARSET;
00257                 else if (!is_string($charset)) $err[] = 'invalid charset type';
00258                 else if (!(strlen($charset) >= 2 && FUNC5::is_alpha($charset, true, '-'))) $err[] = 'invalid charset value';
00259                 if ($encoding == null) $encoding = self::MENCDEF;
00260                 else if (!is_string($encoding)) $err[] = 'invalid encoding type';
00261                 else {
00262                         $encoding = strtolower(FUNC5::str_clear($encoding));
00263                         if (!isset(self::$mencarr[$encoding])) $err[] = 'invalid encoding value';
00264                 }
00265                 if ($disposition == null) $disposition = 'inline';
00266                 else if (is_string($disposition)) {
00267                         $disposition = strtolower(FUNC5::str_clear($disposition));
00268                         if (!($disposition == 'inline' || $disposition == 'attachment')) $err[] = 'invalid disposition value';
00269                 } else $err[] = 'invalid disposition type';
00270                 if (is_string($id)) {
00271                         $id = FUNC5::str_clear($id, array(' '));
00272                         if ($id == '') $err[] = 'invalid id value';
00273                 } else if ($id != null) $err[] = 'invalid id type';
00274                 if ($len == null) $len = self::MLEN;
00275                 else if (!(is_int($len) && $len > 1)) $err[] = 'invalid line length value';
00276                 if ($end == null) $end = self::LE;
00277                 else if (!is_string($end)) $err[] = 'invalid line end value';
00278                 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err));
00279                 else {
00280                         $header = ''.
00281                                 'Content-Type: '.$type.';'.$end."\t".'charset="'.$charset.'"'.
00282                                 (($name == null) ? '' : ';'.$end."\t".'name="'.$name.'"').$end.
00283                                 'Content-Transfer-Encoding: '.$encoding.$end.
00284                                 'Content-Disposition: '.$disposition.
00285                                 (($name == null) ? '' : ';'.$end."\t".'filename="'.$name.'"').
00286                                 (($id == null) ? '' : $end.'Content-ID: <'.$id.'>');
00287                         if ($encoding == '7bit' || $encoding == '8bit') $content = wordwrap(self::fix_eol($content), $len, $end, true);
00288                         else if ($encoding == 'base64') $content = rtrim(chunk_split(base64_encode($content), $len, $end));
00289                         else if ($encoding == 'quoted-printable') $content = self::qp_encode(self::fix_eol($content), $len, $end);
00290                         return array('header' => $header, 'content' => $content);
00291                 }
00292         }
00293 
00294         static public function compose($text = null, $html = null, $attach = null, $uniq = null, $end = null, $debug = null) {
00295                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00296                 $err = array();
00297                 if ($text == null && $html == null) $err[] = 'message is not set';
00298                 else {
00299                         if ($text != null) {
00300                                 if (!(is_array($text) && isset($text['header'], $text['content']) && is_string($text['header']) && is_string($text['content']) && self::isset_header($text['header'], 'content-type', 'text/plain', $debug))) $err[] = 'invalid text message type';
00301                         }
00302                         if ($html != null) {
00303                                 if (!(is_array($html) && isset($html['header'], $html['content']) && is_string($html['header']) && is_string($html['content']) && self::isset_header($html['header'], 'content-type', 'text/html', $debug))) $err[] = 'invalid html message type';
00304                         }
00305                 }
00306                 if ($attach != null) {
00307                         if (is_array($attach) && count($attach) > 0) {
00308                                 foreach ($attach as $arr) {
00309                                         if (!(is_array($arr) && isset($arr['header'], $arr['content']) && is_string($arr['header']) && is_string($arr['content']) && (self::isset_header($arr['header'], 'content-disposition', 'inline', $debug) || self::isset_header($arr['header'], 'content-disposition', 'attachment', $debug)))) {
00310                                                 $err[] = 'invalid attachment type';
00311                                                 break;
00312                                         }
00313                                 }
00314                         } else $err[] = 'invalid attachment format';
00315                 }
00316                 if ($end == null) $end = self::LE;
00317                 else if (!is_string($end)) $err[] = 'invalid line end value';
00318                 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err));
00319                 else {
00320                         $multipart = false;
00321                         if ($text && $html) $multipart = true;
00322                         if ($attach) $multipart = true;
00323                         $header = $body = array();
00324                         $header[] = 'Date: '.date('r');
00325                         $header[] = base64_decode('WC1NYWlsZXI6IFhQTTQgdi4wLjUgPCB3d3cueHBlcnRtYWlsZXIuY29tID4=');
00326                         if ($multipart) {
00327                                 $uniq = ($uniq == null) ? 0 : intval($uniq);
00328                                 $boundary1 = '=_1.'.self::unique($uniq++);
00329                                 $boundary2 = '=_2.'.self::unique($uniq++);
00330                                 $boundary3 = '=_3.'.self::unique($uniq++);
00331                                 $disp['inline'] = $disp['attachment'] = false;
00332                                 if ($attach != null) {
00333                                         foreach ($attach as $darr) {
00334                                                 if (self::isset_header($darr['header'], 'content-disposition', 'inline', $debug)) $disp['inline'] = true;
00335                                                 else if (self::isset_header($darr['header'], 'content-disposition', 'attachment', $debug)) $disp['attachment'] = true;
00336                                         }
00337                                 }
00338                                 $hstr = 'Content-Type: multipart/%s;'.$end."\t".'boundary="%s"';
00339                                 $bstr = '--%s'.$end.'%s'.$end.$end.'%s';
00340                                 $body[] = 'This is a message in MIME Format. If you see this, your mail reader does not support this format.'.$end;
00341                                 if ($text && $html) {
00342                                                 if ($disp['inline'] && $disp['attachment']) {
00343                                                         $header[] = sprintf($hstr, 'mixed', $boundary1);
00344                                                         $body[] = '--'.$boundary1;
00345                                                         $body[] = sprintf($hstr, 'related', $boundary2).$end;
00346                                                         $body[] = '--'.$boundary2;
00347                                                         $body[] = sprintf($hstr, 'alternative', $boundary3).$end;
00348                                                         $body[] = sprintf($bstr, $boundary3, $text['header'], $text['content']);
00349                                                         $body[] = sprintf($bstr, $boundary3, $html['header'], $html['content']);
00350                                                         $body[] = '--'.$boundary3.'--';
00351                                                         foreach ($attach as $desc) if (self::isset_header($desc['header'], 'content-disposition', 'inline', $debug)) $body[] = sprintf($bstr, $boundary2, $desc['header'], $desc['content']);
00352                                                         $body[] = '--'.$boundary2.'--';
00353                                                         foreach ($attach as $desc) if (self::isset_header($desc['header'], 'content-disposition', 'attachment', $debug)) $body[] = sprintf($bstr, $boundary1, $desc['header'], $desc['content']);
00354                                                         $body[] = '--'.$boundary1.'--';
00355                                                 } else if ($disp['inline']) {
00356                                                         $header[] = sprintf($hstr, 'related', $boundary1);
00357                                                         $body[] = '--'.$boundary1;
00358                                                         $body[] = sprintf($hstr, 'alternative', $boundary2).$end;
00359                                                         $body[] = sprintf($bstr, $boundary2, $text['header'], $text['content']);
00360                                                         $body[] = sprintf($bstr, $boundary2, $html['header'], $html['content']);
00361                                                         $body[] = '--'.$boundary2.'--';
00362                                                         foreach ($attach as $desc) $body[] = sprintf($bstr, $boundary1, $desc['header'], $desc['content']);
00363                                                         $body[] = '--'.$boundary1.'--';
00364                                                 } else if ($disp['attachment']) {
00365                                                         $header[] = sprintf($hstr, 'mixed', $boundary1);
00366                                                         $body[] = '--'.$boundary1;
00367                                                         $body[] = sprintf($hstr, 'alternative', $boundary2).$end;
00368                                                         $body[] = sprintf($bstr, $boundary2, $text['header'], $text['content']);
00369                                                         $body[] = sprintf($bstr, $boundary2, $html['header'], $html['content']);
00370                                                         $body[] = '--'.$boundary2.'--';
00371                                                         foreach ($attach as $desc) $body[] = sprintf($bstr, $boundary1, $desc['header'], $desc['content']);
00372                                                         $body[] = '--'.$boundary1.'--';
00373                                                 } else {
00374                                                         $header[] = sprintf($hstr, 'alternative', $boundary1);
00375                                                         $body[] = sprintf($bstr, $boundary1, $text['header'], $text['content']);
00376                                                         $body[] = sprintf($bstr, $boundary1, $html['header'], $html['content']);
00377                                                         $body[] = '--'.$boundary1.'--';
00378                                                 }
00379                                 } else if ($text) {
00380                                         $header[] = sprintf($hstr, 'mixed', $boundary1);
00381                                         $body[] = sprintf($bstr, $boundary1, $text['header'], $text['content']);
00382                                         foreach ($attach as $desc) $body[] = sprintf($bstr, $boundary1, $desc['header'], $desc['content']);
00383                                         $body[] = '--'.$boundary1.'--';
00384                                 } else if ($html) {
00385                                         if ($disp['inline'] && $disp['attachment']) {
00386                                                 $header[] = sprintf($hstr, 'mixed', $boundary1);
00387                                                 $body[] = '--'.$boundary1;
00388                                                 $body[] = sprintf($hstr, 'related', $boundary2).$end;
00389                                                 $body[] = sprintf($bstr, $boundary2, $html['header'], $html['content']);
00390                                                 foreach ($attach as $desc) if (self::isset_header($desc['header'], 'content-disposition', 'inline', $debug)) $body[] = sprintf($bstr, $boundary2, $desc['header'], $desc['content']);
00391                                                 $body[] = '--'.$boundary2.'--';
00392                                                 foreach ($attach as $desc) if (self::isset_header($desc['header'], 'content-disposition', 'attachment', $debug)) $body[] = sprintf($bstr, $boundary1, $desc['header'], $desc['content']);
00393                                                 $body[] = '--'.$boundary1.'--';
00394                                         } else if ($disp['inline']) {
00395                                                 $header[] = sprintf($hstr, 'related', $boundary1);
00396                                                 $body[] = sprintf($bstr, $boundary1, $html['header'], $html['content']);
00397                                                 foreach ($attach as $desc) $body[] = sprintf($bstr, $boundary1, $desc['header'], $desc['content']);
00398                                                 $body[] = '--'.$boundary1.'--';
00399                                         } else if ($disp['attachment']) {
00400                                                 $header[] = sprintf($hstr, 'mixed', $boundary1);
00401                                                 $body[] = sprintf($bstr, $boundary1, $html['header'], $html['content']);
00402                                                 foreach ($attach as $desc) $body[] = sprintf($bstr, $boundary1, $desc['header'], $desc['content']);
00403                                                 $body[] = '--'.$boundary1.'--';
00404                                         }
00405                                 }
00406                         } else {
00407                                 if ($text) {
00408                                         $header[] = $text['header'];
00409                                         $body[] = $text['content'];
00410                                 } else if ($html) {
00411                                         $header[] = $html['header'];
00412                                         $body[] = $html['content'];
00413                                 }
00414                         }
00415                         $header[] = 'MIME-Version: 1.0';
00416                         return array('header' => implode($end, $header), 'content' => implode($end, $body));
00417                 }
00418         }
00419 
00420         static public function isset_header($str = null, $name = null, $value = null, $debug = null) {
00421                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00422                 $err = array();
00423                 if (!(is_string($str) && $str != '')) $err[] = 'invalid header type';
00424                 if (!(is_string($name) && strlen($name) > 1 && FUNC5::is_alpha($name, true, '-'))) $err[] = 'invalid name type';
00425                 if ($value != null && !is_string($value)) $err[] = 'invalid value type';
00426                 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err));
00427                 else {
00428                         $ret = false;
00429                         if ($exp = self::split_header($str, $debug)) {
00430                                 foreach ($exp as $harr) {
00431                                         if (strtolower($harr['name']) == strtolower($name)) {
00432                                                 if ($value != null) $ret = (strtolower($harr['value']) == strtolower($value)) ? $harr['value'] : false;
00433                                                 else $ret = $harr['value'];
00434                                                 if ($ret) break;
00435                                         }
00436                                 }
00437                         }
00438                         return $ret;
00439                 }
00440         }
00441 
00442         static public function split_header($str = null, $debug = null) {
00443                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00444                 if (!(is_string($str) && $str != '')) FUNC5::trace($debug, 'invalid header value');
00445                 else {
00446                         $str = str_replace(array(";\r\n\t", "; \r\n\t", ";\r\n ", "; \r\n "), '; ', $str);
00447                         $str = str_replace(array(";\n\t", "; \n\t", ";\n ", "; \n "), '; ', $str);
00448                         $str = str_replace(array("\r\n\t", "\r\n "), '', $str);
00449                         $str = str_replace(array("\n\t", "\n "), '', $str);
00450                         $arr = array();
00451                         foreach (explode("\n", $str) as $line) {
00452                                 $line = trim(FUNC5::str_clear($line));
00453                                 if ($line != '') {
00454                                         if (count($exp1 = explode(':', $line, 2)) == 2) {
00455                                                 $name = rtrim($exp1[0]);
00456                                                 $val1 = ltrim($exp1[1]);
00457                                                 if (strlen($name) > 1 && FUNC5::is_alpha($name, true, '-') && $val1 != '') {
00458                                                         $name = ucfirst($name);
00459                                                         $hadd = array();
00460                                                         if (substr(strtolower($name), 0, 8) == 'content-') {
00461                                                                 $exp2 = explode('; ', $val1);
00462                                                                 $cnt2 = count($exp2);
00463                                                                 if ($cnt2 > 1) {
00464                                                                         for ($i = 1; $i < $cnt2; $i++) {
00465                                                                                 if (count($exp3 = explode('=', $exp2[$i], 2)) == 2) {
00466                                                                                         $hset = trim($exp3[0]);
00467                                                                                         $hval = trim($exp3[1], ' "');
00468                                                                                         if ($hset != '' && $hval != '') $hadd[strtolower($hset)] = $hval;
00469                                                                                 }
00470                                                                         }
00471                                                                 }
00472                                                         }
00473                                                         $val2 = (count($hadd) > 0) ? trim($exp2[0]) : $val1;
00474                                                         $arr[] = array('name' => $name, 'value' => $val2, 'content' => $hadd);
00475                                                 }
00476                                         }
00477                                 }
00478                         }
00479                         if (count($arr) > 0) return $arr;
00480                         else FUNC5::trace($debug, 'invalid header value', 1);
00481                 }
00482         }
00483 
00484         static public function split_message($str = null, $debug = null) {
00485                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00486                 if (!(is_string($str) && $str != '')) FUNC5::trace($debug, 'invalid message value');
00487                 else {
00488                         $ret = false;
00489                         if (strpos($str, "\r\n\r\n")) $ret = explode("\r\n\r\n", $str, 2);
00490                         else if (strpos($str, "\n\n")) $ret = explode("\n\n", $str, 2);
00491                         if ($ret) return array('header' => trim($ret[0]), 'content' => $ret[1]);
00492                         else return false;
00493                 }
00494         }
00495 
00496         static public function split_mail($str = null, &$headers, &$body, $debug = null) {
00497                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00498                 $headers = $body = false;
00499                 if (!$part = self::split_message($str, $debug)) return false;
00500                 if (!$harr = self::split_header($part['header'], $debug)) return false;
00501                 $type = $boundary = false;
00502                 foreach ($harr as $hnum) {
00503                         if (strtolower($hnum['name']) == 'content-type') {
00504                                 $type = strtolower($hnum['value']);
00505                                 foreach ($hnum['content'] as $hnam => $hval) {
00506                                         if (strtolower($hnam) == 'boundary') {
00507                                                 $boundary = $hval;
00508                                                 break;
00509                                         }
00510                                 }
00511                                 if ($boundary) break;
00512                         }
00513                 }
00514                 $headers = $harr;
00515                 $body = array();
00516                 if (substr($type, 0, strlen('multipart/')) == 'multipart/' && $boundary && strstr($part['content'], '--'.$boundary.'--')) $body = self::_parts($part['content'], $boundary, strtolower(substr($type, strlen('multipart/'))), $debug);
00517                 if (count($body) == 0) $body[] = self::_content($str, $debug);
00518         }
00519 
00520         static private function _parts($str = null, $boundary = null, $multipart = null, $debug = null) {
00521                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00522                 $err = array();
00523                 if (!(is_string($str) && $str != '')) $err[] = 'invalid content value';
00524                 if (!(is_string($boundary) && $boundary != '')) $err[] = 'invalid boundary value';
00525                 if (!(is_string($multipart) && $multipart != '')) $err[] = 'invalid multipart value';
00526                 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err));
00527                 else {
00528                         $ret = array();
00529                         if (count($exp = explode('--'.$boundary.'--', $str)) == 2) {
00530                                 if (count($exp = explode('--'.$boundary, $exp[0])) > 2) {
00531                                         $cnt = 0;
00532                                         foreach ($exp as $split) {
00533                                                 $cnt++;
00534                                                 if ($cnt > 1 && $part = self::split_message($split, $debug)) {
00535                                                         if ($harr = self::split_header($part['header'], $debug)) {
00536                                                                 $type = $newb = false;
00537                                                                 foreach ($harr as $hnum) {
00538                                                                         if (strtolower($hnum['name']) == 'content-type') {
00539                                                                                 $type = strtolower($hnum['value']);
00540                                                                                 foreach ($hnum['content'] as $hnam => $hval) {
00541                                                                                         if (strtolower($hnam) == 'boundary') {
00542                                                                                                 $newb = $hval;
00543                                                                                                 break;
00544                                                                                         }
00545                                                                                 }
00546                                                                                 if ($newb) break;
00547                                                                         }
00548                                                                 }
00549                                                                 if (substr($type, 0, strlen('multipart/')) == 'multipart/' && $newb && strstr($part['content'], '--'.$newb.'--')) $ret = self::_parts($part['content'], $newb, $multipart.'|'.strtolower(substr($type, strlen('multipart/'))), $debug);
00550                                                                 else {
00551                                                                         $res = self::_content($split, $debug);
00552                                                                         $res['multipart'] = $multipart;
00553                                                                         $ret[] = $res;
00554                                                                 }
00555                                                         }
00556                                                 }
00557                                         }
00558                                 }
00559                         }
00560                         return $ret;
00561                 }
00562         }
00563 
00564         static private function _content($str = null, $debug = null) {
00565                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00566                 if (!(is_string($str) && $str != '')) FUNC5::trace($debug, 'invalid content value');
00567                 else {
00568                         if (!$part = self::split_message($str, $debug)) return null;
00569                         if (!$harr = self::split_header($part['header'], $debug)) return null;
00570                         $body = array();
00571                         $clen = strlen('content-');
00572                         $encoding = false;
00573                         foreach ($harr as $hnum) {
00574                                 if (substr(strtolower($hnum['name']), 0, $clen) == 'content-') {
00575                                         $name = strtolower(substr($hnum['name'], $clen));
00576                                         if ($name == 'transfer-encoding') $encoding = strtolower($hnum['value']);
00577                                         else if ($name == 'id') $body[$name] = array('value' => trim($hnum['value'], '<>'), 'extra' => $hnum['content']);
00578                                         else $body[$name] = array('value' => $hnum['value'], 'extra' => $hnum['content']);
00579                                 }
00580                         }
00581                         if ($encoding == 'base64' || $encoding == 'quoted-printable') $body['content'] = self::decode_content($part['content'], $encoding, $debug);
00582                         else {
00583                                 if ($encoding) $body['transfer-encoding'] = $encoding;
00584                                 $body['content'] = $part['content'];
00585                         }
00586                         if (substr($body['content'], -2) == "\r\n") $body['content'] = substr($body['content'], 0, -2);
00587                         else if (substr($body['content'], -1) == "\n") $body['content'] = substr($body['content'], 0, -1);
00588                         return $body;
00589                 }
00590         }
00591 
00592         static public function fix_eol($str = null, $debug = null) {
00593                 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace();
00594                 if (!(is_string($str) && $str != '')) FUNC5::trace($debug, 'invalid content value');
00595                 else {
00596                         $str = str_replace("\r\n", "\n", $str);
00597                         $str = str_replace("\r", "\n", $str);
00598                         if (self::LE != "\n") $str = str_replace("\n", self::LE, $str);
00599                         return $str;
00600                 }
00601         }
00602 
00603 }
00604 
00605 ?>
 All Data Structures Files Functions Variables Enumerations