aceb0d5c |
1 | <? |
2 | /** mime.php |
3 | ** |
4 | ** This contains the functions necessary to detect and decode MIME messages. |
5 | **/ |
6 | |
7 | |
4809f489 |
8 | /** This is the first function called. It decides if this is a multipart |
9 | message or if it should be handled as a single entity |
10 | **/ |
11 | function decodeMime($body, $bound, $type0, $type1, &$entities) { |
aceb0d5c |
12 | if ($type0 == "multipart") { |
aceb0d5c |
13 | $bound = trim($bound); |
4809f489 |
14 | while (($i < count($body)) && (substr($body[$i], 0, strlen("--$bound--")) != "--$bound--")) { |
15 | if (trim($body[$i]) == "--$bound") { |
16 | $j = $i+1; |
aceb0d5c |
17 | $p = 0; |
18 | |
4809f489 |
19 | /** Lets find the header for this entity **/ |
20 | /** If the first line after the boundary is blank, we use default values **/ |
21 | if (trim($body[$j]) == "") { |
22 | $ent_type0 = "text"; |
23 | $ent_type1 = "plain"; |
24 | $charset = "us-ascii"; |
aceb0d5c |
25 | $j++; |
4809f489 |
26 | /** If the first line ISNT blank, read in the header for this entity **/ |
27 | } else { |
28 | while ((substr(trim($body[$j]), 0, strlen("--$bound")) != "--$bound") && (trim($body[$j]) != "")) { |
29 | $entity_header[$p] = $body[$j]; |
30 | $j++; |
31 | $p++; |
32 | } |
33 | /** All of these values are getting passed back to us **/ |
34 | fetchEntityHeader($imapConnection, $entity_header, $ent_type0, $ent_type1, $ent_bound, $encoding, $charset, $filename); |
aceb0d5c |
35 | } |
bcb432a3 |
36 | |
bcb432a3 |
37 | |
4809f489 |
38 | /** OK, we have the header information, now lets decide what to do with it **/ |
39 | if ($ent_type0 == "multipart") { |
40 | $y = 0; |
41 | while (substr($body[$j], 0, strlen("--$bound--")) != "--$bound--") { |
42 | $ent_body[$y] = $body[$j]; |
43 | $y++; |
44 | $j++; |
45 | } |
46 | $ent = decodeMime($ent_body, $ent_bound, $ent_type0, $ent_type1, $entities); |
47 | $entities = $ent; |
48 | } else if ($ent_type0 == "text") { |
49 | while (substr(trim($body[$j]), 0, strlen("--$bound")) != "--$bound") { |
bcb432a3 |
50 | $entity_body[$p] = $body[$j]; |
51 | $j++; |
52 | $p++; |
53 | } |
4809f489 |
54 | $count = count($entities); |
55 | $entities[$count] = getEntity($entity_body, $ent_bound, $ent_type0, $ent_type1, $encoding, $charset, $filename); |
56 | |
bcb432a3 |
57 | } else { |
7c9499e1 |
58 | $j++; |
59 | $entity_body = ""; |
4809f489 |
60 | while (substr(trim($body[$j]), 0, strlen("--$bound")) != "--$bound") { |
bcb432a3 |
61 | $entity_body .= $body[$j]; |
62 | $j++; |
63 | } |
4809f489 |
64 | $count = count($entities); |
65 | $entities[$count] = getEntity($entity_body, $ent_bound, $ent_type0, $ent_type1, $encoding, $charset, $filename); |
bcb432a3 |
66 | } |
aceb0d5c |
67 | } |
68 | $i++; |
69 | } |
d4467150 |
70 | } else { |
4809f489 |
71 | $count = count($entities); |
72 | $entities[$count] = getEntity($body, $bound, $type0, $type1, $encoding, $charset, $filename); |
d4467150 |
73 | } |
74 | |
4809f489 |
75 | return $entities; |
d4467150 |
76 | } |
77 | |
78 | /** This gets one entity's properties **/ |
7c9499e1 |
79 | function getEntity($body, $bound, $type0, $type1, $encoding, $charset, $filename) { |
4809f489 |
80 | $msg["TYPE0"] = $type0; |
81 | $msg["TYPE1"] = $type1; |
82 | $msg["ENCODING"] = $encoding; |
83 | $msg["CHARSET"] = $charset; |
84 | $msg["FILENAME"] = $filename; |
d4467150 |
85 | |
4809f489 |
86 | $msg["BODY"][0] = $body; |
d4467150 |
87 | if ($type0 == "text") { |
8405ee35 |
88 | // error correcting if they didn't follow RFC standards |
89 | if (trim($type1) == "") |
90 | $type1 = "plain"; |
91 | |
aceb0d5c |
92 | if ($type1 == "plain") { |
aceb0d5c |
93 | for ($p = 0;$p < count($body);$p++) { |
4809f489 |
94 | $msg["BODY"][$p] = parsePlainTextMessage($body[$p]); |
95 | } |
96 | } else if ($type1 == "html") { |
97 | for ($p = 0;$p < count($body);$p++) { |
98 | $msg["BODY"][$p] = parseHTMLMessage($body[$p]); |
aceb0d5c |
99 | } |
d4467150 |
100 | } else { |
4809f489 |
101 | $msg["BODY"] = $body; |
aceb0d5c |
102 | } |
7c9499e1 |
103 | } else { |
4809f489 |
104 | $msg["BODY"][0] = $body; |
aceb0d5c |
105 | } |
106 | |
d4467150 |
107 | return $msg; |
108 | } |
109 | |
4809f489 |
110 | /** This will check whether or not the message contains a certain type. It |
111 | searches through all the entities for a match. |
112 | **/ |
b1dadc61 |
113 | function containsType($message, $type0, $type1, &$ent_num) { |
114 | $type0 = strtolower($type0); |
115 | $type1 = strtolower($type1); |
d4467150 |
116 | for ($i = 0; $i < count($message["ENTITIES"]); $i++) { |
b1dadc61 |
117 | /** Check only on type0 **/ |
118 | if ( $type1 == "any_type" ) { |
119 | if ( ($message["ENTITIES"][$i]["TYPE0"] == $type0) ) { |
120 | $ent_num = $i; |
121 | return true; |
122 | } |
123 | |
124 | /** Check on type0 and type1 **/ |
125 | } else { |
126 | if ( ($message["ENTITIES"][$i]["TYPE0"] == $type0) && ($message["ENTITIES"][$i]["TYPE1"] == $type1) ) { |
127 | $ent_num = $i; |
128 | return true; |
129 | } |
d4467150 |
130 | } |
131 | } |
b1dadc61 |
132 | return false; |
133 | } |
8405ee35 |
134 | |
4809f489 |
135 | /** This returns a parsed string called $body. That string can then be displayed |
136 | as the actual message in the HTML. It contains everything needed, including |
137 | HTML Tags, Attachments at the bottom, etc. |
138 | **/ |
b1dadc61 |
139 | function formatBody($message) { |
4809f489 |
140 | /** this if statement checks for the entity to show as the primary message. To |
141 | add more of them, just put them in the order that is their priority. |
142 | **/ |
b1dadc61 |
143 | if (containsType($message, "text", "html", $ent_num)) { |
144 | $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]); |
145 | } else if (containsType($message, "text", "plain", $ent_num)) { |
146 | $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]); |
4809f489 |
147 | } |
148 | // add other primary displaying message types here |
b1dadc61 |
149 | else { |
150 | // find any type that's displayable |
151 | if (containsType($message, "text", "any_type", $ent_num)) { |
152 | $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]); |
153 | } else if (containsType($message, "message", "any_type", $ent_num)) { |
154 | $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]); |
8405ee35 |
155 | } |
156 | } |
157 | |
b1dadc61 |
158 | /** Display the ATTACHMENTS: message if there's more than one part **/ |
159 | if (count($message["ENTITIES"]) > 1) { |
8405ee35 |
160 | $pos = count($body); |
b1dadc61 |
161 | $body[$pos] .= "<BR><TT><U><B>ATTACHMENTS:</B></U></TT><BR>"; |
162 | $num = 0; |
163 | |
164 | for ($i = 0; $i < count($message["ENTITIES"]); $i++) { |
165 | /** If we've displayed this entity, go to the next one **/ |
166 | if ($ent_num == $i) |
167 | continue; |
168 | |
169 | $type0 = strtolower($message["ENTITIES"][$i]["TYPE0"]); |
170 | $type1 = strtolower($message["ENTITIES"][$i]["TYPE1"]); |
171 | |
172 | $num++; |
7c9499e1 |
173 | $filename = $message["ENTITIES"][$i]["FILENAME"]; |
b1dadc61 |
174 | if (trim($filename) == "") { |
175 | $filename = "UNKNOWN_FORMAT_" . time() . $i; |
176 | $display_filename = "Attachment $i"; |
177 | } else { |
178 | $display_filename = $filename; |
179 | } |
7c9499e1 |
180 | |
97be2168 |
181 | $urlMailbox = urlencode($message["INFO"]["MAILBOX"]); |
182 | $id = $message["INFO"]["ID"]; |
183 | $body[$pos] .= "<TT> <A HREF=\"../src/download.php?passed_id=$id&mailbox=$urlMailbox&passed_ent_id=$i\">" . $display_filename . "</A> <SMALL>(TYPE: $type0/$type1)</SMALL></TT><BR>"; |
8405ee35 |
184 | } |
185 | } |
d4467150 |
186 | return $body; |
187 | } |
188 | |
4809f489 |
189 | |
190 | |
191 | /** this function decodes the body depending on the encoding type. **/ |
d4467150 |
192 | function decodeBody($body, $encoding) { |
193 | $encoding = strtolower($encoding); |
194 | if ($encoding == "us-ascii") { |
195 | $newbody = $body; // if only they all were this easy |
196 | } else if ($encoding == "quoted-printable") { |
197 | for ($q=0; $q < count($body); $q++) { |
198 | if (substr(trim($body[$q]), -1) == "=") { |
199 | $body[$q] = trim($body[$q]); |
200 | $body[$q] = substr($body[$q], 0, strlen($body[$q])-1); |
201 | } else if (substr(trim($body[$q]), -3) == "=20") { |
202 | $body[$q] = trim($body[$q]); |
203 | $body[$q] = substr($body[$q], 0, strlen($body[$q])-3); |
204 | $body[$q] = "$body[$q]\n"; // maybe should be \n.. dunno |
205 | } |
206 | } |
14d10786 |
207 | for ($q=0;$q < count($body);$q++) { |
208 | $body[$q] = ereg_replace("=3D", "=", $body[$q]); |
209 | } |
d4467150 |
210 | $newbody = $body; |
97be2168 |
211 | } else if ($encoding == "base64") { |
212 | $newbody = base64_decode($body); |
d4467150 |
213 | } else { |
214 | $newbody = $body; |
215 | } |
216 | return $newbody; |
aceb0d5c |
217 | } |
218 | ?> |