3 * FusionForge mail parser
5 * Copyright 2004, GForge, LLC
7 * This file is part of FusionForge.
9 * FusionForge is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License,
12 * or (at your option) any later version.
14 * FusionForge is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with FusionForge; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 require_once $gfcommon.'include/Error.class.php';
27 class MailParser extends Error {
29 var $max_file_size=2000000;
33 function MailParser($input_file) {
35 $size = filesize($input_file);
36 if ($size > $this->max_file_size) {
37 $this->setError("Error - file too large");
40 $fo = fopen($input_file, 'r');
41 $input_data = fread($fo, $size);
44 $lines=explode("\n",$input_data);
45 $linecount=count($lines);
48 //system("echo \"mp: headers".implode("***\n",$lines)."\n\" >> /tmp/forum.log");
50 // Read the message line-by-line
52 for ($i=0; $i<($linecount-1); $i++) {
53 //system("echo \"mp: line $i of $linecount length: ".strlen($lines[$i])." ".$lines[$i]."\n\" >> /tmp/forum.log");
55 // Still reading headers
59 // If we hit a blank line, end of headers
61 if (strlen($lines[$i]) < 2) {
65 // See if line starts with tab, if so ignore it for now
67 if (!ereg('^[A-z]',$lines[$i])) {
68 $header[$lastheader] = $header[$lastheader]."\n".$lines[$i];
70 $pos = (strpos($lines[$i],':'));
71 $header[substr($lines[$i],0,$pos)] = trim(substr($lines[$i],$pos+2,(strlen($lines[$i])-$pos-2)));
72 $lastheader=substr($lines[$i],0,$pos);
76 $body .= $lines[$i]."\r\n";
82 $this->headers =& $header;
84 if ($header['Content-Type']) {
85 $hdr = strtolower($header['Content-Type']);
86 if (strpos($hdr,'text/plain') !== false) {
89 $this->setError('Error - only text/plain supported at this time');
93 //echo "\n\n**".$header['Content-Type']."**\n\n";
98 //system("echo \"mp: headers".implode("***\n",$header)."\n\" >> /tmp/forum.log");
99 //system("echo \"mp: body".$body."\n\" >> /tmp/forum.log");
103 function &getBody() {
107 function &getHeader($header) {
108 return $this->headers[$header];
111 function getSubject() {
112 return $this->getHeader('Subject');
115 //tperdue@collab.adpcorp.com (Tim Perdue)
116 function getFromEmail() {
117 $mail = $this->getHeader('From');
118 if (strpos($mail,'(') !== false) {
119 $email = substr($mail,0,strpos($mail,' '));
120 } elseif (strpos($mail,'<') !== false) {
121 $begin=(strpos($mail,'<')+1);
122 $end = strpos($mail,'>');
123 $email = substr($mail,$begin,($end-$begin));
127 $email = str_replace('"','',$email);
129 //echo "***$mail*$begin*$end**".$email."*****";
130 //system("echo \"mp: email".$email."\n\" >> /tmp/forum.log");
134 /*------------------------------------------------------------------------
135 * MIME decoding functions
136 *-----------------------------------------------------------------------*/
138 * Subject and From decode implementation of RFC 2047
140 * @param String one or more encoded strings
141 * @return String strcat of all texts. Ignore all charsets
143 function mime_header_decode_string($string) {
145 $decoded_arr = $this->mime_header_decode($string);
147 $return_string = $decoded_arr[0]['text'];
150 for ($i=1; $i<count($decoded_arr); $i++) {
151 $return_string.=$decoded_arr[$i]['text'];
154 DBG("mime_header: $string -> $return_string \n");
156 return $return_string;
160 * Mime header decoding
162 * @param String to decode
163 * @return Decoded String Array. return['charset'] and retutn['text']
165 *# FIXME: Should we use imap_mime_headres_decode? It's too havey to install
166 * See http://us2.php.net/manual/en/function.imap-mime-header-decode.php
169 function mime_header_decode($string) {
170 /* We expecting series of encoded-word:
171 * encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
172 * See more detail in RFC 2407
175 $strlen = strlen($string);
177 for ($i=0; $i < $strlen; $i++) {
178 /* Start seperation */
179 if (!strcmp($string{$i} . $string{$i+1}, "=?")) {
184 if( !strcmp($string{$i} . $string{$i+1}, "?=")) {
185 $encoded_word_arr[$count].=$string{$i};
186 $encoded_word_arr[$count].=$string{++$i};
187 $count++; /* Null array should be OK */
191 $encoded_word_arr[$count].=$string{$i};
194 for ($i=0; $i<count($encoded_word_arr); $i++) {
195 $return_arr[$i] = $this->mime_header_one_word_decode($encoded_word_arr[$i]);
202 * one word decode implementation of RFC 2047
204 function mime_header_one_word_decode($string) {
205 /* Default charset */
208 /* We ecpecting : encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
209 * See more detail in RFC 2407
212 /* No encoded-word, return default */
213 if (strncmp($string, "=?", 2)) {
214 return array("charset"=>$charset, "text" => $string);
218 * Expecting [0]='=', [1]=charset, [2]=B|Q, [3]=encoded-text
220 $string_arr = explode('?', $string);
222 if (!strcasecmp($string_arr[2], "B") && $string_arr[3]) {
223 $string = base64_decode($string_arr[3]);
224 $charset = $string_arr[1];
225 } else if (!strcasecmp($string_arr[2], "Q") && $string_arr[3]) {
226 $string = quoted_printable_decode($string_arr[3]);
227 $charset = $string_arr[1];
230 /* Return what we have */
231 $ret_arr = array("charset"=>$charset, "text" => $string);
239 // c-file-style: "bsd"