mime.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. <?php
  2. /** mime.php
  3. **
  4. ** This contains the functions necessary to detect and decode MIME
  5. ** messages.
  6. **
  7. **/
  8. $mime_php = true;
  9. if (!isset($i18n_php))
  10. include "../functions/i18n.php";
  11. /** This is the first function called. It decides if this is a multipart
  12. message or if it should be handled as a single entity
  13. **/
  14. function decodeMime($body, $bound, $type0, $type1, $encoding, $charset, &$entities) {
  15. if ($type0 == "multipart") {
  16. $bound = trim($bound);
  17. $i = 0;
  18. while (($i < count($body)) && (substr($body[$i], 0, strlen("--$bound--")) != "--$bound--")) {
  19. if (trim($body[$i]) == "--$bound") {
  20. $j = $i+1;
  21. $p = 0;
  22. /** Lets find the header for this entity **/
  23. /** If the first line after the boundary is blank, we
  24. use default values **/
  25. if (trim($body[$j]) == "") {
  26. $ent_type0 = "text";
  27. $ent_type1 = "plain";
  28. $charset = "us-ascii";
  29. $j++;
  30. /** If the first line ISNT blank, read in the header
  31. for this entity **/
  32. } else {
  33. while ((substr(trim($body[$j]), 0, strlen("--$bound")) != "--$bound") && (trim($body[$j]) != "")) {
  34. $entity_header[$p] = $body[$j];
  35. $j++;
  36. $p++;
  37. }
  38. /** All of these values are getting passed back to us **/
  39. sqimap_get_entity_header($imapConnection, $entity_header, $ent_type0, $ent_type1, $ent_bound, $encoding, $charset, $filename);
  40. }
  41. /** OK, we have the header information, now lets decide
  42. what to do with it **/
  43. if ($ent_type0 == "multipart") {
  44. $y = 0;
  45. while (substr($body[$j], 0, strlen("--$bound--")) != "--$bound--") {
  46. $ent_body[$y] = $body[$j];
  47. $y++;
  48. $j++;
  49. }
  50. $ent = decodeMime($ent_body, $ent_bound, $ent_type0, $ent_type1, $charset, $entities);
  51. $entities = $ent;
  52. } else {
  53. $j++;
  54. $entity_body = "";
  55. while (substr(trim($body[$j]), 0, strlen("--$bound")) != "--$bound") {
  56. $entity_body .= $body[$j];
  57. $j++;
  58. }
  59. $count = count($entities);
  60. $entities[$count] = getEntity($entity_body, $ent_bound, $ent_type0, $ent_type1, $encoding, $charset, $filename);
  61. }
  62. }
  63. $i++;
  64. }
  65. } else {
  66. /** If this isn't a multipart message **/
  67. $j = 0;
  68. $entity_body = "";
  69. while ($j < count($body)) {
  70. $entity_body .= $body[$j];
  71. $j++;
  72. }
  73. $count = count($entities);
  74. $entities[$count] = getEntity($entity_body, $bound, $type0, $type1, $encoding, $charset, $filename);
  75. }
  76. return $entities;
  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. $msg["BODY"] = $body;
  86. return $msg;
  87. }
  88. /** This will check whether or not the message contains a certain type. It
  89. searches through all the entities for a match.
  90. **/
  91. function containsType($message, $type0, $type1, &$ent_num) {
  92. $type0 = strtolower($type0);
  93. $type1 = strtolower($type1);
  94. for ($i = 0; $i < count($message["ENTITIES"]); $i++) {
  95. /** Check only on type0 **/
  96. if ( $type1 == "any_type" ) {
  97. if ( ($message["ENTITIES"][$i]["TYPE0"] == $type0) ) {
  98. $ent_num = $i;
  99. return true;
  100. }
  101. /** Check on type0 and type1 **/
  102. } else {
  103. if ( ($message["ENTITIES"][$i]["TYPE0"] == $type0) && ($message["ENTITIES"][$i]["TYPE1"] == $type1) ) {
  104. $ent_num = $i;
  105. return true;
  106. }
  107. }
  108. }
  109. return false;
  110. }
  111. /** This returns a parsed string called $body. That string can then
  112. be displayed as the actual message in the HTML. It contains
  113. everything needed, including HTML Tags, Attachments at the
  114. bottom, etc.
  115. **/
  116. function formatBody($message, $color, $wrap_at) {
  117. /** this if statement checks for the entity to show as the
  118. primary message. To add more of them, just put them in the
  119. order that is their priority.
  120. **/
  121. $id = $message["INFO"]["ID"];
  122. $urlmailbox = urlencode($message["INFO"]["MAILBOX"]);
  123. if (containsType($message, "text", "html", $ent_num)) {
  124. $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
  125. $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
  126. } else if (containsType($message, "text", "plain", $ent_num)) {
  127. $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
  128. $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
  129. }
  130. // add other primary displaying message types here
  131. else {
  132. // find any type that's displayable
  133. if (containsType($message, "text", "any_type", $ent_num)) {
  134. $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
  135. $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
  136. } else if (containsType($message, "message", "any_type", $ent_num)) {
  137. $body = decodeBody($message["ENTITIES"][$ent_num]["BODY"], $message["ENTITIES"][$ent_num]["ENCODING"]);
  138. $charset = $message["ENTITIES"][$ent_num]["CHARSET"];
  139. }
  140. }
  141. /** If there are other types that shouldn't be formatted, add
  142. them here **/
  143. if ($message["ENTITIES"][$ent_num]["TYPE1"] != "html")
  144. $body = translateText($body, $wrap_at, $charset);
  145. $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>";
  146. /** Display the ATTACHMENTS: message if there's more than one part **/
  147. if (count($message["ENTITIES"]) > 1) {
  148. $body .= "<TABLE WIDTH=100% CELLSPACING=0 CELLPADDING=4 BORDER=0><TR><TD BGCOLOR=\"$color[0]\">";
  149. $body .= "<TT><B>ATTACHMENTS:</B></TT>";
  150. $body .= "</TD></TR><TR><TD BGCOLOR=\"$color[0]\">";
  151. $num = 0;
  152. for ($i = 0; $i < count($message["ENTITIES"]); $i++) {
  153. /** If we've displayed this entity, go to the next one **/
  154. if ($ent_num == $i)
  155. continue;
  156. $type0 = strtolower($message["ENTITIES"][$i]["TYPE0"]);
  157. $type1 = strtolower($message["ENTITIES"][$i]["TYPE1"]);
  158. $num++;
  159. $filename = $message["ENTITIES"][$i]["FILENAME"];
  160. if (trim($filename) == "") {
  161. $display_filename = "untitled$i";
  162. } else {
  163. $display_filename = $filename;
  164. }
  165. $urlMailbox = urlencode($message["INFO"]["MAILBOX"]);
  166. $id = $message["INFO"]["ID"];
  167. $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>";
  168. }
  169. $body .= "</TD></TR></TABLE>";
  170. }
  171. return $body;
  172. }
  173. /** this function decodes the body depending on the encoding type. **/
  174. function decodeBody($body, $encoding) {
  175. $encoding = strtolower($encoding);
  176. if ($encoding == "quoted-printable") {
  177. $body = quoted_printable_decode($body);
  178. while (ereg("=\n", $body))
  179. $body = ereg_replace ("=\n", "", $body);
  180. } else if ($encoding == "base64") {
  181. $body = base64_decode($body);
  182. }
  183. // All other encodings are returned raw.
  184. return $body;
  185. }
  186. // This functions decode strings that is encoded according to
  187. // RFC1522 (MIME Part Two: Message Header Extensions for Non-ASCII Text).
  188. function decodeHeader ($string) {
  189. if (eregi('=\?([^?]+)\?(q|b)\?([^?]+)\?=',
  190. $string, $res)) {
  191. if (ucfirst($res[2]) == "B") {
  192. $replace = base64_decode($res[3]);
  193. } else {
  194. $replace = ereg_replace("_", " ", $res[3]);
  195. $replace = quoted_printable_decode($replace);
  196. }
  197. $replace = charset_decode ($res[1], $replace);
  198. $string = eregi_replace
  199. ('=\?([^?]+)\?(q|b)\?([^?]+)\?=',
  200. $replace, $string);
  201. // In case there should be more encoding in the string: recurse
  202. return (decodeHeader($string));
  203. } else
  204. return ($string);
  205. }
  206. // Encode a string according to RFC 1522 for use in headers if it
  207. // contains 8-bit characters
  208. function encodeHeader ($string) {
  209. global $default_charset;
  210. // Encode only if the string contains 8-bit characters
  211. if (ereg("[\200-\377]", $string)) {
  212. $newstring = "=?$default_charset?Q?";
  213. $newstring .= str_replace(" ", "_", $string);
  214. while (ereg("([\200-\377])", $newstring, $regs)) {
  215. $replace = $regs[1];
  216. $insert = "=" . bin2hex($replace);
  217. $newstring = str_replace($replace, $insert, $newstring);
  218. }
  219. $newstring .= "?=";
  220. return $newstring;
  221. }
  222. return $string;
  223. }
  224. ?>