Added basic support for message highlighting. Note that this needs quite
[squirrelmail.git] / functions / mime.php
CommitLineData
59177427 1<?php
aceb0d5c 2 /** mime.php
3 **
d068c0ec 4 ** This contains the functions necessary to detect and decode MIME
5 ** messages.
6 **
aceb0d5c 7 **/
8
d068c0ec 9 $mime_php = true;
aceb0d5c 10
1fd97780 11 if (!isset($i18n_php))
12 include "../functions/i18n.php";
13
4809f489 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 **/
bf74a636 17 function decodeMime($body, $bound, $type0, $type1, $encoding, $charset, &$entities) {
aceb0d5c 18 if ($type0 == "multipart") {
aceb0d5c 19 $bound = trim($bound);
f7835374 20 $i = 0;
4809f489 21 while (($i < count($body)) && (substr($body[$i], 0, strlen("--$bound--")) != "--$bound--")) {
22 if (trim($body[$i]) == "--$bound") {
23 $j = $i+1;
aceb0d5c 24 $p = 0;
25
4809f489 26 /** Lets find the header for this entity **/
d068c0ec 27 /** If the first line after the boundary is blank, we
28 use default values **/
4809f489 29 if (trim($body[$j]) == "") {
30 $ent_type0 = "text";
31 $ent_type1 = "plain";
32 $charset = "us-ascii";
aceb0d5c 33 $j++;
d068c0ec 34 /** If the first line ISNT blank, read in the header
35 for this entity **/
4809f489 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 **/
d29aac0e 43 sqimap_get_entity_header($imapConnection, $entity_header, $ent_type0, $ent_type1, $ent_bound, $encoding, $charset, $filename);
aceb0d5c 44 }
bcb432a3 45
bcb432a3 46
d068c0ec 47 /** OK, we have the header information, now lets decide
48 what to do with it **/
4809f489 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 }
bf74a636 56 $ent = decodeMime($ent_body, $ent_bound, $ent_type0, $ent_type1, $charset, $entities);
4809f489 57 $entities = $ent;
bcb432a3 58 } else {
7c9499e1 59 $j++;
60 $entity_body = "";
4809f489 61 while (substr(trim($body[$j]), 0, strlen("--$bound")) != "--$bound") {
bcb432a3 62 $entity_body .= $body[$j];
63 $j++;
64 }
4809f489 65 $count = count($entities);
66 $entities[$count] = getEntity($entity_body, $ent_bound, $ent_type0, $ent_type1, $encoding, $charset, $filename);
bcb432a3 67 }
aceb0d5c 68 }
69 $i++;
70 }
d4467150 71 } else {
7831268e 72 /** If this isn't a multipart message **/
73 $j = 0;
74 $entity_body = "";
78509c54 75 while ($j < count($body)) {
7831268e 76 $entity_body .= $body[$j];
77 $j++;
78 }
79
4809f489 80 $count = count($entities);
7831268e 81 $entities[$count] = getEntity($entity_body, $bound, $type0, $type1, $encoding, $charset, $filename);
d4467150 82 }
83
4809f489 84 return $entities;
d4467150 85 }
86
87 /** This gets one entity's properties **/
7c9499e1 88 function getEntity($body, $bound, $type0, $type1, $encoding, $charset, $filename) {
4809f489 89 $msg["TYPE0"] = $type0;
90 $msg["TYPE1"] = $type1;
91 $msg["ENCODING"] = $encoding;
92 $msg["CHARSET"] = $charset;
93 $msg["FILENAME"] = $filename;
d4467150 94
7831268e 95 $msg["BODY"] = $body;
aceb0d5c 96
d4467150 97 return $msg;
98 }
99
4809f489 100 /** This will check whether or not the message contains a certain type. It
101 searches through all the entities for a match.
102 **/
b1dadc61 103 function containsType($message, $type0, $type1, &$ent_num) {
104 $type0 = strtolower($type0);
105 $type1 = strtolower($type1);
d4467150 106 for ($i = 0; $i < count($message["ENTITIES"]); $i++) {
b1dadc61 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 }
d4467150 120 }
121 }
b1dadc61 122 return false;
123 }
8405ee35 124
d068c0ec 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.
4809f489 129 **/
a8648d75 130 function formatBody($message, $color, $wrap_at) {
d068c0ec 131 /** this if statement checks for the entity to show as the
132 primary message. To add more of them, just put them in the
133 order that is their priority.
4809f489 134 **/
7085fa78 135 $id = $message["INFO"]["ID"];
136 $urlmailbox = urlencode($message["INFO"]["MAILBOX"]);
7085fa78 137
b1dadc61 138 if (containsType($message, "text", "html", $ent_num)) {
a8648d75 139 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
17ce8467 140 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
b1dadc61 141 } else if (containsType($message, "text", "plain", $ent_num)) {
a8648d75 142 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
17ce8467 143 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
4809f489 144 }
145 // add other primary displaying message types here
b1dadc61 146 else {
147 // find any type that's displayable
148 if (containsType($message, "text", "any_type", $ent_num)) {
a8648d75 149 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
17ce8467 150 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
b1dadc61 151 } else if (containsType($message, "message", "any_type", $ent_num)) {
a8648d75 152 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
17ce8467 153 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
8405ee35 154 }
155 }
156
d068c0ec 157 /** If there are other types that shouldn't be formatted, add
158 them here **/
78509c54 159 if ($message["ENTITIES"][$ent_num]["TYPE1"] != "html")
17ce8467 160 $body = translateText($body, $wrap_at, $charset);
a8648d75 161
78509c54 162
9f2215a1 163 $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>";
7831268e 164
b1dadc61 165 /** Display the ATTACHMENTS: message if there's more than one part **/
166 if (count($message["ENTITIES"]) > 1) {
7831268e 167 $body .= "<TABLE WIDTH=100% CELLSPACING=0 CELLPADDING=4 BORDER=0><TR><TD BGCOLOR=\"$color[0]\">";
168 $body .= "<TT><B>ATTACHMENTS:</B></TT>";
169 $body .= "</TD></TR><TR><TD BGCOLOR=\"$color[0]\">";
b1dadc61 170 $num = 0;
171
172 for ($i = 0; $i < count($message["ENTITIES"]); $i++) {
173 /** If we've displayed this entity, go to the next one **/
174 if ($ent_num == $i)
175 continue;
176
177 $type0 = strtolower($message["ENTITIES"][$i]["TYPE0"]);
178 $type1 = strtolower($message["ENTITIES"][$i]["TYPE1"]);
179
180 $num++;
7c9499e1 181 $filename = $message["ENTITIES"][$i]["FILENAME"];
b1dadc61 182 if (trim($filename) == "") {
7085fa78 183 $display_filename = "untitled$i";
b1dadc61 184 } else {
185 $display_filename = $filename;
186 }
7c9499e1 187
97be2168 188 $urlMailbox = urlencode($message["INFO"]["MAILBOX"]);
189 $id = $message["INFO"]["ID"];
9f2215a1 190 $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>";
8405ee35 191 }
7831268e 192 $body .= "</TD></TR></TABLE>";
8405ee35 193 }
d4467150 194 return $body;
195 }
196
4809f489 197
198
199 /** this function decodes the body depending on the encoding type. **/
d4467150 200 function decodeBody($body, $encoding) {
201 $encoding = strtolower($encoding);
7831268e 202
ef3f274f 203 if ($encoding == "quoted-printable") {
204 $body = quoted_printable_decode($body);
db87f79c 205
ef3f274f 206 while (ereg("=\n", $body))
207 $body = ereg_replace ("=\n", "", $body);
97be2168 208 } else if ($encoding == "base64") {
ef3f274f 209 $body = base64_decode($body);
d4467150 210 }
ef3f274f 211
212 // All other encodings are returned raw.
213 return $body;
aceb0d5c 214 }
a4c2cd49 215
216
217 // This functions decode strings that is encoded according to
218 // RFC1522 (MIME Part Two: Message Header Extensions for Non-ASCII Text).
2e434774 219 function decodeHeader ($string) {
1fd97780 220 if (eregi('=\?([^?]+)\?(q|b)\?([^?]+)\?=',
a4c2cd49 221 $string, $res)) {
1fd97780 222 if (ucfirst($res[2]) == "B") {
223 $replace = base64_decode($res[3]);
a4c2cd49 224 } else {
1fd97780 225 $replace = ereg_replace("_", " ", $res[3]);
a4c2cd49 226 $replace = quoted_printable_decode($replace);
227 }
228
1fd97780 229 $replace = charset_decode ($res[1], $replace);
a4c2cd49 230
231 $string = eregi_replace
1fd97780 232 ('=\?([^?]+)\?(q|b)\?([^?]+)\?=',
a4c2cd49 233 $replace, $string);
2e434774 234 // In case there should be more encoding in the string: recurse
235 return (decodeHeader($string));
a4c2cd49 236 } else
237 return ($string);
238 }
239
c3084273 240 // Encode a string according to RFC 1522 for use in headers if it
241 // contains 8-bit characters
242 function encodeHeader ($string) {
243 global $default_charset;
244
245 // Encode only if the string contains 8-bit characters
246 if (ereg("[\200-\377]", $string)) {
247 $newstring = "=?$default_charset?Q?";
248 $newstring .= str_replace(" ", "_", $string);
249
250 while (ereg("([\200-\377])", $newstring, $regs)) {
251 $replace = $regs[1];
252 $insert = "=" . bin2hex($replace);
253 $newstring = str_replace($replace, $insert, $newstring);
254 }
255
256 $newstring .= "?=";
257
258 return $newstring;
259 }
260
261 return $string;
262 }
263
9f9d7d28 264?>