| 1 | <? |
| 2 | /** mime.php |
| 3 | ** |
| 4 | ** This contains the functions necessary to detect and decode MIME messages. |
| 5 | **/ |
| 6 | |
| 7 | |
| 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) { |
| 12 | if ($type0 == "multipart") { |
| 13 | $bound = trim($bound); |
| 14 | $i = 0; |
| 15 | while (($i < count($body)) && (substr($body[$i], 0, strlen("--$bound--")) != "--$bound--")) { |
| 16 | if (trim($body[$i]) == "--$bound") { |
| 17 | $j = $i+1; |
| 18 | $p = 0; |
| 19 | |
| 20 | /** Lets find the header for this entity **/ |
| 21 | /** If the first line after the boundary is blank, we use default values **/ |
| 22 | if (trim($body[$j]) == "") { |
| 23 | $ent_type0 = "text"; |
| 24 | $ent_type1 = "plain"; |
| 25 | $charset = "us-ascii"; |
| 26 | $j++; |
| 27 | /** If the first line ISNT blank, read in the header for this entity **/ |
| 28 | } else { |
| 29 | while ((substr(trim($body[$j]), 0, strlen("--$bound")) != "--$bound") && (trim($body[$j]) != "")) { |
| 30 | $entity_header[$p] = $body[$j]; |
| 31 | $j++; |
| 32 | $p++; |
| 33 | } |
| 34 | /** All of these values are getting passed back to us **/ |
| 35 | sqimap_get_entity_header($imapConnection, $entity_header, $ent_type0, $ent_type1, $ent_bound, $encoding, $charset, $filename); |
| 36 | } |
| 37 | |
| 38 | |
| 39 | /** OK, we have the header information, now lets decide what to do with it **/ |
| 40 | if ($ent_type0 == "multipart") { |
| 41 | $y = 0; |
| 42 | while (substr($body[$j], 0, strlen("--$bound--")) != "--$bound--") { |
| 43 | $ent_body[$y] = $body[$j]; |
| 44 | $y++; |
| 45 | $j++; |
| 46 | } |
| 47 | $ent = decodeMime($ent_body, $ent_bound, $ent_type0, $ent_type1, $entities); |
| 48 | $entities = $ent; |
| 49 | } else { |
| 50 | $j++; |
| 51 | $entity_body = ""; |
| 52 | while (substr(trim($body[$j]), 0, strlen("--$bound")) != "--$bound") { |
| 53 | $entity_body .= $body[$j]; |
| 54 | $j++; |
| 55 | } |
| 56 | $count = count($entities); |
| 57 | $entities[$count] = getEntity($entity_body, $ent_bound, $ent_type0, $ent_type1, $encoding, $charset, $filename); |
| 58 | } |
| 59 | } |
| 60 | $i++; |
| 61 | } |
| 62 | } else { |
| 63 | /** If this isn't a multipart message **/ |
| 64 | $j = 0; |
| 65 | $entity_body = ""; |
| 66 | while ($j < count($body)) { |
| 67 | $entity_body .= $body[$j]; |
| 68 | $j++; |
| 69 | } |
| 70 | |
| 71 | $count = count($entities); |
| 72 | $entities[$count] = getEntity($entity_body, $bound, $type0, $type1, $encoding, $charset, $filename); |
| 73 | } |
| 74 | |
| 75 | return $entities; |
| 76 | } |
| 77 | |
| 78 | /** This gets one entity's properties **/ |
| 79 | function getEntity($body, $bound, $type0, $type1, $encoding, $charset, $filename) { |
| 80 | $msg["TYPE0"] = $type0; |
| 81 | $msg["TYPE1"] = $type1; |
| 82 | $msg["ENCODING"] = $encoding; |
| 83 | $msg["CHARSET"] = $charset; |
| 84 | $msg["FILENAME"] = $filename; |
| 85 | |
| 86 | $msg["BODY"] = $body; |
| 87 | |
| 88 | return $msg; |
| 89 | } |
| 90 | |
| 91 | /** This will check whether or not the message contains a certain type. It |
| 92 | searches through all the entities for a match. |
| 93 | **/ |
| 94 | function containsType($message, $type0, $type1, &$ent_num) { |
| 95 | $type0 = strtolower($type0); |
| 96 | $type1 = strtolower($type1); |
| 97 | for ($i = 0; $i < count($message["ENTITIES"]); $i++) { |
| 98 | /** Check only on type0 **/ |
| 99 | if ( $type1 == "any_type" ) { |
| 100 | if ( ($message["ENTITIES"][$i]["TYPE0"] == $type0) ) { |
| 101 | $ent_num = $i; |
| 102 | return true; |
| 103 | } |
| 104 | |
| 105 | /** Check on type0 and type1 **/ |
| 106 | } else { |
| 107 | if ( ($message["ENTITIES"][$i]["TYPE0"] == $type0) && ($message["ENTITIES"][$i]["TYPE1"] == $type1) ) { |
| 108 | $ent_num = $i; |
| 109 | return true; |
| 110 | } |
| 111 | } |
| 112 | } |
| 113 | return false; |
| 114 | } |
| 115 | |
| 116 | /** This returns a parsed string called $body. That string can then be displayed |
| 117 | as the actual message in the HTML. It contains everything needed, including |
| 118 | HTML Tags, Attachments at the bottom, etc. |
| 119 | **/ |
| 120 | function formatBody($message, $color, $wrap_at) { |
| 121 | |
| 122 | /** this if statement checks for the entity to show as the primary message. To |
| 123 | add more of them, just put them in the order that is their priority. |
| 124 | **/ |
| 125 | $id = $message["INFO"]["ID"]; |
| 126 | $urlmailbox = urlencode($message["INFO"]["MAILBOX"]); |
| 127 | |
| 128 | if (containsType($message, "text", "html", $ent_num)) { |
| 129 | $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]); |
| 130 | } else if (containsType($message, "text", "plain", $ent_num)) { |
| 131 | $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]); |
| 132 | } |
| 133 | // add other primary displaying message types here |
| 134 | else { |
| 135 | // find any type that's displayable |
| 136 | if (containsType($message, "text", "any_type", $ent_num)) { |
| 137 | $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]); |
| 138 | } else if (containsType($message, "message", "any_type", $ent_num)) { |
| 139 | $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]); |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | /** If there are other types that shouldn't be formatted, add them here **/ |
| 144 | if ($message["ENTITIES"][$ent_num]["TYPE1"] != "html") |
| 145 | $body = translateText($body, $wrap_at); |
| 146 | |
| 147 | |
| 148 | $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>"; |
| 149 | |
| 150 | /** Display the ATTACHMENTS: message if there's more than one part **/ |
| 151 | if (count($message["ENTITIES"]) > 1) { |
| 152 | $body .= "<TABLE WIDTH=100% CELLSPACING=0 CELLPADDING=4 BORDER=0><TR><TD BGCOLOR=\"$color[0]\">"; |
| 153 | $body .= "<TT><B>ATTACHMENTS:</B></TT>"; |
| 154 | $body .= "</TD></TR><TR><TD BGCOLOR=\"$color[0]\">"; |
| 155 | $num = 0; |
| 156 | |
| 157 | for ($i = 0; $i < count($message["ENTITIES"]); $i++) { |
| 158 | /** If we've displayed this entity, go to the next one **/ |
| 159 | if ($ent_num == $i) |
| 160 | continue; |
| 161 | |
| 162 | $type0 = strtolower($message["ENTITIES"][$i]["TYPE0"]); |
| 163 | $type1 = strtolower($message["ENTITIES"][$i]["TYPE1"]); |
| 164 | |
| 165 | $num++; |
| 166 | $filename = $message["ENTITIES"][$i]["FILENAME"]; |
| 167 | if (trim($filename) == "") { |
| 168 | $display_filename = "untitled$i"; |
| 169 | } else { |
| 170 | $display_filename = $filename; |
| 171 | } |
| 172 | |
| 173 | $urlMailbox = urlencode($message["INFO"]["MAILBOX"]); |
| 174 | $id = $message["INFO"]["ID"]; |
| 175 | $body .= "<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>"; |
| 176 | } |
| 177 | $body .= "</TD></TR></TABLE>"; |
| 178 | } |
| 179 | return $body; |
| 180 | } |
| 181 | |
| 182 | |
| 183 | |
| 184 | /** this function decodes the body depending on the encoding type. **/ |
| 185 | function decodeBody($body, $encoding) { |
| 186 | $encoding = strtolower($encoding); |
| 187 | |
| 188 | if ($encoding == "us-ascii") { |
| 189 | $newbody = $body; // if only they all were this easy |
| 190 | |
| 191 | } else if ($encoding == "quoted-printable") { |
| 192 | $body_ary = explode("\n", $body); |
| 193 | |
| 194 | for ($q=0; $q < count($body_ary); $q++) { |
| 195 | if (substr(trim($body_ary[$q]), -1) == "=") { |
| 196 | $body_ary[$q] = trim($body_ary[$q]); |
| 197 | $body_ary[$q] = substr($body_ary[$q], 0, strlen($body_ary[$q])-1); |
| 198 | } else if (substr(trim($body_ary[$q]), -3) == "=20") { |
| 199 | $body_ary[$q] = trim($body_ary[$q]); |
| 200 | $body_ary[$q] = substr($body_ary[$q], 0, strlen($body_ary[$q])-3); |
| 201 | $body_ary[$q] = "$body_ary[$q]\n"; |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | for ($q=0;$q < count($body_ary);$q++) { |
| 206 | $body_ary[$q] = ereg_replace("=3D", "=", $body_ary[$q]); |
| 207 | } |
| 208 | |
| 209 | $body = ""; |
| 210 | for ($i = 0; $i < count($body_ary); $i++) { |
| 211 | $body .= "$body_ary[$i]\n"; |
| 212 | } |
| 213 | |
| 214 | $newbody = $body; |
| 215 | } else if ($encoding == "base64") { |
| 216 | $newbody = base64_decode($body); |
| 217 | |
| 218 | } else { |
| 219 | $newbody = $body; |
| 220 | } |
| 221 | return $newbody; |
| 222 | } |
| 223 | |
| 224 | |
| 225 | // This functions decode strings that is encoded according to |
| 226 | // RFC1522 (MIME Part Two: Message Header Extensions for Non-ASCII Text). |
| 227 | function rfc1522Decode ($string) { |
| 228 | // Recognizing only US-ASCII and ISO-8859. Other charsets should |
| 229 | // probably be recognized as well. |
| 230 | if (eregi('=\?(us-ascii|iso-8859-([0-9])+)\?(q|b)\?([^?]+)\?=', |
| 231 | $string, $res)) { |
| 232 | if (ucfirst($res[3]) == "B") { |
| 233 | $replace = base64_decode($res[4]); |
| 234 | } else { |
| 235 | $replace = ereg_replace("_", " ", $res[4]); |
| 236 | $replace = quoted_printable_decode($replace); |
| 237 | } |
| 238 | |
| 239 | // Only US-ASCII and ISO-8859-1 can be displayed without further ado |
| 240 | if ($res[2] != "" && $res[2] != "1") { |
| 241 | // This get rid of all characters with over 0x9F |
| 242 | $replace = strtr($replace, "\240\241\242\243\244\245\246\247". |
| 243 | "\250\251\252\253\254\255\256\257". |
| 244 | "\260\261\262\263\264\265\266\267". |
| 245 | "\270\271\272\273\274\275\276\277". |
| 246 | "\300\301\302\303\304\305\306\307". |
| 247 | "\310\311\312\313\314\315\316\317". |
| 248 | "\320\321\322\323\324\325\326\327". |
| 249 | "\330\331\332\333\334\335\336\337". |
| 250 | "\340\341\342\343\344\345\346\347". |
| 251 | "\350\351\352\353\354\355\356\357". |
| 252 | "\360\361\362\363\364\365\366\367". |
| 253 | "\370\371\372\373\374\375\376\377", |
| 254 | "????????????????????????????????????????". |
| 255 | "????????????????????????????????????????". |
| 256 | "????????????????????????????????????????". |
| 257 | "????????"); |
| 258 | } |
| 259 | |
| 260 | $string = eregi_replace |
| 261 | ('=\?(us-ascii|iso-8859-([0-9])+)\?(q|b)\?([^?]+)\?=', |
| 262 | $replace, $string); |
| 263 | |
| 264 | return (rfc1522Decode($string)); |
| 265 | } else |
| 266 | return ($string); |
| 267 | } |
| 268 | |
| 269 | ?> |