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