PageRenderTime 57ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/com/fsck/k9/mail/internet/MimeUtility.java

https://bitbucket.org/devconcert1/k-9
Java | 1240 lines | 1084 code | 40 blank | 116 comment | 54 complexity | 9a986bf26b73e39f4fd5cf7d9dbf1f3a MD5 | raw file
  1. package com.fsck.k9.mail.internet;
  2. import android.content.Context;
  3. import android.util.Log;
  4. import com.fsck.k9.K9;
  5. import com.fsck.k9.R;
  6. import com.fsck.k9.helper.HtmlConverter;
  7. import com.fsck.k9.mail.*;
  8. import com.fsck.k9.mail.Message.RecipientType;
  9. import com.fsck.k9.mail.internet.BinaryTempFileBody.BinaryTempFileBodyInputStream;
  10. import org.apache.commons.io.IOUtils;
  11. import org.apache.james.mime4j.codec.Base64InputStream;
  12. import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
  13. import java.io.IOException;
  14. import java.io.InputStream;
  15. import java.io.OutputStream;
  16. import java.util.ArrayList;
  17. import java.util.Date;
  18. import java.util.HashSet;
  19. import java.util.List;
  20. import java.util.Locale;
  21. import java.util.Set;
  22. import java.util.regex.Matcher;
  23. import java.util.regex.Pattern;
  24. import java.nio.charset.Charset;
  25. import java.nio.charset.IllegalCharsetNameException;
  26. public class MimeUtility {
  27. public static final String DEFAULT_ATTACHMENT_MIME_TYPE = "application/octet-stream";
  28. public static final String K9_SETTINGS_MIME_TYPE = "application/x-k9settings";
  29. private static final String TEXT_DIVIDER =
  30. "------------------------------------------------------------------------";
  31. /*
  32. * http://www.w3schools.com/media/media_mimeref.asp
  33. * +
  34. * http://www.stdicon.com/mimetypes
  35. */
  36. public static final String[][] MIME_TYPE_BY_EXTENSION_MAP = new String[][] {
  37. //* Do not delete the next two lines
  38. { "", DEFAULT_ATTACHMENT_MIME_TYPE },
  39. { "k9s", K9_SETTINGS_MIME_TYPE},
  40. //* Do not delete the previous two lines
  41. { "123", "application/vnd.lotus-1-2-3"},
  42. { "323", "text/h323"},
  43. { "3dml", "text/vnd.in3d.3dml"},
  44. { "3g2", "video/3gpp2"},
  45. { "3gp", "video/3gpp"},
  46. { "aab", "application/x-authorware-bin"},
  47. { "aac", "audio/x-aac"},
  48. { "aam", "application/x-authorware-map"},
  49. { "a", "application/octet-stream"},
  50. { "aas", "application/x-authorware-seg"},
  51. { "abw", "application/x-abiword"},
  52. { "acc", "application/vnd.americandynamics.acc"},
  53. { "ace", "application/x-ace-compressed"},
  54. { "acu", "application/vnd.acucobol"},
  55. { "acutc", "application/vnd.acucorp"},
  56. { "acx", "application/internet-property-stream"},
  57. { "adp", "audio/adpcm"},
  58. { "aep", "application/vnd.audiograph"},
  59. { "afm", "application/x-font-type1"},
  60. { "afp", "application/vnd.ibm.modcap"},
  61. { "ai", "application/postscript"},
  62. { "aif", "audio/x-aiff"},
  63. { "aifc", "audio/x-aiff"},
  64. { "aiff", "audio/x-aiff"},
  65. { "air", "application/vnd.adobe.air-application-installer-package+zip"},
  66. { "ami", "application/vnd.amiga.ami"},
  67. { "apk", "application/vnd.android.package-archive"},
  68. { "application", "application/x-ms-application"},
  69. { "apr", "application/vnd.lotus-approach"},
  70. { "asc", "application/pgp-signature"},
  71. { "asf", "video/x-ms-asf"},
  72. { "asm", "text/x-asm"},
  73. { "aso", "application/vnd.accpac.simply.aso"},
  74. { "asr", "video/x-ms-asf"},
  75. { "asx", "video/x-ms-asf"},
  76. { "atc", "application/vnd.acucorp"},
  77. { "atom", "application/atom+xml"},
  78. { "atomcat", "application/atomcat+xml"},
  79. { "atomsvc", "application/atomsvc+xml"},
  80. { "atx", "application/vnd.antix.game-component"},
  81. { "au", "audio/basic"},
  82. { "avi", "video/x-msvideo"},
  83. { "aw", "application/applixware"},
  84. { "axs", "application/olescript"},
  85. { "azf", "application/vnd.airzip.filesecure.azf"},
  86. { "azs", "application/vnd.airzip.filesecure.azs"},
  87. { "azw", "application/vnd.amazon.ebook"},
  88. { "bas", "text/plain"},
  89. { "bat", "application/x-msdownload"},
  90. { "bcpio", "application/x-bcpio"},
  91. { "bdf", "application/x-font-bdf"},
  92. { "bdm", "application/vnd.syncml.dm+wbxml"},
  93. { "bh2", "application/vnd.fujitsu.oasysprs"},
  94. { "bin", "application/octet-stream"},
  95. { "bmi", "application/vnd.bmi"},
  96. { "bmp", "image/bmp"},
  97. { "book", "application/vnd.framemaker"},
  98. { "box", "application/vnd.previewsystems.box"},
  99. { "boz", "application/x-bzip2"},
  100. { "bpk", "application/octet-stream"},
  101. { "btif", "image/prs.btif"},
  102. { "bz2", "application/x-bzip2"},
  103. { "bz", "application/x-bzip"},
  104. { "c4d", "application/vnd.clonk.c4group"},
  105. { "c4f", "application/vnd.clonk.c4group"},
  106. { "c4g", "application/vnd.clonk.c4group"},
  107. { "c4p", "application/vnd.clonk.c4group"},
  108. { "c4u", "application/vnd.clonk.c4group"},
  109. { "cab", "application/vnd.ms-cab-compressed"},
  110. { "car", "application/vnd.curl.car"},
  111. { "cat", "application/vnd.ms-pki.seccat"},
  112. { "cct", "application/x-director"},
  113. { "cc", "text/x-c"},
  114. { "ccxml", "application/ccxml+xml"},
  115. { "cdbcmsg", "application/vnd.contact.cmsg"},
  116. { "cdf", "application/x-cdf"},
  117. { "cdkey", "application/vnd.mediastation.cdkey"},
  118. { "cdx", "chemical/x-cdx"},
  119. { "cdxml", "application/vnd.chemdraw+xml"},
  120. { "cdy", "application/vnd.cinderella"},
  121. { "cer", "application/x-x509-ca-cert"},
  122. { "cgm", "image/cgm"},
  123. { "chat", "application/x-chat"},
  124. { "chm", "application/vnd.ms-htmlhelp"},
  125. { "chrt", "application/vnd.kde.kchart"},
  126. { "cif", "chemical/x-cif"},
  127. { "cii", "application/vnd.anser-web-certificate-issue-initiation"},
  128. { "cla", "application/vnd.claymore"},
  129. { "class", "application/java-vm"},
  130. { "clkk", "application/vnd.crick.clicker.keyboard"},
  131. { "clkp", "application/vnd.crick.clicker.palette"},
  132. { "clkt", "application/vnd.crick.clicker.template"},
  133. { "clkw", "application/vnd.crick.clicker.wordbank"},
  134. { "clkx", "application/vnd.crick.clicker"},
  135. { "clp", "application/x-msclip"},
  136. { "cmc", "application/vnd.cosmocaller"},
  137. { "cmdf", "chemical/x-cmdf"},
  138. { "cml", "chemical/x-cml"},
  139. { "cmp", "application/vnd.yellowriver-custom-menu"},
  140. { "cmx", "image/x-cmx"},
  141. { "cod", "application/vnd.rim.cod"},
  142. { "com", "application/x-msdownload"},
  143. { "conf", "text/plain"},
  144. { "cpio", "application/x-cpio"},
  145. { "cpp", "text/x-c"},
  146. { "cpt", "application/mac-compactpro"},
  147. { "crd", "application/x-mscardfile"},
  148. { "crl", "application/pkix-crl"},
  149. { "crt", "application/x-x509-ca-cert"},
  150. { "csh", "application/x-csh"},
  151. { "csml", "chemical/x-csml"},
  152. { "csp", "application/vnd.commonspace"},
  153. { "css", "text/css"},
  154. { "cst", "application/x-director"},
  155. { "csv", "text/csv"},
  156. { "c", "text/plain"},
  157. { "cu", "application/cu-seeme"},
  158. { "curl", "text/vnd.curl"},
  159. { "cww", "application/prs.cww"},
  160. { "cxt", "application/x-director"},
  161. { "cxx", "text/x-c"},
  162. { "daf", "application/vnd.mobius.daf"},
  163. { "dataless", "application/vnd.fdsn.seed"},
  164. { "davmount", "application/davmount+xml"},
  165. { "dcr", "application/x-director"},
  166. { "dcurl", "text/vnd.curl.dcurl"},
  167. { "dd2", "application/vnd.oma.dd2+xml"},
  168. { "ddd", "application/vnd.fujixerox.ddd"},
  169. { "deb", "application/x-debian-package"},
  170. { "def", "text/plain"},
  171. { "deploy", "application/octet-stream"},
  172. { "der", "application/x-x509-ca-cert"},
  173. { "dfac", "application/vnd.dreamfactory"},
  174. { "dic", "text/x-c"},
  175. { "diff", "text/plain"},
  176. { "dir", "application/x-director"},
  177. { "dis", "application/vnd.mobius.dis"},
  178. { "dist", "application/octet-stream"},
  179. { "distz", "application/octet-stream"},
  180. { "djv", "image/vnd.djvu"},
  181. { "djvu", "image/vnd.djvu"},
  182. { "dll", "application/x-msdownload"},
  183. { "dmg", "application/octet-stream"},
  184. { "dms", "application/octet-stream"},
  185. { "dna", "application/vnd.dna"},
  186. { "doc", "application/msword"},
  187. { "docm", "application/vnd.ms-word.document.macroenabled.12"},
  188. { "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
  189. { "dot", "application/msword"},
  190. { "dotm", "application/vnd.ms-word.template.macroenabled.12"},
  191. { "dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"},
  192. { "dp", "application/vnd.osgi.dp"},
  193. { "dpg", "application/vnd.dpgraph"},
  194. { "dsc", "text/prs.lines.tag"},
  195. { "dtb", "application/x-dtbook+xml"},
  196. { "dtd", "application/xml-dtd"},
  197. { "dts", "audio/vnd.dts"},
  198. { "dtshd", "audio/vnd.dts.hd"},
  199. { "dump", "application/octet-stream"},
  200. { "dvi", "application/x-dvi"},
  201. { "dwf", "model/vnd.dwf"},
  202. { "dwg", "image/vnd.dwg"},
  203. { "dxf", "image/vnd.dxf"},
  204. { "dxp", "application/vnd.spotfire.dxp"},
  205. { "dxr", "application/x-director"},
  206. { "ecelp4800", "audio/vnd.nuera.ecelp4800"},
  207. { "ecelp7470", "audio/vnd.nuera.ecelp7470"},
  208. { "ecelp9600", "audio/vnd.nuera.ecelp9600"},
  209. { "ecma", "application/ecmascript"},
  210. { "edm", "application/vnd.novadigm.edm"},
  211. { "edx", "application/vnd.novadigm.edx"},
  212. { "efif", "application/vnd.picsel"},
  213. { "ei6", "application/vnd.pg.osasli"},
  214. { "elc", "application/octet-stream"},
  215. { "eml", "message/rfc822"},
  216. { "emma", "application/emma+xml"},
  217. { "eol", "audio/vnd.digital-winds"},
  218. { "eot", "application/vnd.ms-fontobject"},
  219. { "eps", "application/postscript"},
  220. { "epub", "application/epub+zip"},
  221. { "es3", "application/vnd.eszigno3+xml"},
  222. { "esf", "application/vnd.epson.esf"},
  223. { "et3", "application/vnd.eszigno3+xml"},
  224. { "etx", "text/x-setext"},
  225. { "evy", "application/envoy"},
  226. { "exe", "application/octet-stream"},
  227. { "ext", "application/vnd.novadigm.ext"},
  228. { "ez2", "application/vnd.ezpix-album"},
  229. { "ez3", "application/vnd.ezpix-package"},
  230. { "ez", "application/andrew-inset"},
  231. { "f4v", "video/x-f4v"},
  232. { "f77", "text/x-fortran"},
  233. { "f90", "text/x-fortran"},
  234. { "fbs", "image/vnd.fastbidsheet"},
  235. { "fdf", "application/vnd.fdf"},
  236. { "fe_launch", "application/vnd.denovo.fcselayout-link"},
  237. { "fg5", "application/vnd.fujitsu.oasysgp"},
  238. { "fgd", "application/x-director"},
  239. { "fh4", "image/x-freehand"},
  240. { "fh5", "image/x-freehand"},
  241. { "fh7", "image/x-freehand"},
  242. { "fhc", "image/x-freehand"},
  243. { "fh", "image/x-freehand"},
  244. { "fif", "application/fractals"},
  245. { "fig", "application/x-xfig"},
  246. { "fli", "video/x-fli"},
  247. { "flo", "application/vnd.micrografx.flo"},
  248. { "flr", "x-world/x-vrml"},
  249. { "flv", "video/x-flv"},
  250. { "flw", "application/vnd.kde.kivio"},
  251. { "flx", "text/vnd.fmi.flexstor"},
  252. { "fly", "text/vnd.fly"},
  253. { "fm", "application/vnd.framemaker"},
  254. { "fnc", "application/vnd.frogans.fnc"},
  255. { "for", "text/x-fortran"},
  256. { "fpx", "image/vnd.fpx"},
  257. { "frame", "application/vnd.framemaker"},
  258. { "fsc", "application/vnd.fsc.weblaunch"},
  259. { "fst", "image/vnd.fst"},
  260. { "ftc", "application/vnd.fluxtime.clip"},
  261. { "f", "text/x-fortran"},
  262. { "fti", "application/vnd.anser-web-funds-transfer-initiation"},
  263. { "fvt", "video/vnd.fvt"},
  264. { "fzs", "application/vnd.fuzzysheet"},
  265. { "g3", "image/g3fax"},
  266. { "gac", "application/vnd.groove-account"},
  267. { "gdl", "model/vnd.gdl"},
  268. { "geo", "application/vnd.dynageo"},
  269. { "gex", "application/vnd.geometry-explorer"},
  270. { "ggb", "application/vnd.geogebra.file"},
  271. { "ggt", "application/vnd.geogebra.tool"},
  272. { "ghf", "application/vnd.groove-help"},
  273. { "gif", "image/gif"},
  274. { "gim", "application/vnd.groove-identity-message"},
  275. { "gmx", "application/vnd.gmx"},
  276. { "gnumeric", "application/x-gnumeric"},
  277. { "gph", "application/vnd.flographit"},
  278. { "gqf", "application/vnd.grafeq"},
  279. { "gqs", "application/vnd.grafeq"},
  280. { "gram", "application/srgs"},
  281. { "gre", "application/vnd.geometry-explorer"},
  282. { "grv", "application/vnd.groove-injector"},
  283. { "grxml", "application/srgs+xml"},
  284. { "gsf", "application/x-font-ghostscript"},
  285. { "gtar", "application/x-gtar"},
  286. { "gtm", "application/vnd.groove-tool-message"},
  287. { "gtw", "model/vnd.gtw"},
  288. { "gv", "text/vnd.graphviz"},
  289. { "gz", "application/x-gzip"},
  290. { "h261", "video/h261"},
  291. { "h263", "video/h263"},
  292. { "h264", "video/h264"},
  293. { "hbci", "application/vnd.hbci"},
  294. { "hdf", "application/x-hdf"},
  295. { "hh", "text/x-c"},
  296. { "hlp", "application/winhlp"},
  297. { "hpgl", "application/vnd.hp-hpgl"},
  298. { "hpid", "application/vnd.hp-hpid"},
  299. { "hps", "application/vnd.hp-hps"},
  300. { "hqx", "application/mac-binhex40"},
  301. { "hta", "application/hta"},
  302. { "htc", "text/x-component"},
  303. { "h", "text/plain"},
  304. { "htke", "application/vnd.kenameaapp"},
  305. { "html", "text/html"},
  306. { "htm", "text/html"},
  307. { "htt", "text/webviewhtml"},
  308. { "hvd", "application/vnd.yamaha.hv-dic"},
  309. { "hvp", "application/vnd.yamaha.hv-voice"},
  310. { "hvs", "application/vnd.yamaha.hv-script"},
  311. { "icc", "application/vnd.iccprofile"},
  312. { "ice", "x-conference/x-cooltalk"},
  313. { "icm", "application/vnd.iccprofile"},
  314. { "ico", "image/x-icon"},
  315. { "ics", "text/calendar"},
  316. { "ief", "image/ief"},
  317. { "ifb", "text/calendar"},
  318. { "ifm", "application/vnd.shana.informed.formdata"},
  319. { "iges", "model/iges"},
  320. { "igl", "application/vnd.igloader"},
  321. { "igs", "model/iges"},
  322. { "igx", "application/vnd.micrografx.igx"},
  323. { "iif", "application/vnd.shana.informed.interchange"},
  324. { "iii", "application/x-iphone"},
  325. { "imp", "application/vnd.accpac.simply.imp"},
  326. { "ims", "application/vnd.ms-ims"},
  327. { "ins", "application/x-internet-signup"},
  328. { "in", "text/plain"},
  329. { "ipk", "application/vnd.shana.informed.package"},
  330. { "irm", "application/vnd.ibm.rights-management"},
  331. { "irp", "application/vnd.irepository.package+xml"},
  332. { "iso", "application/octet-stream"},
  333. { "isp", "application/x-internet-signup"},
  334. { "itp", "application/vnd.shana.informed.formtemplate"},
  335. { "ivp", "application/vnd.immervision-ivp"},
  336. { "ivu", "application/vnd.immervision-ivu"},
  337. { "jad", "text/vnd.sun.j2me.app-descriptor"},
  338. { "jam", "application/vnd.jam"},
  339. { "jar", "application/java-archive"},
  340. { "java", "text/x-java-source"},
  341. { "jfif", "image/pipeg"},
  342. { "jisp", "application/vnd.jisp"},
  343. { "jlt", "application/vnd.hp-jlyt"},
  344. { "jnlp", "application/x-java-jnlp-file"},
  345. { "joda", "application/vnd.joost.joda-archive"},
  346. { "jpeg", "image/jpeg"},
  347. { "jpe", "image/jpeg"},
  348. { "jpg", "image/jpeg"},
  349. { "jpgm", "video/jpm"},
  350. { "jpgv", "video/jpeg"},
  351. { "jpm", "video/jpm"},
  352. { "js", "application/x-javascript"},
  353. { "json", "application/json"},
  354. { "kar", "audio/midi"},
  355. { "karbon", "application/vnd.kde.karbon"},
  356. { "kfo", "application/vnd.kde.kformula"},
  357. { "kia", "application/vnd.kidspiration"},
  358. { "kil", "application/x-killustrator"},
  359. { "kml", "application/vnd.google-earth.kml+xml"},
  360. { "kmz", "application/vnd.google-earth.kmz"},
  361. { "kne", "application/vnd.kinar"},
  362. { "knp", "application/vnd.kinar"},
  363. { "kon", "application/vnd.kde.kontour"},
  364. { "kpr", "application/vnd.kde.kpresenter"},
  365. { "kpt", "application/vnd.kde.kpresenter"},
  366. { "ksh", "text/plain"},
  367. { "ksp", "application/vnd.kde.kspread"},
  368. { "ktr", "application/vnd.kahootz"},
  369. { "ktz", "application/vnd.kahootz"},
  370. { "kwd", "application/vnd.kde.kword"},
  371. { "kwt", "application/vnd.kde.kword"},
  372. { "latex", "application/x-latex"},
  373. { "lbd", "application/vnd.llamagraphics.life-balance.desktop"},
  374. { "lbe", "application/vnd.llamagraphics.life-balance.exchange+xml"},
  375. { "les", "application/vnd.hhe.lesson-player"},
  376. { "lha", "application/octet-stream"},
  377. { "link66", "application/vnd.route66.link66+xml"},
  378. { "list3820", "application/vnd.ibm.modcap"},
  379. { "listafp", "application/vnd.ibm.modcap"},
  380. { "list", "text/plain"},
  381. { "log", "text/plain"},
  382. { "lostxml", "application/lost+xml"},
  383. { "lrf", "application/octet-stream"},
  384. { "lrm", "application/vnd.ms-lrm"},
  385. { "lsf", "video/x-la-asf"},
  386. { "lsx", "video/x-la-asf"},
  387. { "ltf", "application/vnd.frogans.ltf"},
  388. { "lvp", "audio/vnd.lucent.voice"},
  389. { "lwp", "application/vnd.lotus-wordpro"},
  390. { "lzh", "application/octet-stream"},
  391. { "m13", "application/x-msmediaview"},
  392. { "m14", "application/x-msmediaview"},
  393. { "m1v", "video/mpeg"},
  394. { "m2a", "audio/mpeg"},
  395. { "m2v", "video/mpeg"},
  396. { "m3a", "audio/mpeg"},
  397. { "m3u", "audio/x-mpegurl"},
  398. { "m4u", "video/vnd.mpegurl"},
  399. { "m4v", "video/x-m4v"},
  400. { "ma", "application/mathematica"},
  401. { "mag", "application/vnd.ecowin.chart"},
  402. { "maker", "application/vnd.framemaker"},
  403. { "man", "text/troff"},
  404. { "mathml", "application/mathml+xml"},
  405. { "mb", "application/mathematica"},
  406. { "mbk", "application/vnd.mobius.mbk"},
  407. { "mbox", "application/mbox"},
  408. { "mc1", "application/vnd.medcalcdata"},
  409. { "mcd", "application/vnd.mcd"},
  410. { "mcurl", "text/vnd.curl.mcurl"},
  411. { "mdb", "application/x-msaccess"},
  412. { "mdi", "image/vnd.ms-modi"},
  413. { "mesh", "model/mesh"},
  414. { "me", "text/troff"},
  415. { "mfm", "application/vnd.mfmp"},
  416. { "mgz", "application/vnd.proteus.magazine"},
  417. { "mht", "message/rfc822"},
  418. { "mhtml", "message/rfc822"},
  419. { "mid", "audio/midi"},
  420. { "midi", "audio/midi"},
  421. { "mif", "application/vnd.mif"},
  422. { "mime", "message/rfc822"},
  423. { "mj2", "video/mj2"},
  424. { "mjp2", "video/mj2"},
  425. { "mlp", "application/vnd.dolby.mlp"},
  426. { "mmd", "application/vnd.chipnuts.karaoke-mmd"},
  427. { "mmf", "application/vnd.smaf"},
  428. { "mmr", "image/vnd.fujixerox.edmics-mmr"},
  429. { "mny", "application/x-msmoney"},
  430. { "mobi", "application/x-mobipocket-ebook"},
  431. { "movie", "video/x-sgi-movie"},
  432. { "mov", "video/quicktime"},
  433. { "mp2a", "audio/mpeg"},
  434. { "mp2", "video/mpeg"},
  435. { "mp3", "audio/mpeg"},
  436. { "mp4a", "audio/mp4"},
  437. { "mp4s", "application/mp4"},
  438. { "mp4", "video/mp4"},
  439. { "mp4v", "video/mp4"},
  440. { "mpa", "video/mpeg"},
  441. { "mpc", "application/vnd.mophun.certificate"},
  442. { "mpeg", "video/mpeg"},
  443. { "mpe", "video/mpeg"},
  444. { "mpg4", "video/mp4"},
  445. { "mpga", "audio/mpeg"},
  446. { "mpg", "video/mpeg"},
  447. { "mpkg", "application/vnd.apple.installer+xml"},
  448. { "mpm", "application/vnd.blueice.multipass"},
  449. { "mpn", "application/vnd.mophun.application"},
  450. { "mpp", "application/vnd.ms-project"},
  451. { "mpt", "application/vnd.ms-project"},
  452. { "mpv2", "video/mpeg"},
  453. { "mpy", "application/vnd.ibm.minipay"},
  454. { "mqy", "application/vnd.mobius.mqy"},
  455. { "mrc", "application/marc"},
  456. { "mscml", "application/mediaservercontrol+xml"},
  457. { "mseed", "application/vnd.fdsn.mseed"},
  458. { "mseq", "application/vnd.mseq"},
  459. { "msf", "application/vnd.epson.msf"},
  460. { "msh", "model/mesh"},
  461. { "msi", "application/x-msdownload"},
  462. { "ms", "text/troff"},
  463. { "msty", "application/vnd.muvee.style"},
  464. { "mts", "model/vnd.mts"},
  465. { "mus", "application/vnd.musician"},
  466. { "musicxml", "application/vnd.recordare.musicxml+xml"},
  467. { "mvb", "application/x-msmediaview"},
  468. { "mxf", "application/mxf"},
  469. { "mxl", "application/vnd.recordare.musicxml"},
  470. { "mxml", "application/xv+xml"},
  471. { "mxs", "application/vnd.triscape.mxs"},
  472. { "mxu", "video/vnd.mpegurl"},
  473. { "nb", "application/mathematica"},
  474. { "nc", "application/x-netcdf"},
  475. { "ncx", "application/x-dtbncx+xml"},
  476. { "n-gage", "application/vnd.nokia.n-gage.symbian.install"},
  477. { "ngdat", "application/vnd.nokia.n-gage.data"},
  478. { "nlu", "application/vnd.neurolanguage.nlu"},
  479. { "nml", "application/vnd.enliven"},
  480. { "nnd", "application/vnd.noblenet-directory"},
  481. { "nns", "application/vnd.noblenet-sealer"},
  482. { "nnw", "application/vnd.noblenet-web"},
  483. { "npx", "image/vnd.net-fpx"},
  484. { "nsf", "application/vnd.lotus-notes"},
  485. { "nws", "message/rfc822"},
  486. { "oa2", "application/vnd.fujitsu.oasys2"},
  487. { "oa3", "application/vnd.fujitsu.oasys3"},
  488. { "o", "application/octet-stream"},
  489. { "oas", "application/vnd.fujitsu.oasys"},
  490. { "obd", "application/x-msbinder"},
  491. { "obj", "application/octet-stream"},
  492. { "oda", "application/oda"},
  493. { "odb", "application/vnd.oasis.opendocument.database"},
  494. { "odc", "application/vnd.oasis.opendocument.chart"},
  495. { "odf", "application/vnd.oasis.opendocument.formula"},
  496. { "odft", "application/vnd.oasis.opendocument.formula-template"},
  497. { "odg", "application/vnd.oasis.opendocument.graphics"},
  498. { "odi", "application/vnd.oasis.opendocument.image"},
  499. { "odp", "application/vnd.oasis.opendocument.presentation"},
  500. { "ods", "application/vnd.oasis.opendocument.spreadsheet"},
  501. { "odt", "application/vnd.oasis.opendocument.text"},
  502. { "oga", "audio/ogg"},
  503. { "ogg", "audio/ogg"},
  504. { "ogv", "video/ogg"},
  505. { "ogx", "application/ogg"},
  506. { "onepkg", "application/onenote"},
  507. { "onetmp", "application/onenote"},
  508. { "onetoc2", "application/onenote"},
  509. { "onetoc", "application/onenote"},
  510. { "opf", "application/oebps-package+xml"},
  511. { "oprc", "application/vnd.palm"},
  512. { "org", "application/vnd.lotus-organizer"},
  513. { "osf", "application/vnd.yamaha.openscoreformat"},
  514. { "osfpvg", "application/vnd.yamaha.openscoreformat.osfpvg+xml"},
  515. { "otc", "application/vnd.oasis.opendocument.chart-template"},
  516. { "otf", "application/x-font-otf"},
  517. { "otg", "application/vnd.oasis.opendocument.graphics-template"},
  518. { "oth", "application/vnd.oasis.opendocument.text-web"},
  519. { "oti", "application/vnd.oasis.opendocument.image-template"},
  520. { "otm", "application/vnd.oasis.opendocument.text-master"},
  521. { "otp", "application/vnd.oasis.opendocument.presentation-template"},
  522. { "ots", "application/vnd.oasis.opendocument.spreadsheet-template"},
  523. { "ott", "application/vnd.oasis.opendocument.text-template"},
  524. { "oxt", "application/vnd.openofficeorg.extension"},
  525. { "p10", "application/pkcs10"},
  526. { "p12", "application/x-pkcs12"},
  527. { "p7b", "application/x-pkcs7-certificates"},
  528. { "p7c", "application/x-pkcs7-mime"},
  529. { "p7m", "application/x-pkcs7-mime"},
  530. { "p7r", "application/x-pkcs7-certreqresp"},
  531. { "p7s", "application/x-pkcs7-signature"},
  532. { "pas", "text/x-pascal"},
  533. { "pbd", "application/vnd.powerbuilder6"},
  534. { "pbm", "image/x-portable-bitmap"},
  535. { "pcf", "application/x-font-pcf"},
  536. { "pcl", "application/vnd.hp-pcl"},
  537. { "pclxl", "application/vnd.hp-pclxl"},
  538. { "pct", "image/x-pict"},
  539. { "pcurl", "application/vnd.curl.pcurl"},
  540. { "pcx", "image/x-pcx"},
  541. { "pdb", "application/vnd.palm"},
  542. { "pdf", "application/pdf"},
  543. { "pfa", "application/x-font-type1"},
  544. { "pfb", "application/x-font-type1"},
  545. { "pfm", "application/x-font-type1"},
  546. { "pfr", "application/font-tdpfr"},
  547. { "pfx", "application/x-pkcs12"},
  548. { "pgm", "image/x-portable-graymap"},
  549. { "pgn", "application/x-chess-pgn"},
  550. { "pgp", "application/pgp-encrypted"},
  551. { "pic", "image/x-pict"},
  552. { "pkg", "application/octet-stream"},
  553. { "pki", "application/pkixcmp"},
  554. { "pkipath", "application/pkix-pkipath"},
  555. { "pko", "application/ynd.ms-pkipko"},
  556. { "plb", "application/vnd.3gpp.pic-bw-large"},
  557. { "plc", "application/vnd.mobius.plc"},
  558. { "plf", "application/vnd.pocketlearn"},
  559. { "pls", "application/pls+xml"},
  560. { "pl", "text/plain"},
  561. { "pma", "application/x-perfmon"},
  562. { "pmc", "application/x-perfmon"},
  563. { "pml", "application/x-perfmon"},
  564. { "pmr", "application/x-perfmon"},
  565. { "pmw", "application/x-perfmon"},
  566. { "png", "image/png"},
  567. { "pnm", "image/x-portable-anymap"},
  568. { "portpkg", "application/vnd.macports.portpkg"},
  569. { "pot,", "application/vnd.ms-powerpoint"},
  570. { "pot", "application/vnd.ms-powerpoint"},
  571. { "potm", "application/vnd.ms-powerpoint.template.macroenabled.12"},
  572. { "potx", "application/vnd.openxmlformats-officedocument.presentationml.template"},
  573. { "ppa", "application/vnd.ms-powerpoint"},
  574. { "ppam", "application/vnd.ms-powerpoint.addin.macroenabled.12"},
  575. { "ppd", "application/vnd.cups-ppd"},
  576. { "ppm", "image/x-portable-pixmap"},
  577. { "pps", "application/vnd.ms-powerpoint"},
  578. { "ppsm", "application/vnd.ms-powerpoint.slideshow.macroenabled.12"},
  579. { "ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"},
  580. { "ppt", "application/vnd.ms-powerpoint"},
  581. { "pptm", "application/vnd.ms-powerpoint.presentation.macroenabled.12"},
  582. { "pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
  583. { "pqa", "application/vnd.palm"},
  584. { "prc", "application/x-mobipocket-ebook"},
  585. { "pre", "application/vnd.lotus-freelance"},
  586. { "prf", "application/pics-rules"},
  587. { "ps", "application/postscript"},
  588. { "psb", "application/vnd.3gpp.pic-bw-small"},
  589. { "psd", "image/vnd.adobe.photoshop"},
  590. { "psf", "application/x-font-linux-psf"},
  591. { "p", "text/x-pascal"},
  592. { "ptid", "application/vnd.pvi.ptid1"},
  593. { "pub", "application/x-mspublisher"},
  594. { "pvb", "application/vnd.3gpp.pic-bw-var"},
  595. { "pwn", "application/vnd.3m.post-it-notes"},
  596. { "pwz", "application/vnd.ms-powerpoint"},
  597. { "pya", "audio/vnd.ms-playready.media.pya"},
  598. { "pyc", "application/x-python-code"},
  599. { "pyo", "application/x-python-code"},
  600. { "py", "text/x-python"},
  601. { "pyv", "video/vnd.ms-playready.media.pyv"},
  602. { "qam", "application/vnd.epson.quickanime"},
  603. { "qbo", "application/vnd.intu.qbo"},
  604. { "qfx", "application/vnd.intu.qfx"},
  605. { "qps", "application/vnd.publishare-delta-tree"},
  606. { "qt", "video/quicktime"},
  607. { "qwd", "application/vnd.quark.quarkxpress"},
  608. { "qwt", "application/vnd.quark.quarkxpress"},
  609. { "qxb", "application/vnd.quark.quarkxpress"},
  610. { "qxd", "application/vnd.quark.quarkxpress"},
  611. { "qxl", "application/vnd.quark.quarkxpress"},
  612. { "qxt", "application/vnd.quark.quarkxpress"},
  613. { "ra", "audio/x-pn-realaudio"},
  614. { "ram", "audio/x-pn-realaudio"},
  615. { "rar", "application/x-rar-compressed"},
  616. { "ras", "image/x-cmu-raster"},
  617. { "rcprofile", "application/vnd.ipunplugged.rcprofile"},
  618. { "rdf", "application/rdf+xml"},
  619. { "rdz", "application/vnd.data-vision.rdz"},
  620. { "rep", "application/vnd.businessobjects"},
  621. { "res", "application/x-dtbresource+xml"},
  622. { "rgb", "image/x-rgb"},
  623. { "rif", "application/reginfo+xml"},
  624. { "rl", "application/resource-lists+xml"},
  625. { "rlc", "image/vnd.fujixerox.edmics-rlc"},
  626. { "rld", "application/resource-lists-diff+xml"},
  627. { "rm", "application/vnd.rn-realmedia"},
  628. { "rmi", "audio/midi"},
  629. { "rmp", "audio/x-pn-realaudio-plugin"},
  630. { "rms", "application/vnd.jcp.javame.midlet-rms"},
  631. { "rnc", "application/relax-ng-compact-syntax"},
  632. { "roff", "text/troff"},
  633. { "rpm", "application/x-rpm"},
  634. { "rpss", "application/vnd.nokia.radio-presets"},
  635. { "rpst", "application/vnd.nokia.radio-preset"},
  636. { "rq", "application/sparql-query"},
  637. { "rs", "application/rls-services+xml"},
  638. { "rsd", "application/rsd+xml"},
  639. { "rss", "application/rss+xml"},
  640. { "rtf", "application/rtf"},
  641. { "rtx", "text/richtext"},
  642. { "saf", "application/vnd.yamaha.smaf-audio"},
  643. { "sbml", "application/sbml+xml"},
  644. { "sc", "application/vnd.ibm.secure-container"},
  645. { "scd", "application/x-msschedule"},
  646. { "scm", "application/vnd.lotus-screencam"},
  647. { "scq", "application/scvp-cv-request"},
  648. { "scs", "application/scvp-cv-response"},
  649. { "sct", "text/scriptlet"},
  650. { "scurl", "text/vnd.curl.scurl"},
  651. { "sda", "application/vnd.stardivision.draw"},
  652. { "sdc", "application/vnd.stardivision.calc"},
  653. { "sdd", "application/vnd.stardivision.impress"},
  654. { "sdkd", "application/vnd.solent.sdkm+xml"},
  655. { "sdkm", "application/vnd.solent.sdkm+xml"},
  656. { "sdp", "application/sdp"},
  657. { "sdw", "application/vnd.stardivision.writer"},
  658. { "see", "application/vnd.seemail"},
  659. { "seed", "application/vnd.fdsn.seed"},
  660. { "sema", "application/vnd.sema"},
  661. { "semd", "application/vnd.semd"},
  662. { "semf", "application/vnd.semf"},
  663. { "ser", "application/java-serialized-object"},
  664. { "setpay", "application/set-payment-initiation"},
  665. { "setreg", "application/set-registration-initiation"},
  666. { "sfd-hdstx", "application/vnd.hydrostatix.sof-data"},
  667. { "sfs", "application/vnd.spotfire.sfs"},
  668. { "sgl", "application/vnd.stardivision.writer-global"},
  669. { "sgml", "text/sgml"},
  670. { "sgm", "text/sgml"},
  671. { "sh", "application/x-sh"},
  672. { "shar", "application/x-shar"},
  673. { "shf", "application/shf+xml"},
  674. { "sic", "application/vnd.wap.sic"},
  675. { "sig", "application/pgp-signature"},
  676. { "silo", "model/mesh"},
  677. { "sis", "application/vnd.symbian.install"},
  678. { "sisx", "application/vnd.symbian.install"},
  679. { "sit", "application/x-stuffit"},
  680. { "si", "text/vnd.wap.si"},
  681. { "sitx", "application/x-stuffitx"},
  682. { "skd", "application/vnd.koan"},
  683. { "skm", "application/vnd.koan"},
  684. { "skp", "application/vnd.koan"},
  685. { "skt", "application/vnd.koan"},
  686. { "slc", "application/vnd.wap.slc"},
  687. { "sldm", "application/vnd.ms-powerpoint.slide.macroenabled.12"},
  688. { "sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"},
  689. { "slt", "application/vnd.epson.salt"},
  690. { "sl", "text/vnd.wap.sl"},
  691. { "smf", "application/vnd.stardivision.math"},
  692. { "smi", "application/smil+xml"},
  693. { "smil", "application/smil+xml"},
  694. { "snd", "audio/basic"},
  695. { "snf", "application/x-font-snf"},
  696. { "so", "application/octet-stream"},
  697. { "spc", "application/x-pkcs7-certificates"},
  698. { "spf", "application/vnd.yamaha.smaf-phrase"},
  699. { "spl", "application/x-futuresplash"},
  700. { "spot", "text/vnd.in3d.spot"},
  701. { "spp", "application/scvp-vp-response"},
  702. { "spq", "application/scvp-vp-request"},
  703. { "spx", "audio/ogg"},
  704. { "src", "application/x-wais-source"},
  705. { "srx", "application/sparql-results+xml"},
  706. { "sse", "application/vnd.kodak-descriptor"},
  707. { "ssf", "application/vnd.epson.ssf"},
  708. { "ssml", "application/ssml+xml"},
  709. { "sst", "application/vnd.ms-pkicertstore"},
  710. { "stc", "application/vnd.sun.xml.calc.template"},
  711. { "std", "application/vnd.sun.xml.draw.template"},
  712. { "s", "text/x-asm"},
  713. { "stf", "application/vnd.wt.stf"},
  714. { "sti", "application/vnd.sun.xml.impress.template"},
  715. { "stk", "application/hyperstudio"},
  716. { "stl", "application/vnd.ms-pki.stl"},
  717. { "stm", "text/html"},
  718. { "str", "application/vnd.pg.format"},
  719. { "stw", "application/vnd.sun.xml.writer.template"},
  720. { "sus", "application/vnd.sus-calendar"},
  721. { "susp", "application/vnd.sus-calendar"},
  722. { "sv4cpio", "application/x-sv4cpio"},
  723. { "sv4crc", "application/x-sv4crc"},
  724. { "svd", "application/vnd.svd"},
  725. { "svg", "image/svg+xml"},
  726. { "svgz", "image/svg+xml"},
  727. { "swa", "application/x-director"},
  728. { "swf", "application/x-shockwave-flash"},
  729. { "swi", "application/vnd.arastra.swi"},
  730. { "sxc", "application/vnd.sun.xml.calc"},
  731. { "sxd", "application/vnd.sun.xml.draw"},
  732. { "sxg", "application/vnd.sun.xml.writer.global"},
  733. { "sxi", "application/vnd.sun.xml.impress"},
  734. { "sxm", "application/vnd.sun.xml.math"},
  735. { "sxw", "application/vnd.sun.xml.writer"},
  736. { "tao", "application/vnd.tao.intent-module-archive"},
  737. { "t", "application/x-troff"},
  738. { "tar", "application/x-tar"},
  739. { "tcap", "application/vnd.3gpp2.tcap"},
  740. { "tcl", "application/x-tcl"},
  741. { "teacher", "application/vnd.smart.teacher"},
  742. { "tex", "application/x-tex"},
  743. { "texi", "application/x-texinfo"},
  744. { "texinfo", "application/x-texinfo"},
  745. { "text", "text/plain"},
  746. { "tfm", "application/x-tex-tfm"},
  747. { "tgz", "application/x-gzip"},
  748. { "tiff", "image/tiff"},
  749. { "tif", "image/tiff"},
  750. { "tmo", "application/vnd.tmobile-livetv"},
  751. { "torrent", "application/x-bittorrent"},
  752. { "tpl", "application/vnd.groove-tool-template"},
  753. { "tpt", "application/vnd.trid.tpt"},
  754. { "tra", "application/vnd.trueapp"},
  755. { "trm", "application/x-msterminal"},
  756. { "tr", "text/troff"},
  757. { "tsv", "text/tab-separated-values"},
  758. { "ttc", "application/x-font-ttf"},
  759. { "ttf", "application/x-font-ttf"},
  760. { "twd", "application/vnd.simtech-mindmapper"},
  761. { "twds", "application/vnd.simtech-mindmapper"},
  762. { "txd", "application/vnd.genomatix.tuxedo"},
  763. { "txf", "application/vnd.mobius.txf"},
  764. { "txt", "text/plain"},
  765. { "u32", "application/x-authorware-bin"},
  766. { "udeb", "application/x-debian-package"},
  767. { "ufd", "application/vnd.ufdl"},
  768. { "ufdl", "application/vnd.ufdl"},
  769. { "uls", "text/iuls"},
  770. { "umj", "application/vnd.umajin"},
  771. { "unityweb", "application/vnd.unity"},
  772. { "uoml", "application/vnd.uoml+xml"},
  773. { "uris", "text/uri-list"},
  774. { "uri", "text/uri-list"},
  775. { "urls", "text/uri-list"},
  776. { "ustar", "application/x-ustar"},
  777. { "utz", "application/vnd.uiq.theme"},
  778. { "uu", "text/x-uuencode"},
  779. { "vcd", "application/x-cdlink"},
  780. { "vcf", "text/x-vcard"},
  781. { "vcg", "application/vnd.groove-vcard"},
  782. { "vcs", "text/x-vcalendar"},
  783. { "vcx", "application/vnd.vcx"},
  784. { "vis", "application/vnd.visionary"},
  785. { "viv", "video/vnd.vivo"},
  786. { "vor", "application/vnd.stardivision.writer"},
  787. { "vox", "application/x-authorware-bin"},
  788. { "vrml", "x-world/x-vrml"},
  789. { "vsd", "application/vnd.visio"},
  790. { "vsf", "application/vnd.vsf"},
  791. { "vss", "application/vnd.visio"},
  792. { "vst", "application/vnd.visio"},
  793. { "vsw", "application/vnd.visio"},
  794. { "vtu", "model/vnd.vtu"},
  795. { "vxml", "application/voicexml+xml"},
  796. { "w3d", "application/x-director"},
  797. { "wad", "application/x-doom"},
  798. { "wav", "audio/x-wav"},
  799. { "wax", "audio/x-ms-wax"},
  800. { "wbmp", "image/vnd.wap.wbmp"},
  801. { "wbs", "application/vnd.criticaltools.wbs+xml"},
  802. { "wbxml", "application/vnd.wap.wbxml"},
  803. { "wcm", "application/vnd.ms-works"},
  804. { "wdb", "application/vnd.ms-works"},
  805. { "wiz", "application/msword"},
  806. { "wks", "application/vnd.ms-works"},
  807. { "wma", "audio/x-ms-wma"},
  808. { "wmd", "application/x-ms-wmd"},
  809. { "wmf", "application/x-msmetafile"},
  810. { "wmlc", "application/vnd.wap.wmlc"},
  811. { "wmlsc", "application/vnd.wap.wmlscriptc"},
  812. { "wmls", "text/vnd.wap.wmlscript"},
  813. { "wml", "text/vnd.wap.wml"},
  814. { "wm", "video/x-ms-wm"},
  815. { "wmv", "video/x-ms-wmv"},
  816. { "wmx", "video/x-ms-wmx"},
  817. { "wmz", "application/x-ms-wmz"},
  818. { "wpd", "application/vnd.wordperfect"},
  819. { "wpl", "application/vnd.ms-wpl"},
  820. { "wps", "application/vnd.ms-works"},
  821. { "wqd", "application/vnd.wqd"},
  822. { "wri", "application/x-mswrite"},
  823. { "wrl", "x-world/x-vrml"},
  824. { "wrz", "x-world/x-vrml"},
  825. { "wsdl", "application/wsdl+xml"},
  826. { "wspolicy", "application/wspolicy+xml"},
  827. { "wtb", "application/vnd.webturbo"},
  828. { "wvx", "video/x-ms-wvx"},
  829. { "x32", "application/x-authorware-bin"},
  830. { "x3d", "application/vnd.hzn-3d-crossword"},
  831. { "xaf", "x-world/x-vrml"},
  832. { "xap", "application/x-silverlight-app"},
  833. { "xar", "application/vnd.xara"},
  834. { "xbap", "application/x-ms-xbap"},
  835. { "xbd", "application/vnd.fujixerox.docuworks.binder"},
  836. { "xbm", "image/x-xbitmap"},
  837. { "xdm", "application/vnd.syncml.dm+xml"},
  838. { "xdp", "application/vnd.adobe.xdp+xml"},
  839. { "xdw", "application/vnd.fujixerox.docuworks"},
  840. { "xenc", "application/xenc+xml"},
  841. { "xer", "application/patch-ops-error+xml"},
  842. { "xfdf", "application/vnd.adobe.xfdf"},
  843. { "xfdl", "application/vnd.xfdl"},
  844. { "xht", "application/xhtml+xml"},
  845. { "xhtml", "application/xhtml+xml"},
  846. { "xhvml", "application/xv+xml"},
  847. { "xif", "image/vnd.xiff"},
  848. { "xla", "application/vnd.ms-excel"},
  849. { "xlam", "application/vnd.ms-excel.addin.macroenabled.12"},
  850. { "xlb", "application/vnd.ms-excel"},
  851. { "xlc", "application/vnd.ms-excel"},
  852. { "xlm", "application/vnd.ms-excel"},
  853. { "xls", "application/vnd.ms-excel"},
  854. { "xlsb", "application/vnd.ms-excel.sheet.binary.macroenabled.12"},
  855. { "xlsm", "application/vnd.ms-excel.sheet.macroenabled.12"},
  856. { "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
  857. { "xlt", "application/vnd.ms-excel"},
  858. { "xltm", "application/vnd.ms-excel.template.macroenabled.12"},
  859. { "xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"},
  860. { "xlw", "application/vnd.ms-excel"},
  861. { "xml", "application/xml"},
  862. { "xo", "application/vnd.olpc-sugar"},
  863. { "xof", "x-world/x-vrml"},
  864. { "xop", "application/xop+xml"},
  865. { "xpdl", "application/xml"},
  866. { "xpi", "application/x-xpinstall"},
  867. { "xpm", "image/x-xpixmap"},
  868. { "xpr", "application/vnd.is-xpr"},
  869. { "xps", "application/vnd.ms-xpsdocument"},
  870. { "xpw", "application/vnd.intercon.formnet"},
  871. { "xpx", "application/vnd.intercon.formnet"},
  872. { "xsl", "application/xml"},
  873. { "xslt", "application/xslt+xml"},
  874. { "xsm", "application/vnd.syncml+xml"},
  875. { "xspf", "application/xspf+xml"},
  876. { "xul", "application/vnd.mozilla.xul+xml"},
  877. { "xvm", "application/xv+xml"},
  878. { "xvml", "application/xv+xml"},
  879. { "xwd", "image/x-xwindowdump"},
  880. { "xyz", "chemical/x-xyz"},
  881. { "z", "application/x-compress"},
  882. { "zaz", "application/vnd.zzazz.deck+xml"},
  883. { "zip", "application/zip"},
  884. { "zir", "application/vnd.zul"},
  885. { "zirz", "application/vnd.zul"},
  886. { "zmm", "application/vnd.handheld-entertainment+xml"}
  887. };
  888. /**
  889. * Table for MIME type replacements.
  890. *
  891. * Table format: wrong type, correct type
  892. */
  893. private static final String[][] MIME_TYPE_REPLACEMENT_MAP = new String[][] {
  894. {"image/jpg", "image/jpeg"},
  895. {"image/pjpeg", "image/jpeg"}, // see issue 1712
  896. {"application/x-zip-compressed", "application/zip"} // see issue 3791
  897. };
  898. /**
  899. * Table for character set fall-back.
  900. *
  901. * Table format: unsupported charset (regular expression), fall-back charset
  902. */
  903. private static final String[][] CHARSET_FALLBACK_MAP = new String[][] {
  904. // Some Android versions don't support KOI8-U
  905. {"koi8-u", "koi8-r"},
  906. {"iso-2022-jp-[\\d]+", "iso-2022-jp"},
  907. // Default fall-back is US-ASCII
  908. {".*", "US-ASCII"}
  909. };
  910. public static String unfold(String s) {
  911. if (s == null) {
  912. return null;
  913. }
  914. return s.replaceAll("\r|\n", "");
  915. }
  916. public static String decode(String s) {
  917. return decode(s, null);
  918. }
  919. public static String decode(String s, Message message) {
  920. if (s == null) {
  921. return null;
  922. }
  923. return DecoderUtil.decodeEncodedWords(s, message);
  924. }
  925. public static String unfoldAndDecode(String s) {
  926. return unfoldAndDecode(s, null);
  927. }
  928. public static String unfoldAndDecode(String s, Message message) {
  929. return decode(unfold(s), message);
  930. }
  931. // TODO implement proper foldAndEncode
  932. public static String foldAndEncode(String s) {
  933. return s;
  934. }
  935. /**
  936. * Returns the named parameter of a header field. If name is null the first
  937. * parameter is returned, or if there are no additional parameters in the
  938. * field the entire field is returned. Otherwise the named parameter is
  939. * searched for in a case insensitive fashion and returned. If the parameter
  940. * cannot be found the method returns null.
  941. *
  942. * @param header
  943. * @param name
  944. * @return
  945. */
  946. public static String getHeaderParameter(String header, String name) {
  947. if (header == null) {
  948. return null;
  949. }
  950. header = header.replaceAll("\r|\n", "");
  951. String[] parts = header.split(";");
  952. if (name == null && parts.length > 0) {
  953. return parts[0].trim();
  954. }
  955. for (String part : parts) {
  956. if (part.trim().toLowerCase(Locale.US).startsWith(name.toLowerCase(Locale.US))) {
  957. String[] partParts = part.split("=", 2);
  958. if (partParts.length == 2) {
  959. String parameter = partParts[1].trim();
  960. int len = parameter.length();
  961. if (len >= 2 && parameter.startsWith("\"") && parameter.endsWith("\"")) {
  962. return parameter.substring(1, len - 1);
  963. } else {
  964. return parameter;
  965. }
  966. }
  967. }
  968. }
  969. return null;
  970. }
  971. public static Part findFirstPartByMimeType(Part part, String mimeType)
  972. throws MessagingException {
  973. if (part.getBody() instanceof Multipart) {
  974. Multipart multipart = (Multipart)part.getBody();
  975. for (int i = 0, count = multipart.getCount(); i < count; i++) {
  976. BodyPart bodyPart = multipart.getBodyPart(i);
  977. Part ret = findFirstPartByMimeType(bodyPart, mimeType);
  978. if (ret != null) {
  979. return ret;
  980. }
  981. }
  982. } else if (part.getMimeType().equalsIgnoreCase(mimeType)) {
  983. return part;
  984. }
  985. return null;
  986. }
  987. public static Part findPartByContentId(Part part, String contentId) throws Exception {
  988. if (part.getBody() instanceof Multipart) {
  989. Multipart multipart = (Multipart)part.getBody();
  990. for (int i = 0, count = multipart.getCount(); i < count; i++) {
  991. BodyPart bodyPart = multipart.getBodyPart(i);
  992. Part ret = findPartByContentId(bodyPart, contentId);
  993. if (ret != null) {
  994. return ret;
  995. }
  996. }
  997. }
  998. String[] header = part.getHeader(MimeHeader.HEADER_CONTENT_ID);
  999. if (header != null) {
  1000. for (String s : header) {
  1001. if (s.equals(contentId)) {
  1002. return part;
  1003. }
  1004. }
  1005. }
  1006. return null;
  1007. }
  1008. /**
  1009. * Reads the Part's body and returns a String based on any charset conversion that needed
  1010. * to be done. Note, this <b>does not</b> return a text representation of HTML.
  1011. * @param part The part containing a body
  1012. * @return a String containing the converted text in the body, or null if there was no text
  1013. * or an error during conversion.
  1014. */
  1015. public static String getTextFromPart(Part part) {
  1016. try {
  1017. if ((part != null) && (part.getBody() != null)) {
  1018. final Body body = part.getBody();
  1019. if (body instanceof TextBody) {
  1020. return ((TextBody)body).getText();
  1021. }
  1022. final String mimeType = part.getMimeType();
  1023. if ((mimeType != null) && MimeUtility.mimeTypeMatches(mimeType, "text/*")) {
  1024. /*
  1025. * We've got a text part, so let's see if it needs to be processed further.
  1026. */
  1027. String charset = getHeaderParameter(part.getContentType(), "charset");
  1028. /*
  1029. * determine the charset from HTML message.
  1030. */
  1031. if (mimeType.equalsIgnoreCase("text/html") && charset == null) {
  1032. InputStream in = part.getBody().getInputStream();
  1033. try {
  1034. byte[] buf = new byte[256];
  1035. in.read(buf, 0, buf.length);
  1036. String str = new String(buf, "US-ASCII");
  1037. if (str.length() == 0) {
  1038. return "";
  1039. }
  1040. Pattern p = Pattern.compile("<meta http-equiv=\"?Content-Type\"? content=\"text/html; charset=(.+?)\">", Pattern.CASE_INSENSITIVE);
  1041. Matcher m = p.matcher(str);
  1042. if (m.find()) {
  1043. charset = m.group(1);
  1044. }
  1045. } finally {
  1046. try {
  1047. if (in instanceof BinaryTempFileBodyInputStream) {
  1048. /*
  1049. * If this is a BinaryTempFileBodyInputStream, calling close()
  1050. * will delete the file. But we can't let that happen because
  1051. * the file needs to be opened again by the code a few lines
  1052. * down.
  1053. */
  1054. ((BinaryTempFileBodyInputStream) in).closeWithoutDeleting();
  1055. } else {
  1056. in.close();
  1057. }
  1058. } catch (Exception e) { /* ignore */ }
  1059. }
  1060. }
  1061. charset = fixupCharset(charset, getMessageFromPart(part));
  1062. /*
  1063. * Now we read the part into a buffer for further processing. Because
  1064. * the stream is now wrapped we'll remove any transfer encoding at this point.
  1065. */
  1066. InputStream in = part.getBody().getInputStream();
  1067. try {
  1068. String text = readToString(in, charset);
  1069. // Replace the body with a TextBody that already contains the decoded text
  1070. part.setBody(new TextBody(text));
  1071. return text;
  1072. } finally {
  1073. try {
  1074. /*
  1075. * This time we don't care if it's a BinaryTempFileBodyInputStream. We
  1076. * replaced the body with a TextBody instance and hence don't need the
  1077. * file anymore.
  1078. */
  1079. in.close();
  1080. } catch (IOException e) { /* Ignore */ }
  1081. }
  1082. }
  1083. }
  1084. } catch (OutOfMemoryError oom) {
  1085. /*
  1086. * If we are not able to process the body there's nothing we can do about it. Return
  1087. * null and let the upper layers handle the missing content.
  1088. */
  1089. Log.e(K9.LOG_TAG, "Unable to getTextFromPart " + oom.toString());
  1090. } catch (Exception e) {
  1091. /*
  1092. * If we are not able to process the body there's nothing we can do about it. Return
  1093. * null and let the upper layers handle the missing content.
  1094. */
  1095. Log.e(K9.LOG_TAG, "Unable to getTextFromPart", e);
  1096. }
  1097. return null;
  1098. }
  1099. /**
  1100. * Returns true if the given mimeType matches the matchAgainst specification.
  1101. * @param mimeType A MIME type to check.
  1102. * @param matchAgainst A MIME type to check against. May include wildcards such as image/* or
  1103. * * /*.
  1104. * @return
  1105. */
  1106. public static boolean mimeTypeMatches(String mimeType, String matchAgainst) {
  1107. Pattern p = Pattern.compile(matchAgainst.replaceAll("\\*", "\\.\\*"), Pattern.CASE_INSENSITIVE);
  1108. return p.matcher(mimeType).matches();
  1109. }
  1110. /**
  1111. * Returns true if the given mimeType matches any of the matchAgainst specifications.
  1112. * @param mimeType A MIME type to check.
  1113. * @param matchAgainst An array of MIME types to check against. May include wildcards such
  1114. * as image/* or * /*.
  1115. * @return
  1116. */
  1117. public static boolean mimeTypeMatches(String mimeType, String[] matchAgainst) {
  1118. for (String matchType : matchAgainst) {
  1119. if (mimeTypeMatches(mimeType, matchType)) {
  1120. return true;
  1121. }
  1122. }
  1123. return false;
  1124. }
  1125. /**
  1126. * Removes any content transfer encoding from the stream and returns a Body.
  1127. */
  1128. public static Body decodeBody(InputStream in, String contentTransferEncoding)
  1129. throws IOException {
  1130. /*
  1131. * We'll remove any transfer encoding by wrapping the stream.
  1132. */
  1133. if (contentTransferEncoding != null) {
  1134. contentTransferEncoding =
  1135. MimeUtility.getHeaderParameter(contentTransferEncoding, null);
  1136. if ("quoted-printable".equalsIgnoreCase(contentTransferEncoding)) {
  1137. in = new QuotedPrintableInputStream(in);
  1138. } else if ("base64".equalsIgnoreCase(contentTransferEncoding)) {
  1139. in = new Base64InputStream(in);
  1140. }
  1141. }
  1142. BinaryTempFileBody tempBody = new BinaryTempFileBody();
  1143. OutputStream out = tempBody.getOutputStream();
  1144. try {
  1145. IOUtils.copy(in, out);
  1146. } finally {
  1147. out.close();
  1148. }
  1149. return tempBody;
  1150. }
  1151. /**
  1152. * Empty base class for the class hierarchy used by
  1153. * {@link MimeUtility#extractTextAndAttachments(Context, Message)}.
  1154. *
  1155. * @see Text
  1156. * @see Html
  1157. * @see MessageHeader
  1158. * @see Alternative
  1159. */
  1160. static abstract class Viewable { /* empty */ }
  1161. /**
  1162. * Class representing textual parts of a message that aren't marked as attachments.
  1163. *
  1164. * @see MimeUtility#isPartTextualBody(Part)
  1165. */
  1166. static abstract class Textual extends Viewable {
  1167. private Part mPart;
  1168. public Textual(Part part) {
  1169. mPart = part;
  1170. }
  1171. public Part getPart() {
  1172. return mPart;
  1173. }
  1174. }
  1175. /**
  1176. * Class representing a {@code text/plain} part of a message.
  1177. */
  1178. static class Text extends Textual {
  1179. public Text(Part part) {
  1180. super(part);
  1181. }
  1182. }
  1183. /**
  1184. * Class representing a {@code text/html} part of a message.
  1185. */
  1186. static class Html extends Textual {
  1187. public Html(Part part) {
  1188. super(part);
  1189. }
  1190. }
  1191. /**
  1192. * Class representing a {@code message/rfc822} part of a message.
  1193. *
  1194. * <p>
  1195. * This is used to extract basic header information when the message contents are displayed
  1196. * inline.
  1197. * </p>
  1198. */
  1199. static class MessageHeader extends Viewable {
  1200. pri