43bcad88bcb306b1e58cd2e4e23f5c70a4675472
[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 global $PHPSESSID;
132
133 /** this if statement checks for the entity to show as the
134 primary message. To add more of them, just put them in the
135 order that is their priority.
136 **/
137 $id = $message["INFO"]["ID"];
138 $urlmailbox = urlencode($message["INFO"]["MAILBOX"]);
139
140 if (containsType($message, "text", "html", $ent_num)) {
141 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
142 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
143 } else if (containsType($message, "text", "plain", $ent_num)) {
144 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
145 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
146 }
147 // add other primary displaying message types here
148 else {
149 // find any type that's displayable
150 if (containsType($message, "text", "any_type", $ent_num)) {
151 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
152 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
153 } else if (containsType($message, "message", "any_type", $ent_num)) {
154 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
155 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
156 }
157 }
158
159 /** If there are other types that shouldn't be formatted, add
160 them here **/
161 if ($message["ENTITIES"][$ent_num]["TYPE1"] != "html")
162 $body = translateText($body, $wrap_at, $charset);
163
164
165 $body .= "<BR><SMALL><CENTER><A HREF=\"../src/download.php?PHPSESSID=$PHPSESSID&absolute_dl=true&passed_id=$id&passed_ent_id=$ent_num&mailbox=$urlmailbox\">". _("Download this as a file") ."</A></CENTER><BR></SMALL>";
166
167 /** Display the ATTACHMENTS: message if there's more than one part **/
168 if (count($message["ENTITIES"]) > 1) {
169 $body .= "<TABLE WIDTH=100% CELLSPACING=0 CELLPADDING=4 BORDER=0><TR><TD BGCOLOR=\"$color[0]\">";
170 $body .= "<TT><B>ATTACHMENTS:</B></TT>";
171 $body .= "</TD></TR><TR><TD BGCOLOR=\"$color[0]\">";
172 $num = 0;
173
174 for ($i = 0; $i < count($message["ENTITIES"]); $i++) {
175 /** If we've displayed this entity, go to the next one **/
176 if ($ent_num == $i)
177 continue;
178
179 $type0 = strtolower($message["ENTITIES"][$i]["TYPE0"]);
180 $type1 = strtolower($message["ENTITIES"][$i]["TYPE1"]);
181
182 $num++;
183 $filename = $message["ENTITIES"][$i]["FILENAME"];
184 if (trim($filename) == "") {
185 $display_filename = "untitled$i";
186 } else {
187 $display_filename = $filename;
188 }
189
190 $urlMailbox = urlencode($message["INFO"]["MAILBOX"]);
191 $id = $message["INFO"]["ID"];
192 $body .= "<TT>&nbsp;&nbsp;&nbsp;<A HREF=\"../src/download.php?PHPSESSID=$PHPSESSID&passed_id=$id&mailbox=$urlMailbox&passed_ent_id=$i\">" . $display_filename . "</A>&nbsp;&nbsp;<SMALL>(TYPE: $type0/$type1)</SMALL></TT><BR>";
193 }
194 $body .= "</TD></TR></TABLE>";
195 }
196 return $body;
197 }
198
199
200
201 /** this function decodes the body depending on the encoding type. **/
202 function decodeBody($body, $encoding) {
203 $encoding = strtolower($encoding);
204
205 if ($encoding == "quoted-printable") {
206 $body = quoted_printable_decode($body);
207
208 while (ereg("=\n", $body))
209 $body = ereg_replace ("=\n", "", $body);
210 } else if ($encoding == "base64") {
211 $body = base64_decode($body);
212 }
213
214 // All other encodings are returned raw.
215 return $body;
216 }
217
218
219 // This functions decode strings that is encoded according to
220 // RFC1522 (MIME Part Two: Message Header Extensions for Non-ASCII Text).
221 function decodeHeader ($string) {
222 if (eregi('=\?([^?]+)\?(q|b)\?([^?]+)\?=',
223 $string, $res)) {
224 if (ucfirst($res[2]) == "B") {
225 $replace = base64_decode($res[3]);
226 } else {
227 $replace = ereg_replace("_", " ", $res[3]);
228 $replace = quoted_printable_decode($replace);
229 }
230
231 $replace = charset_decode ($res[1], $replace);
232
233 $string = eregi_replace
234 ('=\?([^?]+)\?(q|b)\?([^?]+)\?=',
235 $replace, $string);
236 // In case there should be more encoding in the string: recurse
237 return (decodeHeader($string));
238 } else
239 return ($string);
240 }
241
242 // Encode a string according to RFC 1522 for use in headers if it
243 // contains 8-bit characters
244 function encodeHeader ($string) {
245 global $default_charset;
246
247 // Encode only if the string contains 8-bit characters
248 if (ereg("[\200-\377]", $string)) {
249 $newstring = "=?$default_charset?Q?";
250 $newstring .= str_replace(" ", "_", $string);
251
252 while (ereg("([\200-\377])", $newstring, $regs)) {
253 $replace = $regs[1];
254 $insert = "=" . bin2hex($replace);
255 $newstring = str_replace($replace, $insert, $newstring);
256 }
257
258 $newstring .= "?=";
259
260 return $newstring;
261 }
262
263 return $string;
264 }
265
266 ?>