You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lua_mime.lua 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. --[[
  2. Copyright (c) 2019, Vsevolod Stakhov <vsevolod@highsecure.ru>
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ]]--
  13. --[[[
  14. -- @module lua_mime
  15. -- This module contains helper functions to modify mime parts
  16. --]]
  17. local rspamd_util = require "rspamd_util"
  18. local rspamd_text = require "rspamd_text"
  19. local exports = {}
  20. local function newline(task)
  21. local t = task:get_newlines_type()
  22. if t == 'cr' then
  23. return '\r'
  24. elseif t == 'lf' then
  25. return '\n'
  26. end
  27. return '\r\n'
  28. end
  29. --[[[
  30. -- @function lua_mime.add_text_footer(task, html_footer, text_footer)
  31. -- Adds a footer to all text parts in a message. It returns a table with the following
  32. -- fields:
  33. -- * out: new content (body only)
  34. -- * need_rewrite_ct: boolean field that means if we must rewrite content type
  35. -- * new_ct: new content type (type => string, subtype => string)
  36. -- * new_cte: new content-transfer encoding (string)
  37. --]]
  38. exports.add_text_footer = function(task, html_footer, text_footer)
  39. local newline_s = newline(task)
  40. local res = {}
  41. local out = {}
  42. local text_parts = task:get_text_parts()
  43. if not (html_footer or text_footer) or not (text_parts and #text_parts > 0) then
  44. return false
  45. end
  46. local function do_append_footer(part, footer, is_multipart)
  47. local tp = part:get_text()
  48. local ct = 'text/plain'
  49. local cte = 'quoted-printable'
  50. if tp:is_html() then
  51. ct = 'text/html'
  52. end
  53. local encode_func = function(input)
  54. return rspamd_util.encode_qp(input, 80, task:get_newlines_type())
  55. end
  56. if part:get_cte() == '7bit' then
  57. cte = '7bit'
  58. encode_func = function(input)
  59. if type(input) == 'userdata' then
  60. return input
  61. else
  62. return rspamd_text.fromstring(input)
  63. end
  64. end
  65. end
  66. if is_multipart then
  67. out[#out + 1] = string.format('Content-Type: %s; charset=utf-8%s'..
  68. 'Content-Transfer-Encoding: %s',
  69. ct, newline_s, cte)
  70. out[#out + 1] = ''
  71. else
  72. res.new_cte = cte
  73. end
  74. local content = tostring(tp:get_content('raw_utf') or '')
  75. local double_nline = newline_s .. newline_s
  76. local nlen = #double_nline
  77. -- Hack, if part ends with 2 newline, then we append it after footer
  78. if content:sub(-(nlen), nlen + 1) == double_nline then
  79. content = string.format('%s%s',
  80. content:sub(-(#newline_s), #newline_s + 1), -- content without last newline
  81. footer)
  82. out[#out + 1] = {encode_func(content), true}
  83. out[#out + 1] = ''
  84. else
  85. content = content .. footer
  86. out[#out + 1] = {encode_func(content), true}
  87. out[#out + 1] = ''
  88. end
  89. end
  90. if html_footer or text_footer then
  91. -- We need to take extra care about content-type and cte
  92. local ct = task:get_header('Content-Type')
  93. if ct then
  94. ct = rspamd_util.parse_content_type(ct, task:get_mempool())
  95. end
  96. if ct then
  97. if ct.type and ct.type == 'text' then
  98. if ct.subtype then
  99. if html_footer and (ct.subtype == 'html' or ct.subtype == 'htm') then
  100. res.need_rewrite_ct = true
  101. elseif text_footer and ct.subtype == 'plain' then
  102. res.need_rewrite_ct = true
  103. end
  104. else
  105. if text_footer then
  106. res.need_rewrite_ct = true
  107. end
  108. end
  109. res.new_ct = ct
  110. end
  111. else
  112. if text_parts then
  113. if #text_parts == 1 then
  114. res.need_rewrite_ct = true
  115. res.new_ct = {
  116. type = 'text',
  117. subtype = 'plain'
  118. }
  119. elseif #text_parts > 1 then
  120. -- XXX: in fact, it cannot be
  121. res.new_ct = {
  122. type = 'multipart',
  123. subtype = 'mixed'
  124. }
  125. end
  126. end
  127. end
  128. end
  129. local boundaries = {}
  130. local cur_boundary
  131. for _,part in ipairs(task:get_parts()) do
  132. local boundary = part:get_boundary()
  133. if part:is_multipart() then
  134. if cur_boundary then
  135. out[#out + 1] = string.format('--%s',
  136. boundaries[#boundaries])
  137. end
  138. boundaries[#boundaries + 1] = boundary or '--XXX'
  139. cur_boundary = boundary
  140. local rh = part:get_raw_headers()
  141. if #rh > 0 then
  142. out[#out + 1] = {rh, true}
  143. end
  144. elseif part:is_message() then
  145. if boundary then
  146. if cur_boundary and boundary ~= cur_boundary then
  147. -- Need to close boundary
  148. out[#out + 1] = string.format('--%s--%s',
  149. boundaries[#boundaries], newline_s)
  150. table.remove(boundaries)
  151. cur_boundary = nil
  152. end
  153. out[#out + 1] = string.format('--%s',
  154. boundary)
  155. end
  156. out[#out + 1] = {part:get_raw_headers(), true}
  157. else
  158. local append_footer = false
  159. local skip_footer = part:is_attachment()
  160. local parent = part:get_parent()
  161. if parent then
  162. local t,st = parent:get_type()
  163. if t == 'multipart' and st == 'signed' then
  164. -- Do not modify signed parts
  165. skip_footer = true
  166. end
  167. end
  168. if text_footer and part:is_text() then
  169. local tp = part:get_text()
  170. if not tp:is_html() then
  171. append_footer = text_footer
  172. end
  173. end
  174. if html_footer and part:is_text() then
  175. local tp = part:get_text()
  176. if tp:is_html() then
  177. append_footer = html_footer
  178. end
  179. end
  180. if boundary then
  181. if cur_boundary and boundary ~= cur_boundary then
  182. -- Need to close boundary
  183. out[#out + 1] = string.format('--%s--%s',
  184. boundaries[#boundaries], newline_s)
  185. table.remove(boundaries)
  186. cur_boundary = boundary
  187. end
  188. out[#out + 1] = string.format('--%s',
  189. boundary)
  190. end
  191. if append_footer and not skip_footer then
  192. do_append_footer(part, append_footer,
  193. parent and parent:is_multipart())
  194. else
  195. out[#out + 1] = {part:get_raw_headers(), true}
  196. out[#out + 1] = {part:get_raw_content(), false}
  197. end
  198. end
  199. end
  200. -- Close remaining
  201. local b = table.remove(boundaries)
  202. while b do
  203. out[#out + 1] = string.format('--%s--', b)
  204. if #boundaries > 0 then
  205. out[#out + 1] = ''
  206. end
  207. b = table.remove(boundaries)
  208. end
  209. res.out = out
  210. return res
  211. end
  212. -- All mime extensions with corresponding content types
  213. exports.full_extensions_map = {
  214. {"323", "text/h323"},
  215. {"3g2", "video/3gpp2"},
  216. {"3gp", "video/3gpp"},
  217. {"3gp2", "video/3gpp2"},
  218. {"3gpp", "video/3gpp"},
  219. {"7z", {"application/x-7z-compressed", "application/7z"}},
  220. {"aa", "audio/audible"},
  221. {"AAC", "audio/aac"},
  222. {"aaf", "application/octet-stream"},
  223. {"aax", "audio/vnd.audible.aax"},
  224. {"ac3", "audio/ac3"},
  225. {"aca", "application/octet-stream"},
  226. {"accda", "application/msaccess.addin"},
  227. {"accdb", "application/msaccess"},
  228. {"accdc", "application/msaccess.cab"},
  229. {"accde", "application/msaccess"},
  230. {"accdr", "application/msaccess.runtime"},
  231. {"accdt", "application/msaccess"},
  232. {"accdw", "application/msaccess.webapplication"},
  233. {"accft", "application/msaccess.ftemplate"},
  234. {"acx", "application/internet-property-stream"},
  235. {"AddIn", "text/xml"},
  236. {"ade", "application/msaccess"},
  237. {"adobebridge", "application/x-bridge-url"},
  238. {"adp", "application/msaccess"},
  239. {"ADT", "audio/vnd.dlna.adts"},
  240. {"ADTS", "audio/aac"},
  241. {"afm", "application/octet-stream"},
  242. {"ai", "application/postscript"},
  243. {"aif", "audio/aiff"},
  244. {"aifc", "audio/aiff"},
  245. {"aiff", "audio/aiff"},
  246. {"air", "application/vnd.adobe.air-application-installer-package+zip"},
  247. {"amc", "application/mpeg"},
  248. {"anx", "application/annodex"},
  249. {"apk", "application/vnd.android.package-archive" },
  250. {"application", "application/x-ms-application"},
  251. {"art", "image/x-jg"},
  252. {"asa", "application/xml"},
  253. {"asax", "application/xml"},
  254. {"ascx", "application/xml"},
  255. {"asd", "application/octet-stream"},
  256. {"asf", "video/x-ms-asf"},
  257. {"ashx", "application/xml"},
  258. {"asi", "application/octet-stream"},
  259. {"asm", "text/plain"},
  260. {"asmx", "application/xml"},
  261. {"aspx", "application/xml"},
  262. {"asr", "video/x-ms-asf"},
  263. {"asx", "video/x-ms-asf"},
  264. {"atom", "application/atom+xml"},
  265. {"au", "audio/basic"},
  266. {"avi", "video/x-msvideo"},
  267. {"axa", "audio/annodex"},
  268. {"axs", "application/olescript"},
  269. {"axv", "video/annodex"},
  270. {"bas", "text/plain"},
  271. {"bcpio", "application/x-bcpio"},
  272. {"bin", "application/octet-stream"},
  273. {"bmp", {"image/bmp", "image/x-ms-bmp"}},
  274. {"c", "text/plain"},
  275. {"cab", "application/octet-stream"},
  276. {"caf", "audio/x-caf"},
  277. {"calx", "application/vnd.ms-office.calx"},
  278. {"cat", "application/vnd.ms-pki.seccat"},
  279. {"cc", "text/plain"},
  280. {"cd", "text/plain"},
  281. {"cdda", "audio/aiff"},
  282. {"cdf", "application/x-cdf"},
  283. {"cer", "application/x-x509-ca-cert"},
  284. {"cfg", "text/plain"},
  285. {"chm", "application/octet-stream"},
  286. {"class", "application/x-java-applet"},
  287. {"clp", "application/x-msclip"},
  288. {"cmd", "text/plain"},
  289. {"cmx", "image/x-cmx"},
  290. {"cnf", "text/plain"},
  291. {"cod", "image/cis-cod"},
  292. {"config", "application/xml"},
  293. {"contact", "text/x-ms-contact"},
  294. {"coverage", "application/xml"},
  295. {"cpio", "application/x-cpio"},
  296. {"cpp", "text/plain"},
  297. {"crd", "application/x-mscardfile"},
  298. {"crl", "application/pkix-crl"},
  299. {"crt", "application/x-x509-ca-cert"},
  300. {"cs", "text/plain"},
  301. {"csdproj", "text/plain"},
  302. {"csh", "application/x-csh"},
  303. {"csproj", "text/plain"},
  304. {"css", "text/css"},
  305. {"csv", {"application/vnd.ms-excel", "text/csv", "text/plain"}},
  306. {"cur", "application/octet-stream"},
  307. {"cxx", "text/plain"},
  308. {"dat", {"application/octet-stream", "application/ms-tnef"}},
  309. {"datasource", "application/xml"},
  310. {"dbproj", "text/plain"},
  311. {"dcr", "application/x-director"},
  312. {"def", "text/plain"},
  313. {"deploy", "application/octet-stream"},
  314. {"der", "application/x-x509-ca-cert"},
  315. {"dgml", "application/xml"},
  316. {"dib", "image/bmp"},
  317. {"dif", "video/x-dv"},
  318. {"dir", "application/x-director"},
  319. {"disco", "text/xml"},
  320. {"divx", "video/divx"},
  321. {"dll", "application/x-msdownload"},
  322. {"dll.config", "text/xml"},
  323. {"dlm", "text/dlm"},
  324. {"doc", "application/msword"},
  325. {"docm", "application/vnd.ms-word.document.macroEnabled.12"},
  326. {"docx", {
  327. "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  328. "application/msword",
  329. "application/vnd.ms-word.document.12",
  330. "application/octet-stream",
  331. }},
  332. {"dot", "application/msword"},
  333. {"dotm", "application/vnd.ms-word.template.macroEnabled.12"},
  334. {"dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"},
  335. {"dsp", "application/octet-stream"},
  336. {"dsw", "text/plain"},
  337. {"dtd", "text/xml"},
  338. {"dtsConfig", "text/xml"},
  339. {"dv", "video/x-dv"},
  340. {"dvi", "application/x-dvi"},
  341. {"dwf", "drawing/x-dwf"},
  342. {"dwg", {"application/acad", "image/vnd.dwg"}},
  343. {"dwp", "application/octet-stream"},
  344. {"dxf", "application/x-dxf" },
  345. {"dxr", "application/x-director"},
  346. {"eml", "message/rfc822"},
  347. {"emz", "application/octet-stream"},
  348. {"eot", "application/vnd.ms-fontobject"},
  349. {"eps", "application/postscript"},
  350. {"etl", "application/etl"},
  351. {"etx", "text/x-setext"},
  352. {"evy", "application/envoy"},
  353. {"exe", {
  354. "application/x-dosexec",
  355. "application/x-msdownload",
  356. "application/x-executable",
  357. }},
  358. {"exe.config", "text/xml"},
  359. {"fdf", "application/vnd.fdf"},
  360. {"fif", "application/fractals"},
  361. {"filters", "application/xml"},
  362. {"fla", "application/octet-stream"},
  363. {"flac", "audio/flac"},
  364. {"flr", "x-world/x-vrml"},
  365. {"flv", "video/x-flv"},
  366. {"fsscript", "application/fsharp-script"},
  367. {"fsx", "application/fsharp-script"},
  368. {"generictest", "application/xml"},
  369. {"gif", "image/gif"},
  370. {"gpx", "application/gpx+xml"},
  371. {"group", "text/x-ms-group"},
  372. {"gsm", "audio/x-gsm"},
  373. {"gtar", "application/x-gtar"},
  374. {"gz", {"application/gzip", "application/x-gzip"}},
  375. {"h", "text/plain"},
  376. {"hdf", "application/x-hdf"},
  377. {"hdml", "text/x-hdml"},
  378. {"hhc", "application/x-oleobject"},
  379. {"hhk", "application/octet-stream"},
  380. {"hhp", "application/octet-stream"},
  381. {"hlp", "application/winhlp"},
  382. {"hpp", "text/plain"},
  383. {"hqx", "application/mac-binhex40"},
  384. {"hta", "application/hta"},
  385. {"htc", "text/x-component"},
  386. {"htm", "text/html"},
  387. {"html", "text/html"},
  388. {"htt", "text/webviewhtml"},
  389. {"hxa", "application/xml"},
  390. {"hxc", "application/xml"},
  391. {"hxd", "application/octet-stream"},
  392. {"hxe", "application/xml"},
  393. {"hxf", "application/xml"},
  394. {"hxh", "application/octet-stream"},
  395. {"hxi", "application/octet-stream"},
  396. {"hxk", "application/xml"},
  397. {"hxq", "application/octet-stream"},
  398. {"hxr", "application/octet-stream"},
  399. {"hxs", "application/octet-stream"},
  400. {"hxt", "text/html"},
  401. {"hxv", "application/xml"},
  402. {"hxw", "application/octet-stream"},
  403. {"hxx", "text/plain"},
  404. {"i", "text/plain"},
  405. {"ico", "image/x-icon"},
  406. {"ics", {"text/calendar", "application/ics", "application/octet-stream"}},
  407. {"idl", "text/plain"},
  408. {"ief", "image/ief"},
  409. {"iii", "application/x-iphone"},
  410. {"inc", "text/plain"},
  411. {"inf", "application/octet-stream"},
  412. {"ini", "text/plain"},
  413. {"inl", "text/plain"},
  414. {"ins", "application/x-internet-signup"},
  415. {"ipa", "application/x-itunes-ipa"},
  416. {"ipg", "application/x-itunes-ipg"},
  417. {"ipproj", "text/plain"},
  418. {"ipsw", "application/x-itunes-ipsw"},
  419. {"iqy", "text/x-ms-iqy"},
  420. {"isp", "application/x-internet-signup"},
  421. {"ite", "application/x-itunes-ite"},
  422. {"itlp", "application/x-itunes-itlp"},
  423. {"itms", "application/x-itunes-itms"},
  424. {"itpc", "application/x-itunes-itpc"},
  425. {"IVF", "video/x-ivf"},
  426. {"jar", "application/java-archive"},
  427. {"java", "application/octet-stream"},
  428. {"jck", "application/liquidmotion"},
  429. {"jcz", "application/liquidmotion"},
  430. {"jfif", "image/pjpeg"},
  431. {"jnlp", "application/x-java-jnlp-file"},
  432. {"jpb", "application/octet-stream"},
  433. {"jpe", {"image/jpeg", "image/pjpeg"}},
  434. {"jpeg", {"image/jpeg", "image/pjpeg"}},
  435. {"jpg", {"image/jpeg", "image/pjpeg"}},
  436. {"js", "application/javascript"},
  437. {"json", "application/json"},
  438. {"jsx", "text/jscript"},
  439. {"jsxbin", "text/plain"},
  440. {"latex", "application/x-latex"},
  441. {"library-ms", "application/windows-library+xml"},
  442. {"lit", "application/x-ms-reader"},
  443. {"loadtest", "application/xml"},
  444. {"lpk", "application/octet-stream"},
  445. {"lsf", "video/x-la-asf"},
  446. {"lst", "text/plain"},
  447. {"lsx", "video/x-la-asf"},
  448. {"lzh", "application/octet-stream"},
  449. {"m13", "application/x-msmediaview"},
  450. {"m14", "application/x-msmediaview"},
  451. {"m1v", "video/mpeg"},
  452. {"m2t", "video/vnd.dlna.mpeg-tts"},
  453. {"m2ts", "video/vnd.dlna.mpeg-tts"},
  454. {"m2v", "video/mpeg"},
  455. {"m3u", "audio/x-mpegurl"},
  456. {"m3u8", "audio/x-mpegurl"},
  457. {"m4a", {"audio/m4a", "audio/x-m4a"}},
  458. {"m4b", "audio/m4b"},
  459. {"m4p", "audio/m4p"},
  460. {"m4r", "audio/x-m4r"},
  461. {"m4v", "video/x-m4v"},
  462. {"mac", "image/x-macpaint"},
  463. {"mak", "text/plain"},
  464. {"man", "application/x-troff-man"},
  465. {"manifest", "application/x-ms-manifest"},
  466. {"map", "text/plain"},
  467. {"master", "application/xml"},
  468. {"mbox", "application/mbox"},
  469. {"mda", "application/msaccess"},
  470. {"mdb", "application/x-msaccess"},
  471. {"mde", "application/msaccess"},
  472. {"mdp", "application/octet-stream"},
  473. {"me", "application/x-troff-me"},
  474. {"mfp", "application/x-shockwave-flash"},
  475. {"mht", "message/rfc822"},
  476. {"mhtml", "message/rfc822"},
  477. {"mid", "audio/mid"},
  478. {"midi", "audio/mid"},
  479. {"mix", "application/octet-stream"},
  480. {"mk", "text/plain"},
  481. {"mmf", "application/x-smaf"},
  482. {"mno", "text/xml"},
  483. {"mny", "application/x-msmoney"},
  484. {"mod", "video/mpeg"},
  485. {"mov", "video/quicktime"},
  486. {"movie", "video/x-sgi-movie"},
  487. {"mp2", "video/mpeg"},
  488. {"mp2v", "video/mpeg"},
  489. {"mp3", "audio/mpeg"},
  490. {"mp4", "video/mp4"},
  491. {"mp4v", "video/mp4"},
  492. {"mpa", "video/mpeg"},
  493. {"mpe", "video/mpeg"},
  494. {"mpeg", "video/mpeg"},
  495. {"mpf", "application/vnd.ms-mediapackage"},
  496. {"mpg", "video/mpeg"},
  497. {"mpp", "application/vnd.ms-project"},
  498. {"mpv2", "video/mpeg"},
  499. {"mqv", "video/quicktime"},
  500. {"ms", "application/x-troff-ms"},
  501. {"msg", "application/vnd.ms-outlook"},
  502. {"msi", {"application/x-msi", "application/octet-stream"}},
  503. {"mso", "application/octet-stream"},
  504. {"mts", "video/vnd.dlna.mpeg-tts"},
  505. {"mtx", "application/xml"},
  506. {"mvb", "application/x-msmediaview"},
  507. {"mvc", "application/x-miva-compiled"},
  508. {"mxp", "application/x-mmxp"},
  509. {"nc", "application/x-netcdf"},
  510. {"nsc", "video/x-ms-asf"},
  511. {"nws", "message/rfc822"},
  512. {"ocx", "application/octet-stream"},
  513. {"oda", "application/oda"},
  514. {"odb", "application/vnd.oasis.opendocument.database"},
  515. {"odc", "application/vnd.oasis.opendocument.chart"},
  516. {"odf", "application/vnd.oasis.opendocument.formula"},
  517. {"odg", "application/vnd.oasis.opendocument.graphics"},
  518. {"odh", "text/plain"},
  519. {"odi", "application/vnd.oasis.opendocument.image"},
  520. {"odl", "text/plain"},
  521. {"odm", "application/vnd.oasis.opendocument.text-master"},
  522. {"odp", "application/vnd.oasis.opendocument.presentation"},
  523. {"ods", "application/vnd.oasis.opendocument.spreadsheet"},
  524. {"odt", "application/vnd.oasis.opendocument.text"},
  525. {"oga", "audio/ogg"},
  526. {"ogg", "audio/ogg"},
  527. {"ogv", "video/ogg"},
  528. {"ogx", "application/ogg"},
  529. {"one", "application/onenote"},
  530. {"onea", "application/onenote"},
  531. {"onepkg", "application/onenote"},
  532. {"onetmp", "application/onenote"},
  533. {"onetoc", "application/onenote"},
  534. {"onetoc2", "application/onenote"},
  535. {"opus", "audio/ogg"},
  536. {"orderedtest", "application/xml"},
  537. {"osdx", "application/opensearchdescription+xml"},
  538. {"otf", "application/font-sfnt"},
  539. {"otg", "application/vnd.oasis.opendocument.graphics-template"},
  540. {"oth", "application/vnd.oasis.opendocument.text-web"},
  541. {"otp", "application/vnd.oasis.opendocument.presentation-template"},
  542. {"ots", "application/vnd.oasis.opendocument.spreadsheet-template"},
  543. {"ott", "application/vnd.oasis.opendocument.text-template"},
  544. {"oxt", "application/vnd.openofficeorg.extension"},
  545. {"p10", "application/pkcs10"},
  546. {"p12", "application/x-pkcs12"},
  547. {"p7b", "application/x-pkcs7-certificates"},
  548. {"p7c", "application/pkcs7-mime"},
  549. {"p7m", "application/pkcs7-mime"},
  550. {"p7r", "application/x-pkcs7-certreqresp"},
  551. {"p7s", {"application/pkcs7-signature", "text/plain"}},
  552. {"pbm", "image/x-portable-bitmap"},
  553. {"pcast", "application/x-podcast"},
  554. {"pct", "image/pict"},
  555. {"pcx", "application/octet-stream"},
  556. {"pcz", "application/octet-stream"},
  557. {"pdf", "application/pdf"},
  558. {"pfb", "application/octet-stream"},
  559. {"pfm", "application/octet-stream"},
  560. {"pfx", "application/x-pkcs12"},
  561. {"pgm", "image/x-portable-graymap"},
  562. {"pic", "image/pict"},
  563. {"pict", "image/pict"},
  564. {"pkgdef", "text/plain"},
  565. {"pkgundef", "text/plain"},
  566. {"pko", "application/vnd.ms-pki.pko"},
  567. {"pls", "audio/scpls"},
  568. {"pma", "application/x-perfmon"},
  569. {"pmc", "application/x-perfmon"},
  570. {"pml", "application/x-perfmon"},
  571. {"pmr", "application/x-perfmon"},
  572. {"pmw", "application/x-perfmon"},
  573. {"png", "image/png"},
  574. {"pnm", "image/x-portable-anymap"},
  575. {"pnt", "image/x-macpaint"},
  576. {"pntg", "image/x-macpaint"},
  577. {"pnz", "image/png"},
  578. {"pot", "application/vnd.ms-powerpoint"},
  579. {"potm", "application/vnd.ms-powerpoint.template.macroEnabled.12"},
  580. {"potx", "application/vnd.openxmlformats-officedocument.presentationml.template"},
  581. {"ppa", "application/vnd.ms-powerpoint"},
  582. {"ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12"},
  583. {"ppm", "image/x-portable-pixmap"},
  584. {"pps", "application/vnd.ms-powerpoint"},
  585. {"ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"},
  586. {"ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"},
  587. {"ppt", "application/vnd.ms-powerpoint"},
  588. {"pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12"},
  589. {"pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
  590. {"prf", "application/pics-rules"},
  591. {"prm", "application/octet-stream"},
  592. {"prx", "application/octet-stream"},
  593. {"ps", "application/postscript"},
  594. {"psc1", "application/PowerShell"},
  595. {"psd", "application/octet-stream"},
  596. {"psess", "application/xml"},
  597. {"psm", "application/octet-stream"},
  598. {"psp", "application/octet-stream"},
  599. {"pst", "application/vnd.ms-outlook"},
  600. {"pub", "application/x-mspublisher"},
  601. {"pwz", "application/vnd.ms-powerpoint"},
  602. {"qht", "text/x-html-insertion"},
  603. {"qhtm", "text/x-html-insertion"},
  604. {"qt", "video/quicktime"},
  605. {"qti", "image/x-quicktime"},
  606. {"qtif", "image/x-quicktime"},
  607. {"qtl", "application/x-quicktimeplayer"},
  608. {"qxd", "application/octet-stream"},
  609. {"ra", "audio/x-pn-realaudio"},
  610. {"ram", "audio/x-pn-realaudio"},
  611. {"rar", {"application/x-rar-compressed", "application/x-rar", "application/octet-stream"}},
  612. {"ras", "image/x-cmu-raster"},
  613. {"rat", "application/rat-file"},
  614. {"rc", "text/plain"},
  615. {"rc2", "text/plain"},
  616. {"rct", "text/plain"},
  617. {"rdlc", "application/xml"},
  618. {"reg", "text/plain"},
  619. {"resx", "application/xml"},
  620. {"rf", "image/vnd.rn-realflash"},
  621. {"rgb", "image/x-rgb"},
  622. {"rgs", "text/plain"},
  623. {"rm", "application/vnd.rn-realmedia"},
  624. {"rmi", "audio/mid"},
  625. {"rmp", "application/vnd.rn-rn_music_package"},
  626. {"roff", "application/x-troff"},
  627. {"rpm", "audio/x-pn-realaudio-plugin"},
  628. {"rqy", "text/x-ms-rqy"},
  629. {"rtf", {"application/rtf","application/msword", "text/richtext", "text/rtf"}},
  630. {"rtx", "text/richtext"},
  631. {"rvt", "application/octet-stream" },
  632. {"ruleset", "application/xml"},
  633. {"s", "text/plain"},
  634. {"safariextz", "application/x-safari-safariextz"},
  635. {"scd", "application/x-msschedule"},
  636. {"scr", "text/plain"},
  637. {"sct", "text/scriptlet"},
  638. {"sd2", "audio/x-sd2"},
  639. {"sdp", "application/sdp"},
  640. {"sea", "application/octet-stream"},
  641. {"searchConnector-ms", "application/windows-search-connector+xml"},
  642. {"setpay", "application/set-payment-initiation"},
  643. {"setreg", "application/set-registration-initiation"},
  644. {"settings", "application/xml"},
  645. {"sgimb", "application/x-sgimb"},
  646. {"sgml", "text/sgml"},
  647. {"sh", "application/x-sh"},
  648. {"shar", "application/x-shar"},
  649. {"shtml", "text/html"},
  650. {"sit", "application/x-stuffit"},
  651. {"sitemap", "application/xml"},
  652. {"skin", "application/xml"},
  653. {"skp", "application/x-koan" },
  654. {"sldm", "application/vnd.ms-powerpoint.slide.macroEnabled.12"},
  655. {"sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"},
  656. {"slk", "application/vnd.ms-excel"},
  657. {"sln", "text/plain"},
  658. {"slupkg-ms", "application/x-ms-license"},
  659. {"smd", "audio/x-smd"},
  660. {"smi", "application/octet-stream"},
  661. {"smx", "audio/x-smd"},
  662. {"smz", "audio/x-smd"},
  663. {"snd", "audio/basic"},
  664. {"snippet", "application/xml"},
  665. {"snp", "application/octet-stream"},
  666. {"sol", "text/plain"},
  667. {"sor", "text/plain"},
  668. {"spc", "application/x-pkcs7-certificates"},
  669. {"spl", "application/futuresplash"},
  670. {"spx", "audio/ogg"},
  671. {"src", "application/x-wais-source"},
  672. {"srf", "text/plain"},
  673. {"SSISDeploymentManifest", "text/xml"},
  674. {"ssm", "application/streamingmedia"},
  675. {"sst", "application/vnd.ms-pki.certstore"},
  676. {"stl", "application/vnd.ms-pki.stl"},
  677. {"sv4cpio", "application/x-sv4cpio"},
  678. {"sv4crc", "application/x-sv4crc"},
  679. {"svc", "application/xml"},
  680. {"svg", "image/svg+xml"},
  681. {"swf", "application/x-shockwave-flash"},
  682. {"step", "application/step"},
  683. {"stp", "application/step"},
  684. {"t", "application/x-troff"},
  685. {"tar", "application/x-tar"},
  686. {"tcl", "application/x-tcl"},
  687. {"testrunconfig", "application/xml"},
  688. {"testsettings", "application/xml"},
  689. {"tex", "application/x-tex"},
  690. {"texi", "application/x-texinfo"},
  691. {"texinfo", "application/x-texinfo"},
  692. {"tgz", "application/x-compressed"},
  693. {"thmx", "application/vnd.ms-officetheme"},
  694. {"thn", "application/octet-stream"},
  695. {"tif", {"image/tiff", "application/octet-stream"}},
  696. {"tiff", "image/tiff"},
  697. {"tlh", "text/plain"},
  698. {"tli", "text/plain"},
  699. {"toc", "application/octet-stream"},
  700. {"tr", "application/x-troff"},
  701. {"trm", "application/x-msterminal"},
  702. {"trx", "application/xml"},
  703. {"ts", "video/vnd.dlna.mpeg-tts"},
  704. {"tsv", "text/tab-separated-values"},
  705. {"ttf", "application/font-sfnt"},
  706. {"tts", "video/vnd.dlna.mpeg-tts"},
  707. {"txt", "text/plain"},
  708. {"u32", "application/octet-stream"},
  709. {"uls", "text/iuls"},
  710. {"user", "text/plain"},
  711. {"ustar", "application/x-ustar"},
  712. {"vb", "text/plain"},
  713. {"vbdproj", "text/plain"},
  714. {"vbk", "video/mpeg"},
  715. {"vbproj", "text/plain"},
  716. {"vbs", "text/vbscript"},
  717. {"vcf", {"text/x-vcard", "text/vcard"}},
  718. {"vcproj", "application/xml"},
  719. {"vcs", "text/plain"},
  720. {"vcxproj", "application/xml"},
  721. {"vddproj", "text/plain"},
  722. {"vdp", "text/plain"},
  723. {"vdproj", "text/plain"},
  724. {"vdx", "application/vnd.ms-visio.viewer"},
  725. {"vml", "text/xml"},
  726. {"vscontent", "application/xml"},
  727. {"vsct", "text/xml"},
  728. {"vsd", "application/vnd.visio"},
  729. {"vsi", "application/ms-vsi"},
  730. {"vsix", "application/vsix"},
  731. {"vsixlangpack", "text/xml"},
  732. {"vsixmanifest", "text/xml"},
  733. {"vsmdi", "application/xml"},
  734. {"vspscc", "text/plain"},
  735. {"vss", "application/vnd.visio"},
  736. {"vsscc", "text/plain"},
  737. {"vssettings", "text/xml"},
  738. {"vssscc", "text/plain"},
  739. {"vst", "application/vnd.visio"},
  740. {"vstemplate", "text/xml"},
  741. {"vsto", "application/x-ms-vsto"},
  742. {"vsw", "application/vnd.visio"},
  743. {"vsx", "application/vnd.visio"},
  744. {"vtx", "application/vnd.visio"},
  745. {"wav", "audio/wav"},
  746. {"wave", "audio/wav"},
  747. {"wax", "audio/x-ms-wax"},
  748. {"wbk", "application/msword"},
  749. {"wbmp", "image/vnd.wap.wbmp"},
  750. {"wcm", "application/vnd.ms-works"},
  751. {"wdb", "application/vnd.ms-works"},
  752. {"wdp", "image/vnd.ms-photo"},
  753. {"webarchive", "application/x-safari-webarchive"},
  754. {"webm", "video/webm"},
  755. {"webp", "image/webp"},
  756. {"webtest", "application/xml"},
  757. {"wiq", "application/xml"},
  758. {"wiz", "application/msword"},
  759. {"wks", "application/vnd.ms-works"},
  760. {"WLMP", "application/wlmoviemaker"},
  761. {"wlpginstall", "application/x-wlpg-detect"},
  762. {"wlpginstall3", "application/x-wlpg3-detect"},
  763. {"wm", "video/x-ms-wm"},
  764. {"wma", "audio/x-ms-wma"},
  765. {"wmd", "application/x-ms-wmd"},
  766. {"wmf", "application/x-msmetafile"},
  767. {"wml", "text/vnd.wap.wml"},
  768. {"wmlc", "application/vnd.wap.wmlc"},
  769. {"wmls", "text/vnd.wap.wmlscript"},
  770. {"wmlsc", "application/vnd.wap.wmlscriptc"},
  771. {"wmp", "video/x-ms-wmp"},
  772. {"wmv", "video/x-ms-wmv"},
  773. {"wmx", "video/x-ms-wmx"},
  774. {"wmz", "application/x-ms-wmz"},
  775. {"woff", "application/font-woff"},
  776. {"wpl", "application/vnd.ms-wpl"},
  777. {"wps", "application/vnd.ms-works"},
  778. {"wri", "application/x-mswrite"},
  779. {"wrl", "x-world/x-vrml"},
  780. {"wrz", "x-world/x-vrml"},
  781. {"wsc", "text/scriptlet"},
  782. {"wsdl", "text/xml"},
  783. {"wvx", "video/x-ms-wvx"},
  784. {"x", "application/directx"},
  785. {"xaf", "x-world/x-vrml"},
  786. {"xaml", "application/xaml+xml"},
  787. {"xap", "application/x-silverlight-app"},
  788. {"xbap", "application/x-ms-xbap"},
  789. {"xbm", "image/x-xbitmap"},
  790. {"xdr", "text/plain"},
  791. {"xht", "application/xhtml+xml"},
  792. {"xhtml", "application/xhtml+xml"},
  793. {"xla", "application/vnd.ms-excel"},
  794. {"xlam", "application/vnd.ms-excel.addin.macroEnabled.12"},
  795. {"xlc", "application/vnd.ms-excel"},
  796. {"xld", "application/vnd.ms-excel"},
  797. {"xlk", "application/vnd.ms-excel"},
  798. {"xll", "application/vnd.ms-excel"},
  799. {"xlm", "application/vnd.ms-excel"},
  800. {"xls", {
  801. "application/excel",
  802. "application/vnd.ms-excel",
  803. "application/vnd.ms-office",
  804. "application/x-excel",
  805. "application/octet-stream"
  806. }},
  807. {"xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12"},
  808. {"xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12"},
  809. {"xlsx", {
  810. "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  811. "application/vnd.ms-excel.12",
  812. "application/octet-stream"
  813. }},
  814. {"xlt", "application/vnd.ms-excel"},
  815. {"xltm", "application/vnd.ms-excel.template.macroEnabled.12"},
  816. {"xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"},
  817. {"xlw", "application/vnd.ms-excel"},
  818. {"xml", {"application/xml", "text/xml", "application/octet-stream"}},
  819. {"xmp", "application/octet-stream" },
  820. {"xmta", "application/xml"},
  821. {"xof", "x-world/x-vrml"},
  822. {"XOML", "text/plain"},
  823. {"xpm", "image/x-xpixmap"},
  824. {"xps", "application/vnd.ms-xpsdocument"},
  825. {"xrm-ms", "text/xml"},
  826. {"xsc", "application/xml"},
  827. {"xsd", "text/xml"},
  828. {"xsf", "text/xml"},
  829. {"xsl", "text/xml"},
  830. {"xslt", "text/xml"},
  831. {"xsn", "application/octet-stream"},
  832. {"xss", "application/xml"},
  833. {"xspf", "application/xspf+xml"},
  834. {"xtp", "application/octet-stream"},
  835. {"xwd", "image/x-xwindowdump"},
  836. {"z", "application/x-compress"},
  837. {"zip", {
  838. "application/zip",
  839. "application/x-zip-compressed",
  840. "application/octet-stream"
  841. }},
  842. {"zlib", "application/zlib"},
  843. }
  844. -- Used to match extension by content type
  845. exports.reversed_extensions_map = {
  846. ["text/html"] = "html",
  847. ["text/css"] = "css",
  848. ["text/xml"] = "xml",
  849. ["image/gif"] = "gif",
  850. ["image/jpeg"] = "jpeg",
  851. ["application/javascript"] = "js",
  852. ["application/atom+xml"] = "atom",
  853. ["application/rss+xml"] = "rss",
  854. ["application/csv"] = "csv",
  855. ["text/mathml"] = "mml",
  856. ["text/plain"] = "txt",
  857. ["text/vnd.sun.j2me.app-descriptor"] = "jad",
  858. ["text/vnd.wap.wml"] = "wml",
  859. ["text/x-component"] = "htc",
  860. ["image/png"] = "png",
  861. ["image/svg+xml"] = "svg",
  862. ["image/tiff"] = "tiff",
  863. ["image/vnd.wap.wbmp"] = "wbmp",
  864. ["image/webp"] = "webp",
  865. ["image/x-icon"] = "ico",
  866. ["image/x-jng"] = "jng",
  867. ["image/x-ms-bmp"] = "bmp",
  868. ["font/woff"] = "woff",
  869. ["font/woff2"] = "woff2",
  870. ["application/java-archive"] = "jar",
  871. ["application/json"] = "json",
  872. ["application/mac-binhex40"] = "hqx",
  873. ["application/msword"] = "doc",
  874. ["application/pdf"] = "pdf",
  875. ["application/postscript"] = "ps",
  876. ["application/rtf"] = "rtf",
  877. ["application/vnd.apple.mpegurl"] = "m3u8",
  878. ["application/vnd.google-earth.kml+xml"] = "kml",
  879. ["application/vnd.google-earth.kmz"] = "kmz",
  880. ["application/vnd.ms-excel"] = "xls",
  881. ["application/vnd.ms-fontobject"] = "eot",
  882. ["application/vnd.ms-powerpoint"] = "ppt",
  883. ["application/vnd.oasis.opendocument.graphics"] = "odg",
  884. ["application/vnd.oasis.opendocument.presentation"] = "odp",
  885. ["application/vnd.oasis.opendocument.spreadsheet"] = "ods",
  886. ["application/vnd.oasis.opendocument.text"] = "odt",
  887. ["application/vnd.openxmlformats-officedocument.presentationml.presentation"] = "pptx",
  888. ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] = "xlsx",
  889. ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"] = "docx",
  890. ["application/x-7z-compressed"] = "7z",
  891. ["application/x-cocoa"] = "cco",
  892. ["application/x-java-archive-diff"] = "jardiff",
  893. ["application/x-java-jnlp-file"] = "jnlp",
  894. ["application/x-makeself"] = "run",
  895. ["application/x-perl"] = "pl",
  896. ["application/x-pilot"] = "pdb",
  897. ["application/x-rar-compressed"] = "rar",
  898. ["application/x-redhat-package-manager"] = "rpm",
  899. ["application/x-sea"] = "sea",
  900. ["application/x-shockwave-flash"] = "swf",
  901. ["application/x-stuffit"] = "sit",
  902. ["application/x-tcl"] = "tcl",
  903. ["application/x-x509-ca-cert"] = "crt",
  904. ["application/x-xpinstall"] = "xpi",
  905. ["application/xhtml+xml"] = "xhtml",
  906. ["application/xspf+xml"] = "xspf",
  907. ["application/zip"] = "zip",
  908. ["application/x-dosexec"] = "exe",
  909. ["application/x-msdownload"] = "exe",
  910. ["application/x-executable"] = "exe",
  911. ["text/x-msdos-batch"] = "bat",
  912. ["audio/midi"] = "mid",
  913. ["audio/mpeg"] = "mp3",
  914. ["audio/ogg"] = "ogg",
  915. ["audio/x-m4a"] = "m4a",
  916. ["audio/x-realaudio"] = "ra",
  917. ["video/3gpp"] = "3gpp",
  918. ["video/mp2t"] = "ts",
  919. ["video/mp4"] = "mp4",
  920. ["video/mpeg"] = "mpeg",
  921. ["video/quicktime"] = "mov",
  922. ["video/webm"] = "webm",
  923. ["video/x-flv"] = "flv",
  924. ["video/x-m4v"] = "m4v",
  925. ["video/x-mng"] = "mng",
  926. ["video/x-ms-asf"] = "asx",
  927. ["video/x-ms-wmv"] = "wmv",
  928. ["video/x-msvideo"] = "avi",
  929. }
  930. return exports