2 /////////////////////////////////////////////////////////
4 // Iloha MIME Library (IML)
6 // (C)Copyright 2002 Ryo Chijiiwa <Ryo@IlohaMail.org>
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
12 /////////////////////////////////////////////////////////
14 /********************************************************
16 FILE: include/mime.inc
18 Provide functions for handling mime messages.
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.
24 ********************************************************/
29 $MIME_APPLICATION = 3;
35 function iml_ClosingParenPos($str, $start) {
40 for ($i=$start; $i<$len; $i++) {
41 if ($str[$i] == '"' && $str[$i-1] != "\\")
42 $in_quote = ($in_quote + 1) % 2;
44 if ($str[$i]=="(") $level++;
45 else if (($level > 0) && ($str[$i]==")")) $level--;
46 else if (($level == 0) && ($str[$i]==")")) return $i;
51 function iml_ParseBSString($str){
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
64 while ($str[$i+1] == " ") $i++; // skip additional spaces
65 } else if ($str[$i]=="(") { //new part
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
74 $a[$id].=$str[$i]; //add to current element in array
75 } else if ($in_quote) {
77 $i++; //escape backslashes
78 if ($str[$i] == '"' || $str[$i] == "\\")
81 $a[$id] .= $str[$i]; //add to current element in array
89 function iml_GetRawStructureArray($str){
90 $line=substr($str, 1, strlen($str) - 2);
91 $line = str_replace(")(", ") (", $line);
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);
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)){
111 //echo "m - part: $original_part current: $part rest: $rest array: ".implode(" ", $a)."<br>\n";
112 return iml_GetPartArray($a[$part-1], $rest);
114 if ((strcasecmp($a[0], "message")==0) && (strcasecmp($a[1], "rfc822")==0)){
117 //echo "s - part: $part rest: $rest array: ".implode(" ", $a)."<br>\n";
118 if (is_array($a[$part-1])) return $a[$part-1];
120 }else if (($part==0) || (empty($part))){
125 function iml_GetNumParts($a, $part){
127 $parent=iml_GetPartArray($a, $part);
129 if ((strcasecmp($parent[0], "message")==0) && (strcasecmp($parent[1], "rfc822")==0)){
130 $parent = $parent[8];
135 while (( list ($key, $val) = each ($parent) )&&($is_array)){
136 $is_array=is_array($parent[$key]);
145 function iml_GetPartTypeString($a, $part){
146 $part_a=iml_GetPartArray($a, $part);
148 if (is_array($part_a[0])){
149 $type_str = "MULTIPART/";
151 while(list($n,$element)=each($part_a)){
152 if (!is_array($part_a[$n])){
153 $type_str.=$part_a[$n];
158 }else return $part_a[0]."/".$part_a[1];
162 function iml_GetFirstTextPart($structure,$part){
163 if ($part==0) $part="";
165 while ($typeCode!=0){
166 $typeCode = iml_GetPartTypeCode($structure, $part);
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){
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");
185 $part_a=iml_GetPartArray($a, $part);
187 if (is_array($part_a[0])) $str="multipart";
188 else $str=$part_a[0];
191 while ( list($key, $val) = each($types)) if (strcasecmp($val, $str)==0) $code=$key;
196 function iml_GetPartEncodingCode($a, $part){
197 $encodings=array("7BIT", "8BIT", "BINARY", "BASE64", "QUOTED-PRINTABLE", "OTHER");
199 $part_a=iml_GetPartArray($a, $part);
201 if (is_array($part_a[0])) return -1;
202 else $str=$part_a[5];
205 while ( list($key, $val) = each($encodings)) if (strcasecmp($val, $str)==0) $code=$key;
212 function iml_GetPartEncodingString($a, $part){
213 $part_a=iml_GetPartArray($a, $part);
215 if (is_array($part_a[0])) return -1;
216 else return $part_a[5];
220 function iml_GetPartSize($a, $part){
221 $part_a=iml_GetPartArray($a, $part);
223 if (is_array($part_a[0])) return -1;
224 else return $part_a[6];
228 function iml_GetPartID($a, $part){
229 $part_a=iml_GetPartArray($a, $part);
231 if (is_array($part_a[0])) return -1;
232 else return $part_a[3];
236 function iml_GetPartDisposition($a, $part){
237 $part_a=iml_GetPartArray($a, $part);
239 if (is_array($part_a[0])) return -1;
241 $id = count($part_a) - 2;
242 if (is_array($part_a[$id])) return $part_a[$id][0];
248 function iml_GetPartName($a, $part){
249 $part_a=iml_GetPartArray($a, $part);
251 if (is_array($part_a[0])) return -1;
254 if (is_array($part_a[2])){
255 //first look in content type
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];
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];
279 function iml_GetPartCharset($a, $part){
280 $part_a=iml_GetPartArray($a, $part);
282 if (is_array($part_a[0])) return -1;
284 if (is_array($part_a[2])){
286 while ( list($key, $val) = each ($part_a[2])) if (strcasecmp($val, "charset")==0) $name=$part_a[2][$key+1];
294 function iml_GetPartList($a, $part){
295 //echo "MOO?"; flush();
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));
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);
321 function iml_GetNextPart($part){
322 if (strpos($part, ".")===false) return $part++;
324 $parts_a = explode(".", $part);
325 $num_levels = count($parts_a);
326 $parts_a[$num_levels-1]++;
327 return implode(".", $parts_a);