thomascube
2006-12-11 c45eb594cdbef4e74313054e462d2bb7e250e724
commit | author | age
4e17e6 1 <?php
T 2 /////////////////////////////////////////////////////////
3 //    
4 //    Iloha MIME Library (IML)
5 //
6 //    (C)Copyright 2002 Ryo Chijiiwa <Ryo@IlohaMail.org>
7 //
8 //    This file is part of IlohaMail. IlohaMail is free software released 
9 //    under the GPL license.  See enclosed file COPYING for details, or 
10 //    see http://www.fsf.org/copyleft/gpl.html
11 //
12 /////////////////////////////////////////////////////////
13
14 /********************************************************
15
16     FILE: include/mime.inc
17     PURPOSE:
18         Provide functions for handling mime messages.
19     USAGE:
20         Use iil_C_FetchStructureString to get IMAP structure stirng, then pass that through
21         iml_GetRawStructureArray() to get root node to a nested data structure.
22         Pass root node to the iml_GetPart*() functions to retreive individual bits of info.
23
24 ********************************************************/
25 $MIME_INVALID = -1;
26 $MIME_TEXT = 0;
27 $MIME_MULTIPART = 1;
28 $MIME_MESSAGE = 2;
29 $MIME_APPLICATION = 3;
30 $MIME_AUDIO = 4;
31 $MIME_IMAGE = 5;
32 $MIME_VIDEO = 6;
33 $MIME_OTHER = 7;
34
35 function iml_ClosingParenPos($str, $start){
36     $level=0;
37     $len = strlen($str);
38     $in_quote = 0;
39     for ($i=$start;$i<$len;$i++){
40         if ($str[$i]=="\"") $in_quote = ($in_quote + 1) % 2;
41         if (!$in_quote){
42             if ($str[$i]=="(") $level++;
43             else if (($level > 0) && ($str[$i]==")")) $level--;
44             else if (($level == 0) && ($str[$i]==")")) return $i;
45         }
46     }
47 }
48
49 function iml_ParseBSString($str){    
50     
51     $id = 0;
52     $a = array();
53     $len = strlen($str);
54     
55     $in_quote = 0;
56     for ($i=0; $i<$len; $i++){
57         if ($str[$i] == "\"") $in_quote = ($in_quote + 1) % 2;
58         else if (!$in_quote){
59             if ($str[$i] == " ") $id++; //space means new element
60             else if ($str[$i]=="("){ //new part
61                 $i++;
62                 $endPos = iml_ClosingParenPos($str, $i);
63                 $partLen = $endPos - $i;
64                 $part = substr($str, $i, $partLen);
65                 $a[$id] = iml_ParseBSString($part); //send part string
66                 if ($verbose){
67                     echo "{>".$endPos."}";
68                     flush();
69                 }
70                 $i = $endPos;
71             }else $a[$id].=$str[$i]; //add to current element in array
72         }else if ($in_quote){
73             if ($str[$i]=="\\") $i++; //escape backslashes
74             else $a[$id].=$str[$i]; //add to current element in array
75         }
76     }
77         
78     reset($a);
79     return $a;
80 }
81
82 function iml_GetRawStructureArray($str){
83     $line=substr($str, 1, strlen($str) - 2);
84     $line = str_replace(")(", ") (", $line);
85     
86     $struct = iml_ParseBSString($line);
87     if ((strcasecmp($struct[0], "message")==0) && (strcasecmp($struct[1], "rfc822")==0)){
88         $struct = array($struct);
89     }
90     return $struct;
91 }
92
93 function iml_GetPartArray($a, $part){
94     if (!is_array($a)) return false;
95     if (strpos($part, ".") > 0){
96         $original_part = $part;
97         $pos = strpos($part, ".");
98         $rest = substr($original_part, $pos+1);
99         $part = substr($original_part, 0, $pos);
100         if ((strcasecmp($a[0], "message")==0) && (strcasecmp($a[1], "rfc822")==0)){
101             $a = $a[8];
102         }
103         //echo "m - part: $original_part current: $part rest: $rest array: ".implode(" ", $a)."<br>\n";
104         return iml_GetPartArray($a[$part-1], $rest);
105     }else if ($part>0){
106         if ((strcasecmp($a[0], "message")==0) && (strcasecmp($a[1], "rfc822")==0)){
107             $a = $a[8];
108         }
109         //echo "s - part: $part rest: $rest array: ".implode(" ", $a)."<br>\n";
110         if (is_array($a[$part-1])) return $a[$part-1];
111         else return false;
112     }else if (($part==0) || (empty($part))){
113         return $a;
114     }
115 }
116
117 function iml_GetNumParts($a, $part){
118     if (is_array($a)){
119         $parent=iml_GetPartArray($a, $part);
120         
121         if ((strcasecmp($parent[0], "message")==0) && (strcasecmp($parent[1], "rfc822")==0)){
122             $parent = $parent[8];
123         }
124
125         $is_array=true;
126         $c=0;
127         while (( list ($key, $val) = each ($parent) )&&($is_array)){
128             $is_array=is_array($parent[$key]);
129             if ($is_array) $c++;
130         }
131         return $c;
132     }
133     
134     return false;
135 }
136
137 function iml_GetPartTypeString($a, $part){
138     $part_a=iml_GetPartArray($a, $part);
139     if ($part_a){
140         if (is_array($part_a[0])){
141             $type_str = "MULTIPART/";
142             reset($part_a);
143             while(list($n,$element)=each($part_a)){
144                 if (!is_array($part_a[$n])){
145                     $type_str.=$part_a[$n];
146                     break;
147                 }
148             }
149             return $type_str;
150         }else return $part_a[0]."/".$part_a[1];
151     }else return false;
152 }
153
154 function iml_GetFirstTextPart($structure,$part){
155     if ($part==0) $part="";
156     $typeCode = -1;
157     while ($typeCode!=0){
158         $typeCode = iml_GetPartTypeCode($structure, $part);
159         if ($typeCode == 1){
160             $part .= (empty($part)?"":".")."1";
161         }else if ($typeCode > 0){
162             $parts_a = explode(".", $part);
163             $lastPart = count($parts_a) - 1;
164             $parts_a[$lastPart] = (int)$parts_a[$lastPart] + 1;
165             $part = implode(".", $parts_a);
166         }else if ($typeCode == -1){
167             return "";
168         }
169     }
170     
171     return $part;
172 }
173
174 function iml_GetPartTypeCode($a, $part){
175     $types=array(0=>"text",1=>"multipart",2=>"message",3=>"application",4=>"audio",5=>"image",6=>"video",7=>"other");
176
177     $part_a=iml_GetPartArray($a, $part);
178     if ($part_a){
179         if (is_array($part_a[0])) $str="multipart";
180         else $str=$part_a[0];
181
182         $code=7;
183         while ( list($key, $val) = each($types)) if (strcasecmp($val, $str)==0) $code=$key;
184         return $code;
185     }else return -1;
186 }
187
188 function iml_GetPartEncodingCode($a, $part){
189     $encodings=array("7BIT", "8BIT", "BINARY", "BASE64", "QUOTED-PRINTABLE", "OTHER");
190
191     $part_a=iml_GetPartArray($a, $part);
192     if ($part_a){
193         if (is_array($part_a[0])) return -1;
194         else $str=$part_a[5];
195
196         $code=5;
197         while ( list($key, $val) = each($encodings)) if (strcasecmp($val, $str)==0) $code=$key;
198
199         return $code;
200
201     }else return -1;
202 }
203
204 function iml_GetPartEncodingString($a, $part){
205     $part_a=iml_GetPartArray($a, $part);
206     if ($part_a){
207         if (is_array($part_a[0])) return -1;
208         else return $part_a[5];
209     }else return -1;
210 }
211
212 function iml_GetPartSize($a, $part){
213     $part_a=iml_GetPartArray($a, $part);
214     if ($part_a){
215         if (is_array($part_a[0])) return -1;
216         else return $part_a[6];
217     }else return -1;
218 }
219
220 function iml_GetPartID($a, $part){
221     $part_a=iml_GetPartArray($a, $part);
222     if ($part_a){
223         if (is_array($part_a[0])) return -1;
224         else return $part_a[3];
225     }else return -1;
226 }
227
228 function iml_GetPartDisposition($a, $part){
229     $part_a=iml_GetPartArray($a, $part);
230     if ($part_a){
231         if (is_array($part_a[0])) return -1;
232         else{
233             $id = count($part_a) - 2;
234             if (is_array($part_a[$id])) return $part_a[$id][0];
235             else return "";
236         }
237     }else return "";
238 }
239
240 function iml_GetPartName($a, $part){
241     $part_a=iml_GetPartArray($a, $part);
242     if ($part_a){
243         if (is_array($part_a[0])) return -1;
244         else{
245             $name = "";
246             if (is_array($part_a[2])){
247                 //first look in content type
248                 $name="";
249                 while ( list($key, $val) = each ($part_a[2])){
250                     if ((strcasecmp($val, "NAME")==0)||(strcasecmp($val, "FILENAME")==0)) 
251                         $name=$part_a[2][$key+1];
252                 }
253             }
254             if (empty($name)){
255                 //check in content disposition
256                 $id = count($part_a) - 2;
257                 if ((is_array($part_a[$id])) && (is_array($part_a[$id][1]))){
258                     $array = $part_a[$id][1];
259                     while ( list($key, $val) = each($array)){
260                         if ((strcasecmp($val, "NAME")==0)||(strcasecmp($val, "FILENAME")==0)) 
261                             $name=$array[$key+1];
262                     }
263                 }
264             }
265             return $name;
266         }
267     }else return "";
268 }
269
270
271 function iml_GetPartCharset($a, $part){
272     $part_a=iml_GetPartArray($a, $part);
273     if ($part_a){
274         if (is_array($part_a[0])) return -1;
275         else{
276             if (is_array($part_a[2])){
277                 $name="";
278                 while ( list($key, $val) = each ($part_a[2])) if (strcasecmp($val, "charset")==0) $name=$part_a[2][$key+1];
279                 return $name;
280             }
281             else return "";
282         }
283     }else return "";
284 }
285
286 function iml_GetPartList($a, $part){
287     //echo "MOO?"; flush();
288     $data = array();
289     $num_parts = iml_GetNumParts($a, $part);
290     //echo "($num_parts)"; flush();
291     if ($num_parts !== false){
292         //echo "<!-- ($num_parts parts)//-->\n";
293         for ($i = 0; $i<$num_parts; $i++){
294             $part_code = $part.(empty($part)?"":".").($i+1);
295             $part_type = iml_GetPartTypeCode($a, $part_code);
296             $part_disposition = iml_GetPartDisposition($a, $part_code);
297             //echo "<!-- part: $part_code type: $part_type //-->\n";
298             if (strcasecmp($part_disposition, "attachment")!=0 && 
299                 (($part_type == 1) || ($part_type==2))){
300                 $data = array_merge($data, iml_GetPartList($a, $part_code));
301             }else{
302                 $data[$part_code]["typestring"] = iml_GetPartTypeString($a, $part_code);
303                 $data[$part_code]["disposition"] = $part_disposition;
304                 $data[$part_code]["size"] = iml_GetPartSize($a, $part_code);
305                 $data[$part_code]["name"] = iml_GetPartName($a, $part_code);
306                 $data[$part_code]["id"] = iml_GetPartID($a, $part_code);
307             }
308         }
309     }
310     return $data;
311 }
312
313 function iml_GetNextPart($part){
314     if (strpos($part, ".")===false) return $part++;
315     else{
316         $parts_a = explode(".", $part);
317         $num_levels = count($parts_a);
318         $parts_a[$num_levels-1]++;
319         return implode(".", $parts_a);
320     }
321 }
322 ?>