alecpl
2008-10-02 52851464e0267795ffd688e3c769d9161011dba8
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
510ca2 35 function iml_ClosingParenPos($str, $start) {
4e17e6 36     $level=0;
T 37     $len = strlen($str);
38     $in_quote = 0;
510ca2 39
A 40     for ($i=$start; $i<$len; $i++) {
41         if ($str[$i] == '"' && $str[$i-1] != "\\")
42         $in_quote = ($in_quote + 1) % 2;
43         if (!$in_quote) {
4e17e6 44             if ($str[$i]=="(") $level++;
T 45             else if (($level > 0) && ($str[$i]==")")) $level--;
46             else if (($level == 0) && ($str[$i]==")")) return $i;
47         }
48     }
49 }
50
51 function iml_ParseBSString($str){    
52     
53     $id = 0;
54     $a = array();
55     $len = strlen($str);
56     $in_quote = 0;
510ca2 57
A 58     for ($i=0; $i<$len; $i++) {
59         if ($str[$i] == '"') {
60         $in_quote = ($in_quote + 1) % 2;
61         } else if (!$in_quote) {
62             if ($str[$i] == " ") { //space means new element
63749a 63                 $id++;
T 64                 while ($str[$i+1] == " ") $i++;  // skip additional spaces
510ca2 65             } else if ($str[$i]=="(") { //new part
4e17e6 66                 $i++;
T 67                 $endPos = iml_ClosingParenPos($str, $i);
68                 $partLen = $endPos - $i;
1b5deb 69                 if ($partLen < 0) break;
4e17e6 70                 $part = substr($str, $i, $partLen);
T 71                 $a[$id] = iml_ParseBSString($part); //send part string
72                 $i = $endPos;
510ca2 73             } else
A 74         $a[$id].=$str[$i]; //add to current element in array
75         } else if ($in_quote) {
76             if ($str[$i]=="\\") {
77         $i++; //escape backslashes
78         if ($str[$i] == '"' || $str[$i] == "\\")
79             $a[$id] .= $str[$i];
80             } else
81         $a[$id] .= $str[$i]; //add to current element in array
4e17e6 82         }
T 83     }
84         
85     reset($a);
86     return $a;
87 }
88
89 function iml_GetRawStructureArray($str){
90     $line=substr($str, 1, strlen($str) - 2);
91     $line = str_replace(")(", ") (", $line);
510ca2 92
4e17e6 93     $struct = iml_ParseBSString($line);
T 94     if ((strcasecmp($struct[0], "message")==0) && (strcasecmp($struct[1], "rfc822")==0)){
95         $struct = array($struct);
96     }
97     return $struct;
98 }
99
100 function iml_GetPartArray($a, $part){
101     if (!is_array($a)) return false;
102     if (strpos($part, ".") > 0){
103         $original_part = $part;
104         $pos = strpos($part, ".");
105         $rest = substr($original_part, $pos+1);
106         $part = substr($original_part, 0, $pos);
107         if ((strcasecmp($a[0], "message")==0) && (strcasecmp($a[1], "rfc822")==0)){
108             $a = $a[8];
109         }
110         //echo "m - part: $original_part current: $part rest: $rest array: ".implode(" ", $a)."<br>\n";
111         return iml_GetPartArray($a[$part-1], $rest);
112     }else if ($part>0){
113         if ((strcasecmp($a[0], "message")==0) && (strcasecmp($a[1], "rfc822")==0)){
114             $a = $a[8];
115         }
116         //echo "s - part: $part rest: $rest array: ".implode(" ", $a)."<br>\n";
117         if (is_array($a[$part-1])) return $a[$part-1];
04d630 118         else return $a;
4e17e6 119     }else if (($part==0) || (empty($part))){
T 120         return $a;
121     }
122 }
123
124 function iml_GetNumParts($a, $part){
125     if (is_array($a)){
126         $parent=iml_GetPartArray($a, $part);
127         
128         if ((strcasecmp($parent[0], "message")==0) && (strcasecmp($parent[1], "rfc822")==0)){
129             $parent = $parent[8];
130         }
131
132         $is_array=true;
133         $c=0;
134         while (( list ($key, $val) = each ($parent) )&&($is_array)){
135             $is_array=is_array($parent[$key]);
136             if ($is_array) $c++;
137         }
138         return $c;
139     }
140     
141     return false;
142 }
143
144 function iml_GetPartTypeString($a, $part){
145     $part_a=iml_GetPartArray($a, $part);
146     if ($part_a){
147         if (is_array($part_a[0])){
148             $type_str = "MULTIPART/";
149             reset($part_a);
150             while(list($n,$element)=each($part_a)){
151                 if (!is_array($part_a[$n])){
152                     $type_str.=$part_a[$n];
153                     break;
154                 }
155             }
156             return $type_str;
157         }else return $part_a[0]."/".$part_a[1];
158     }else return false;
159 }
160
161 function iml_GetFirstTextPart($structure,$part){
162     if ($part==0) $part="";
163     $typeCode = -1;
164     while ($typeCode!=0){
165         $typeCode = iml_GetPartTypeCode($structure, $part);
166         if ($typeCode == 1){
167             $part .= (empty($part)?"":".")."1";
168         }else if ($typeCode > 0){
169             $parts_a = explode(".", $part);
170             $lastPart = count($parts_a) - 1;
171             $parts_a[$lastPart] = (int)$parts_a[$lastPart] + 1;
172             $part = implode(".", $parts_a);
173         }else if ($typeCode == -1){
174             return "";
175         }
176     }
177     
178     return $part;
179 }
180
181 function iml_GetPartTypeCode($a, $part){
182     $types=array(0=>"text",1=>"multipart",2=>"message",3=>"application",4=>"audio",5=>"image",6=>"video",7=>"other");
183
184     $part_a=iml_GetPartArray($a, $part);
185     if ($part_a){
186         if (is_array($part_a[0])) $str="multipart";
187         else $str=$part_a[0];
188
189         $code=7;
190         while ( list($key, $val) = each($types)) if (strcasecmp($val, $str)==0) $code=$key;
191         return $code;
192     }else return -1;
193 }
194
195 function iml_GetPartEncodingCode($a, $part){
196     $encodings=array("7BIT", "8BIT", "BINARY", "BASE64", "QUOTED-PRINTABLE", "OTHER");
197
198     $part_a=iml_GetPartArray($a, $part);
199     if ($part_a){
200         if (is_array($part_a[0])) return -1;
201         else $str=$part_a[5];
202
203         $code=5;
204         while ( list($key, $val) = each($encodings)) if (strcasecmp($val, $str)==0) $code=$key;
205
206         return $code;
207
208     }else return -1;
209 }
210
211 function iml_GetPartEncodingString($a, $part){
212     $part_a=iml_GetPartArray($a, $part);
213     if ($part_a){
214         if (is_array($part_a[0])) return -1;
215         else return $part_a[5];
216     }else return -1;
217 }
218
219 function iml_GetPartSize($a, $part){
220     $part_a=iml_GetPartArray($a, $part);
221     if ($part_a){
222         if (is_array($part_a[0])) return -1;
223         else return $part_a[6];
224     }else return -1;
225 }
226
227 function iml_GetPartID($a, $part){
228     $part_a=iml_GetPartArray($a, $part);
229     if ($part_a){
230         if (is_array($part_a[0])) return -1;
231         else return $part_a[3];
232     }else return -1;
233 }
234
235 function iml_GetPartDisposition($a, $part){
236     $part_a=iml_GetPartArray($a, $part);
237     if ($part_a){
238         if (is_array($part_a[0])) return -1;
239         else{
240             $id = count($part_a) - 2;
241             if (is_array($part_a[$id])) return $part_a[$id][0];
242             else return "";
243         }
244     }else return "";
245 }
246
247 function iml_GetPartName($a, $part){
248     $part_a=iml_GetPartArray($a, $part);
249     if ($part_a){
250         if (is_array($part_a[0])) return -1;
251         else{
252             $name = "";
253             if (is_array($part_a[2])){
254                 //first look in content type
255                 $name="";
256                 while ( list($key, $val) = each ($part_a[2])){
257                     if ((strcasecmp($val, "NAME")==0)||(strcasecmp($val, "FILENAME")==0)) 
258                         $name=$part_a[2][$key+1];
259                 }
260             }
261             if (empty($name)){
262                 //check in content disposition
263                 $id = count($part_a) - 2;
264                 if ((is_array($part_a[$id])) && (is_array($part_a[$id][1]))){
265                     $array = $part_a[$id][1];
266                     while ( list($key, $val) = each($array)){
267                         if ((strcasecmp($val, "NAME")==0)||(strcasecmp($val, "FILENAME")==0)) 
268                             $name=$array[$key+1];
269                     }
270                 }
271             }
272             return $name;
273         }
274     }else return "";
275 }
276
277
278 function iml_GetPartCharset($a, $part){
279     $part_a=iml_GetPartArray($a, $part);
280     if ($part_a){
281         if (is_array($part_a[0])) return -1;
282         else{
283             if (is_array($part_a[2])){
284                 $name="";
285                 while ( list($key, $val) = each ($part_a[2])) if (strcasecmp($val, "charset")==0) $name=$part_a[2][$key+1];
286                 return $name;
287             }
288             else return "";
289         }
290     }else return "";
291 }
292
293 function iml_GetPartList($a, $part){
294     //echo "MOO?"; flush();
295     $data = array();
296     $num_parts = iml_GetNumParts($a, $part);
297     //echo "($num_parts)"; flush();
298     if ($num_parts !== false){
299         //echo "<!-- ($num_parts parts)//-->\n";
300         for ($i = 0; $i<$num_parts; $i++){
301             $part_code = $part.(empty($part)?"":".").($i+1);
302             $part_type = iml_GetPartTypeCode($a, $part_code);
303             $part_disposition = iml_GetPartDisposition($a, $part_code);
304             //echo "<!-- part: $part_code type: $part_type //-->\n";
305             if (strcasecmp($part_disposition, "attachment")!=0 && 
306                 (($part_type == 1) || ($part_type==2))){
307                 $data = array_merge($data, iml_GetPartList($a, $part_code));
308             }else{
309                 $data[$part_code]["typestring"] = iml_GetPartTypeString($a, $part_code);
310                 $data[$part_code]["disposition"] = $part_disposition;
311                 $data[$part_code]["size"] = iml_GetPartSize($a, $part_code);
312                 $data[$part_code]["name"] = iml_GetPartName($a, $part_code);
313                 $data[$part_code]["id"] = iml_GetPartID($a, $part_code);
314             }
315         }
316     }
317     return $data;
318 }
319
320 function iml_GetNextPart($part){
321     if (strpos($part, ".")===false) return $part++;
322     else{
323         $parts_a = explode(".", $part);
324         $num_levels = count($parts_a);
325         $parts_a[$num_levels-1]++;
326         return implode(".", $parts_a);
327     }
328 }
329 ?>