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