Fixed the No Subect Bug
[squirrelmail.git] / functions / mime.php
1 <?php
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 /** 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.
134 **/
135 $id = $message["INFO"]["ID"];
136 $urlmailbox = urlencode($message["INFO"]["MAILBOX"]);
137
138 if (containsType($message, "text", "html", $ent_num)) {
139 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
140 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
141 } else if (containsType($message, "text", "plain", $ent_num)) {
142 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
143 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
144 }
145 // add other primary displaying message types here
146 else {
147 // find any type that's displayable
148 if (containsType($message, "text", "any_type", $ent_num)) {
149 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
150 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
151 } else if (containsType($message, "message", "any_type", $ent_num)) {
152 $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
153 $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
154 }
155 }
156
157 /** If there are other types that shouldn't be formatted, add
158 them here **/
159 if ($message["ENTITIES"][$ent_num]["TYPE1"] != "html")
160 $body = translateText($body, $wrap_at, $charset);
161
162
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>";
164
165 /** Display the ATTACHMENTS: message if there's more than one part **/
166 if (count($message["ENTITIES"]) > 1) {
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]\">";
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++;
181 $filename = $message["ENTITIES"][$i]["FILENAME"];
182 if (trim($filename) == "") {
183 $display_filename = "untitled$i";
184 } else {
185 $display_filename = $filename;
186 }
187
188 $urlMailbox = urlencode($message["INFO"]["MAILBOX"]);
189 $id = $message["INFO"]["ID"];
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>";
191 }
192 $body .= "</TD></TR></TABLE>";
193 }
194 return $body;
195 }
196
197
198
199 /** this function decodes the body depending on the encoding type. **/
200 function decodeBody($body, $encoding) {
201 $encoding = strtolower($encoding);
202
203 if ($encoding == "quoted-printable") {
204 $body = quoted_printable_decode($body);
205
206 while (ereg("=\n", $body))
207 $body = ereg_replace ("=\n", "", $body);
208 } else if ($encoding == "base64") {
209 $body = base64_decode($body);
210 }
211
212 // All other encodings are returned raw.
213 return $body;
214 }
215
216
217 // This functions decode strings that is encoded according to
218 // RFC1522 (MIME Part Two: Message Header Extensions for Non-ASCII Text).
219 function decodeHeader ($string) {
220 if (eregi('=\?([^?]+)\?(q|b)\?([^?]+)\?=',
221 $string, $res)) {
222 if (ucfirst($res[2]) == "B") {
223 $replace = base64_decode($res[3]);
224 } else {
225 $replace = ereg_replace("_", " ", $res[3]);
226 $replace = quoted_printable_decode($replace);
227 }
228
229 $replace = charset_decode ($res[1], $replace);
230
231 $string = eregi_replace
232 ('=\?([^?]+)\?(q|b)\?([^?]+)\?=',
233 $replace, $string);
234 // In case there should be more encoding in the string: recurse
235 return (decodeHeader($string));
236 } else
237 return ($string);
238 }
239
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
264 ?>