Updated with new methods.
[squirrelmail.git] / functions / mime.php
1 <?
2 /** mime.php
3 **
4 ** This contains the functions necessary to detect and decode MIME
5 ** messages.
6 **
7 **/
8
9 $mime_php = true;
10
11 if (!isset($i18n_php))
12 include "../functions/i18n.php";
13
14 /** This is the first function called. It decides if this is a multipart
15 message or if it should be handled as a single entity
16 **/
17 function decodeMime($body, $bound, $type0, $type1, $encoding, $charset, &$entities) {
18 if ($type0 == "multipart") {
19 $bound = trim($bound);
20 $i = 0;
21 while (($i < count($body)) && (substr($body[$i], 0, strlen("--$bound--")) != "--$bound--")) {
22 if (trim($body[$i]) == "--$bound") {
23 $j = $i+1;
24 $p = 0;
25
26 /** Lets find the header for this entity **/
27 /** If the first line after the boundary is blank, we
28 use default values **/
29 if (trim($body[$j]) == "") {
30 $ent_type0 = "text";
31 $ent_type1 = "plain";
32 $charset = "us-ascii";
33 $j++;
34 /** If the first line ISNT blank, read in the header
35 for this entity **/
36 } else {
37 while ((substr(trim($body[$j]), 0, strlen("--$bound")) != "--$bound") && (trim($body[$j]) != "")) {
38 $entity_header[$p] = $body[$j];
39 $j++;
40 $p++;
41 }
42 /** All of these values are getting passed back to us **/
43 sqimap_get_entity_header($imapConnection, $entity_header, $ent_type0, $ent_type1, $ent_bound, $encoding, $charset, $filename);
44 }
45
46
47 /** OK, we have the header information, now lets decide
48 what to do with it **/
49 if ($ent_type0 == "multipart") {
50 $y = 0;
51 while (substr($body[$j], 0, strlen("--$bound--")) != "--$bound--") {
52 $ent_body[$y] = $body[$j];
53 $y++;
54 $j++;
55 }
56 $ent = decodeMime($ent_body, $ent_bound, $ent_type0, $ent_type1, $charset, $entities);
57 $entities = $ent;
58 } else {
59 $j++;
60 $entity_body = "";
61 while (substr(trim($body[$j]), 0, strlen("--$bound")) != "--$bound") {
62 $entity_body .= $body[$j];
63 $j++;
64 }
65 $count = count($entities);
66 $entities[$count] = getEntity($entity_body, $ent_bound, $ent_type0, $ent_type1, $encoding, $charset, $filename);
67 }
68 }
69 $i++;
70 }
71 } else {
72 /** If this isn't a multipart message **/
73 $j = 0;
74 $entity_body = "";
75 while ($j < count($body)) {
76 $entity_body .= $body[$j];
77 $j++;
78 }
79
80 $count = count($entities);
81 $entities[$count] = getEntity($entity_body, $bound, $type0, $type1, $encoding, $charset, $filename);
82 }
83
84 return $entities;
85 }
86
87 /** This gets one entity's properties **/
88 function getEntity($body, $bound, $type0, $type1, $encoding, $charset, $filename) {
89 $msg["TYPE0"] = $type0;
90 $msg["TYPE1"] = $type1;
91 $msg["ENCODING"] = $encoding;
92 $msg["CHARSET"] = $charset;
93 $msg["FILENAME"] = $filename;
94
95 $msg["BODY"] = $body;
96
97 return $msg;
98 }
99
100 /** This will check whether or not the message contains a certain type. It
101 searches through all the entities for a match.
102 **/
103 function containsType($message, $type0, $type1, &$ent_num) {
104 $type0 = strtolower($type0);
105 $type1 = strtolower($type1);
106 for ($i = 0; $i < count($message["ENTITIES"]); $i++) {
107 /** Check only on type0 **/
108 if ( $type1 == "any_type" ) {
109 if ( ($message["ENTITIES"][$i]["TYPE0"] == $type0) ) {
110 $ent_num = $i;
111 return true;
112 }
113
114 /** Check on type0 and type1 **/
115 } else {
116 if ( ($message["ENTITIES"][$i]["TYPE0"] == $type0) && ($message["ENTITIES"][$i]["TYPE1"] == $type1) ) {
117 $ent_num = $i;
118 return true;
119 }
120 }
121 }
122 return false;
123 }
124
125 /** This returns a parsed string called $body. That string can then
126 be displayed as the actual message in the HTML. It contains
127 everything needed, including HTML Tags, Attachments at the
128 bottom, etc.
129 **/
130 function formatBody($message, $color, $wrap_at) {
131
132 /** this if statement checks for the entity to show as the
133 primary message. To add more of them, just put them in the
134 order that is their priority.
135 **/
136 $id = $message["INFO"]["ID"];
137 $urlmailbox = urlencode($message["INFO"]["MAILBOX"]);
138
139 if (containsType($message, "text", "html", $ent_num)) {
140 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
141 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
142 } else if (containsType($message, "text", "plain", $ent_num)) {
143 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
144 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
145 }
146 // add other primary displaying message types here
147 else {
148 // find any type that's displayable
149 if (containsType($message, "text", "any_type", $ent_num)) {
150 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
151 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
152 } else if (containsType($message, "message", "any_type", $ent_num)) {
153 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
154 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
155 }
156 }
157
158 /** If there are other types that shouldn't be formatted, add
159 them here **/
160 if ($message["ENTITIES"][$ent_num]["TYPE1"] != "html")
161 $body = translateText($body, $wrap_at, $charset);
162
163
164 $body .= "<BR><SMALL><CENTER><A HREF=\"../src/download.php?absolute_dl=true&passed_id=$id&passed_ent_id=$ent_num&mailbox=$urlmailbox\">". _("Download this as a file") ."</A></CENTER><BR></SMALL>";
165
166 /** Display the ATTACHMENTS: message if there's more than one part **/
167 if (count($message["ENTITIES"]) > 1) {
168 $body .= "<TABLE WIDTH=100% CELLSPACING=0 CELLPADDING=4 BORDER=0><TR><TD BGCOLOR=\"$color[0]\">";
169 $body .= "<TT><B>ATTACHMENTS:</B></TT>";
170 $body .= "</TD></TR><TR><TD BGCOLOR=\"$color[0]\">";
171 $num = 0;
172
173 for ($i = 0; $i < count($message["ENTITIES"]); $i++) {
174 /** If we've displayed this entity, go to the next one **/
175 if ($ent_num == $i)
176 continue;
177
178 $type0 = strtolower($message["ENTITIES"][$i]["TYPE0"]);
179 $type1 = strtolower($message["ENTITIES"][$i]["TYPE1"]);
180
181 $num++;
182 $filename = $message["ENTITIES"][$i]["FILENAME"];
183 if (trim($filename) == "") {
184 $display_filename = "untitled$i";
185 } else {
186 $display_filename = $filename;
187 }
188
189 $urlMailbox = urlencode($message["INFO"]["MAILBOX"]);
190 $id = $message["INFO"]["ID"];
191 $body .= "<TT>&nbsp;&nbsp;&nbsp;<A HREF=\"../src/download.php?passed_id=$id&mailbox=$urlMailbox&passed_ent_id=$i\">" . $display_filename . "</A>&nbsp;&nbsp;<SMALL>(TYPE: $type0/$type1)</SMALL></TT><BR>";
192 }
193 $body .= "</TD></TR></TABLE>";
194 }
195 return $body;
196 }
197
198
199
200 /** this function decodes the body depending on the encoding type. **/
201 function decodeBody($body, $encoding) {
202 $encoding = strtolower($encoding);
203
204 if ($encoding == "quoted-printable") {
205 $body = quoted_printable_decode($body);
206
207 while (ereg("=\n", $body))
208 $body = ereg_replace ("=\n", "", $body);
209 } else if ($encoding == "base64") {
210 $body = base64_decode($body);
211 }
212
213 // All other encodings are returned raw.
214 return $body;
215 }
216
217
218 // This functions decode strings that is encoded according to
219 // RFC1522 (MIME Part Two: Message Header Extensions for Non-ASCII Text).
220 function decodeHeader ($string) {
221 if (eregi('=\?([^?]+)\?(q|b)\?([^?]+)\?=',
222 $string, $res)) {
223 if (ucfirst($res[2]) == "B") {
224 $replace = base64_decode($res[3]);
225 } else {
226 $replace = ereg_replace("_", " ", $res[3]);
227 $replace = quoted_printable_decode($replace);
228 }
229
230 $replace = charset_decode ($res[1], $replace);
231
232 $string = eregi_replace
233 ('=\?([^?]+)\?(q|b)\?([^?]+)\?=',
234 $replace, $string);
235 // In case there should be more encoding in the string: recurse
236 return (decodeHeader($string));
237 } else
238 return ($string);
239 }
240
241 ?>