From 459607a12cc7f1abbd16b6dc1bf844727b33d3c7 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Sun, 16 Mar 2025 13:48:04 -0700 Subject: [PATCH 1/2] regenerate the mime tables from apache httpd; general refactorings --- pkgs/mime/analysis_options.yaml | 3 +- pkgs/mime/doc/media_types.md | 173 ++-- pkgs/mime/lib/mime.dart | 8 +- pkgs/mime/lib/src/extension.dart | 55 -- pkgs/mime/lib/src/magic_number.dart | 407 --------- pkgs/mime/lib/src/magic_numbers.dart | 154 ++++ pkgs/mime/lib/src/mime.dart | 35 + pkgs/mime/lib/src/mime_shared.dart | 2 +- ..._extension_map.dart => mime_tables.g.dart} | 860 +++++++++++++++++- pkgs/mime/lib/src/mime_type.dart | 58 +- ...part_stream.dart => multipart_stream.dart} | 0 ...former.dart => multipart_transformer.dart} | 11 +- pkgs/mime/pubspec.yaml | 1 + .../mime/test/default_extension_map_test.dart | 4 +- pkgs/mime/test/extension_test.dart | 2 +- pkgs/mime/test/mime_type_test.dart | 9 +- ...edia_types.dart => generate_markdown.dart} | 11 +- pkgs/mime/tool/update_media_types.dart | 110 +++ 18 files changed, 1278 insertions(+), 625 deletions(-) delete mode 100644 pkgs/mime/lib/src/extension.dart delete mode 100644 pkgs/mime/lib/src/magic_number.dart create mode 100644 pkgs/mime/lib/src/magic_numbers.dart create mode 100644 pkgs/mime/lib/src/mime.dart rename pkgs/mime/lib/src/{default_extension_map.dart => mime_tables.g.dart} (52%) rename pkgs/mime/lib/src/{bound_multipart_stream.dart => multipart_stream.dart} (100%) rename pkgs/mime/lib/src/{mime_multipart_transformer.dart => multipart_transformer.dart} (88%) rename pkgs/mime/tool/{media_types.dart => generate_markdown.dart} (83%) create mode 100644 pkgs/mime/tool/update_media_types.dart diff --git a/pkgs/mime/analysis_options.yaml b/pkgs/mime/analysis_options.yaml index dc212e7d4b..7a35f3f8c5 100644 --- a/pkgs/mime/analysis_options.yaml +++ b/pkgs/mime/analysis_options.yaml @@ -2,6 +2,8 @@ include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: + errors: + deprecated_member_use_from_same_package: ignore language: strict-casts: true strict-inference: true @@ -23,7 +25,6 @@ linter: - no_adjacent_strings_in_list - no_runtimeType_toString - prefer_const_declarations - - prefer_expression_function_bodies - prefer_final_locals - unnecessary_await_in_return - unnecessary_breaks diff --git a/pkgs/mime/doc/media_types.md b/pkgs/mime/doc/media_types.md index 5878c21bb5..94f477a3d0 100644 --- a/pkgs/mime/doc/media_types.md +++ b/pkgs/mime/doc/media_types.md @@ -4,8 +4,8 @@ Supported media types and file extensions. -| MIME type | Default | Additional | -| --- | --- | --- | +| MIME type | Default | Additional extensions | +| :--- | :--- | :--- | | `application/andrew-inset` | `ez` | | | `application/applixware` | `aw` | | | `application/atom+xml` | `atom` | | @@ -19,7 +19,6 @@ Supported media types and file extensions. | `application/cdmi-queue` | `cdmiq` | | | `application/cu-seeme` | `cu` | | | `application/davmount+xml` | `davmount` | | -| `application/dicom` | `dcm` | | | `application/docbook+xml` | `dbk` | | | `application/dssc+der` | `dssc` | | | `application/dssc+xml` | `xdssc` | | @@ -32,7 +31,7 @@ Supported media types and file extensions. | `application/gpx+xml` | `gpx` | | | `application/gxf` | `gxf` | | | `application/hyperstudio` | `stk` | | -| `application/inkml+xml` | `inkml` | `ink` | +| `application/inkml+xml` | `ink` | `inkml` | | `application/ipfix` | `ipfix` | | | `application/java-archive` | `jar` | | | `application/java-serialized-object` | `ser` | | @@ -43,10 +42,9 @@ Supported media types and file extensions. | `application/mac-binhex40` | `hqx` | | | `application/mac-compactpro` | `cpt` | | | `application/mads+xml` | `mads` | | -| `application/manifest+json` | `webmanifest` | | | `application/marc` | `mrc` | | | `application/marcxml+xml` | `mrcx` | | -| `application/mathematica` | `nb` | `ma`, `mb` | +| `application/mathematica` | `ma` | `mb`, `nb` | | `application/mathml+xml` | `mathml` | | | `application/mbox` | `mbox` | | | `application/mediaservercontrol+xml` | `mscml` | | @@ -54,21 +52,21 @@ Supported media types and file extensions. | `application/metalink4+xml` | `meta4` | | | `application/mets+xml` | `mets` | | | `application/mods+xml` | `mods` | | -| `application/mp21` | `mp21` | `m21` | +| `application/mp21` | `m21` | `mp21` | | `application/mp4` | `mp4s` | | | `application/msword` | `doc` | `dot` | | `application/mxf` | `mxf` | | -| `application/octet-stream` | `so` | `bin`, `bpk`, `deploy`, `dist`, `distz`, `dms`, `dump`, `elc`, `lrf`, `mar`, `pkg` | +| `application/octet-stream` | `bin` | `bpk`, `deploy`, `dist`, `distz`, `dms`, `dump`, `elc`, `lrf`, `mar`, `pkg`, `so` | | `application/oda` | `oda` | | | `application/oebps-package+xml` | `opf` | | | `application/ogg` | `ogx` | | | `application/omdoc+xml` | `omdoc` | | -| `application/onenote` | `onetoc2` | `onepkg`, `onetmp`, `onetoc` | +| `application/onenote` | `onetoc` | `onepkg`, `onetmp`, `onetoc2` | | `application/oxps` | `oxps` | | | `application/patch-ops-error+xml` | `xer` | | | `application/pdf` | `pdf` | | | `application/pgp-encrypted` | `pgp` | | -| `application/pgp-signature` | `sig` | `asc` | +| `application/pgp-signature` | `asc` | `sig` | | `application/pics-rules` | `prf` | | | `application/pkcs10` | `p10` | | | `application/pkcs7-mime` | `p7m` | `p7c` | @@ -80,7 +78,7 @@ Supported media types and file extensions. | `application/pkix-pkipath` | `pkipath` | | | `application/pkixcmp` | `pki` | | | `application/pls+xml` | `pls` | | -| `application/postscript` | `ps` | `ai`, `eps` | +| `application/postscript` | `ai` | `eps`, `ps` | | `application/prs.cww` | `cww` | | | `application/pskc+xml` | `pskcxml` | | | `application/rdf+xml` | `rdf` | | @@ -104,7 +102,7 @@ Supported media types and file extensions. | `application/set-payment-initiation` | `setpay` | | | `application/set-registration-initiation` | `setreg` | | | `application/shf+xml` | `shf` | | -| `application/smil+xml` | `smil` | `smi` | +| `application/smil+xml` | `smi` | `smil` | | `application/sparql-query` | `rq` | | | `application/sparql-results+xml` | `srx` | | | `application/srgs` | `gram` | | @@ -112,10 +110,9 @@ Supported media types and file extensions. | `application/sru+xml` | `sru` | | | `application/ssdl+xml` | `ssdl` | | | `application/ssml+xml` | `ssml` | | -| `application/tei+xml` | `teicorpus` | `tei` | +| `application/tei+xml` | `tei` | `teicorpus` | | `application/thraud+xml` | `tfi` | | | `application/timestamped-data` | `tsd` | | -| `application/toml` | `toml` | | | `application/vnd.3gpp.pic-bw-large` | `plb` | | | `application/vnd.3gpp.pic-bw-small` | `psb` | | | `application/vnd.3gpp.pic-bw-var` | `pvb` | | @@ -127,7 +124,7 @@ Supported media types and file extensions. | `application/vnd.acucorp` | `atc` | `acutc` | | `application/vnd.adobe.air-application-installer-package+zip` | `air` | | | `application/vnd.adobe.formscentral.fcdt` | `fcdt` | | -| `application/vnd.adobe.fxp` | `fxpl` | `fxp` | +| `application/vnd.adobe.fxp` | `fxp` | `fxpl` | | `application/vnd.adobe.xdp+xml` | `xdp` | | | `application/vnd.adobe.xfdf` | `xfdf` | | | `application/vnd.ahead.space` | `ahead` | | @@ -153,7 +150,7 @@ Supported media types and file extensions. | `application/vnd.cinderella` | `cdy` | | | `application/vnd.claymore` | `cla` | | | `application/vnd.cloanto.rp9` | `rp9` | | -| `application/vnd.clonk.c4group` | `c4u` | `c4d`, `c4f`, `c4g`, `c4p` | +| `application/vnd.clonk.c4group` | `c4g` | `c4d`, `c4f`, `c4p`, `c4u` | | `application/vnd.cluetrust.cartomobile-config` | `c11amc` | | | `application/vnd.cluetrust.cartomobile-config-pkg` | `c11amz` | | | `application/vnd.commonspace` | `csp` | | @@ -170,8 +167,8 @@ Supported media types and file extensions. | `application/vnd.curl.car` | `car` | | | `application/vnd.curl.pcurl` | `pcurl` | | | `application/vnd.data-vision.rdz` | `rdz` | | -| `application/vnd.dece.data` | `uvvf` | `uvd`, `uvf`, `uvvd` | -| `application/vnd.dece.ttml+xml` | `uvvt` | `uvt` | +| `application/vnd.dece.data` | `uvf` | `uvd`, `uvvd`, `uvvf` | +| `application/vnd.dece.ttml+xml` | `uvt` | `uvvt` | | `application/vnd.dece.unspecified` | `uvx` | `uvvx` | | `application/vnd.dece.zip` | `uvz` | `uvvz` | | `application/vnd.denovo.fcselayout-link` | `fe_launch` | | @@ -190,7 +187,7 @@ Supported media types and file extensions. | `application/vnd.epson.quickanime` | `qam` | | | `application/vnd.epson.salt` | `slt` | | | `application/vnd.epson.ssf` | `ssf` | | -| `application/vnd.eszigno3+xml` | `et3` | `es3` | +| `application/vnd.eszigno3+xml` | `es3` | `et3` | | `application/vnd.ezpix-album` | `ez2` | | | `application/vnd.ezpix-package` | `ez3` | | | `application/vnd.fdf` | `fdf` | | @@ -198,7 +195,7 @@ Supported media types and file extensions. | `application/vnd.fdsn.seed` | `seed` | `dataless` | | `application/vnd.flographit` | `gph` | | | `application/vnd.fluxtime.clip` | `ftc` | | -| `application/vnd.framemaker` | `maker` | `book`, `fm`, `frame` | +| `application/vnd.framemaker` | `fm` | `book`, `frame`, `maker` | | `application/vnd.frogans.fnc` | `fnc` | | | `application/vnd.frogans.ltf` | `ltf` | | | `application/vnd.fsc.weblaunch` | `fsc` | | @@ -213,15 +210,16 @@ Supported media types and file extensions. | `application/vnd.fuzzysheet` | `fzs` | | | `application/vnd.genomatix.tuxedo` | `txd` | | | `application/vnd.geogebra.file` | `ggb` | | +| `application/vnd.geogebra.slides` | `ggs` | | | `application/vnd.geogebra.tool` | `ggt` | | -| `application/vnd.geometry-explorer` | `gre` | `gex` | +| `application/vnd.geometry-explorer` | `gex` | `gre` | | `application/vnd.geonext` | `gxt` | | | `application/vnd.geoplan` | `g2w` | | | `application/vnd.geospace` | `g3w` | | | `application/vnd.gmx` | `gmx` | | | `application/vnd.google-earth.kml+xml` | `kml` | | | `application/vnd.google-earth.kmz` | `kmz` | | -| `application/vnd.grafeq` | `gqs` | `gqf` | +| `application/vnd.grafeq` | `gqf` | `gqs` | | `application/vnd.groove-account` | `gac` | | | `application/vnd.groove-help` | `ghf` | | | `application/vnd.groove-identity-message` | `gim` | | @@ -241,15 +239,15 @@ Supported media types and file extensions. | `application/vnd.hp-pclxl` | `pclxl` | | | `application/vnd.hydrostatix.sof-data` | `sfd-hdstx` | | | `application/vnd.ibm.minipay` | `mpy` | | -| `application/vnd.ibm.modcap` | `listafp` | `afp`, `list3820` | +| `application/vnd.ibm.modcap` | `afp` | `list3820`, `listafp` | | `application/vnd.ibm.rights-management` | `irm` | | | `application/vnd.ibm.secure-container` | `sc` | | -| `application/vnd.iccprofile` | `icm` | `icc` | +| `application/vnd.iccprofile` | `icc` | `icm` | | `application/vnd.igloader` | `igl` | | | `application/vnd.immervision-ivp` | `ivp` | | | `application/vnd.immervision-ivu` | `ivu` | | | `application/vnd.insors.igm` | `igm` | | -| `application/vnd.intercon.formnet` | `xpx` | `xpw` | +| `application/vnd.intercon.formnet` | `xpw` | `xpx` | | `application/vnd.intergeo` | `i2g` | | | `application/vnd.intu.qbo` | `qbo` | | | `application/vnd.intu.qfx` | `qfx` | | @@ -267,13 +265,13 @@ Supported media types and file extensions. | `application/vnd.kde.kformula` | `kfo` | | | `application/vnd.kde.kivio` | `flw` | | | `application/vnd.kde.kontour` | `kon` | | -| `application/vnd.kde.kpresenter` | `kpt` | `kpr` | +| `application/vnd.kde.kpresenter` | `kpr` | `kpt` | | `application/vnd.kde.kspread` | `ksp` | | -| `application/vnd.kde.kword` | `kwt` | `kwd` | +| `application/vnd.kde.kword` | `kwd` | `kwt` | | `application/vnd.kenameaapp` | `htke` | | | `application/vnd.kidspiration` | `kia` | | -| `application/vnd.kinar` | `knp` | `kne` | -| `application/vnd.koan` | `skt` | `skd`, `skm`, `skp` | +| `application/vnd.kinar` | `kne` | `knp` | +| `application/vnd.koan` | `skp` | `skd`, `skm`, `skt` | | `application/vnd.kodak-descriptor` | `sse` | | | `application/vnd.las.las+xml` | `lasxml` | | | `application/vnd.llamagraphics.life-balance.desktop` | `lbd` | | @@ -324,7 +322,7 @@ Supported media types and file extensions. | `application/vnd.ms-powerpoint.slide.macroenabled.12` | `sldm` | | | `application/vnd.ms-powerpoint.slideshow.macroenabled.12` | `ppsm` | | | `application/vnd.ms-powerpoint.template.macroenabled.12` | `potm` | | -| `application/vnd.ms-project` | `mpt` | `mpp` | +| `application/vnd.ms-project` | `mpp` | `mpt` | | `application/vnd.ms-word.document.macroenabled.12` | `docm` | | | `application/vnd.ms-word.template.macroenabled.12` | `dotm` | | | `application/vnd.ms-works` | `wps` | `wcm`, `wdb`, `wks` | @@ -377,7 +375,7 @@ Supported media types and file extensions. | `application/vnd.osgeo.mapguide.package` | `mgp` | | | `application/vnd.osgi.dp` | `dp` | | | `application/vnd.osgi.subsystem` | `esa` | | -| `application/vnd.palm` | `pqa` | `oprc`, `pdb` | +| `application/vnd.palm` | `pdb` | `oprc`, `pqa` | | `application/vnd.pawaafile` | `paw` | | | `application/vnd.pg.format` | `str` | | | `application/vnd.pg.osasli` | `ei6` | | @@ -389,7 +387,7 @@ Supported media types and file extensions. | `application/vnd.proteus.magazine` | `mgz` | | | `application/vnd.publishare-delta-tree` | `qps` | | | `application/vnd.pvi.ptid1` | `ptid` | | -| `application/vnd.quark.quarkxpress` | `qxt` | `qwd`, `qwt`, `qxb`, `qxd`, `qxl` | +| `application/vnd.quark.quarkxpress` | `qxd` | `qwd`, `qwt`, `qxb`, `qxl`, `qxt` | | `application/vnd.realvnc.bed` | `bed` | | | `application/vnd.recordare.musicxml` | `mxl` | | | `application/vnd.recordare.musicxml+xml` | `musicxml` | | @@ -407,7 +405,7 @@ Supported media types and file extensions. | `application/vnd.shana.informed.formtemplate` | `itp` | | | `application/vnd.shana.informed.interchange` | `iif` | | | `application/vnd.shana.informed.package` | `ipk` | | -| `application/vnd.simtech-mindmapper` | `twds` | `twd` | +| `application/vnd.simtech-mindmapper` | `twd` | `twds` | | `application/vnd.smaf` | `mmf` | | | `application/vnd.smart.teacher` | `teacher` | | | `application/vnd.solent.sdkm+xml` | `sdkm` | `sdkd` | @@ -417,7 +415,7 @@ Supported media types and file extensions. | `application/vnd.stardivision.draw` | `sda` | | | `application/vnd.stardivision.impress` | `sdd` | | | `application/vnd.stardivision.math` | `smf` | | -| `application/vnd.stardivision.writer` | `vor` | `sdw` | +| `application/vnd.stardivision.writer` | `sdw` | `vor` | | `application/vnd.stardivision.writer-global` | `sgl` | | | `application/vnd.stepmania.package` | `smzip` | | | `application/vnd.stepmania.stepchart` | `sm` | | @@ -431,9 +429,9 @@ Supported media types and file extensions. | `application/vnd.sun.xml.writer` | `sxw` | | | `application/vnd.sun.xml.writer.global` | `sxg` | | | `application/vnd.sun.xml.writer.template` | `stw` | | -| `application/vnd.sus-calendar` | `susp` | `sus` | +| `application/vnd.sus-calendar` | `sus` | `susp` | | `application/vnd.svd` | `svd` | | -| `application/vnd.symbian.install` | `sisx` | `sis` | +| `application/vnd.symbian.install` | `sis` | `sisx` | | `application/vnd.syncml+xml` | `xsm` | | | `application/vnd.syncml.dm+wbxml` | `bdm` | | | `application/vnd.syncml.dm+xml` | `xdm` | | @@ -443,13 +441,13 @@ Supported media types and file extensions. | `application/vnd.trid.tpt` | `tpt` | | | `application/vnd.triscape.mxs` | `mxs` | | | `application/vnd.trueapp` | `tra` | | -| `application/vnd.ufdl` | `ufdl` | `ufd` | +| `application/vnd.ufdl` | `ufd` | `ufdl` | | `application/vnd.uiq.theme` | `utz` | | | `application/vnd.umajin` | `umj` | | | `application/vnd.unity` | `unityweb` | | | `application/vnd.uoml+xml` | `uoml` | | | `application/vnd.vcx` | `vcx` | | -| `application/vnd.visio` | `vsw` | `vsd`, `vss`, `vst` | +| `application/vnd.visio` | `vsd` | `vss`, `vst`, `vsw` | | `application/vnd.visionary` | `vis` | | | `application/vnd.vsf` | `vsf` | | | `application/vnd.wap.wbxml` | `wbxml` | | @@ -470,7 +468,7 @@ Supported media types and file extensions. | `application/vnd.yamaha.smaf-audio` | `saf` | | | `application/vnd.yamaha.smaf-phrase` | `spf` | | | `application/vnd.yellowriver-custom-menu` | `cmp` | | -| `application/vnd.zul` | `zirz` | `zir` | +| `application/vnd.zul` | `zir` | `zirz` | | `application/vnd.zzazz.deck+xml` | `zaz` | | | `application/voicexml+xml` | `vxml` | | | `application/wasm` | `wasm` | | @@ -482,15 +480,15 @@ Supported media types and file extensions. | `application/x-abiword` | `abw` | | | `application/x-ace-compressed` | `ace` | | | `application/x-apple-diskimage` | `dmg` | | -| `application/x-authorware-bin` | `x32` | `aab`, `u32`, `vox` | +| `application/x-authorware-bin` | `aab` | `u32`, `vox`, `x32` | | `application/x-authorware-map` | `aam` | | | `application/x-authorware-seg` | `aas` | | | `application/x-bcpio` | `bcpio` | | | `application/x-bittorrent` | `torrent` | | -| `application/x-blorb` | `blorb` | `blb` | +| `application/x-blorb` | `blb` | `blorb` | | `application/x-bzip` | `bz` | | | `application/x-bzip2` | `bz2` | `boz` | -| `application/x-cbr` | `cbz` | `cb7`, `cba`, `cbr`, `cbt` | +| `application/x-cbr` | `cbr` | `cb7`, `cba`, `cbt`, `cbz` | | `application/x-cdlink` | `vcd` | | | `application/x-cfs-compressed` | `cfs` | | | `application/x-chat` | `chat` | | @@ -500,7 +498,7 @@ Supported media types and file extensions. | `application/x-csh` | `csh` | | | `application/x-debian-package` | `deb` | `udeb` | | `application/x-dgc-compressed` | `dgc` | | -| `application/x-director` | `w3d` | `cct`, `cst`, `cxt`, `dcr`, `dir`, `dxr`, `fgd`, `swa` | +| `application/x-director` | `dir` | `cct`, `cst`, `cxt`, `dcr`, `dxr`, `fgd`, `swa`, `w3d` | | `application/x-doom` | `wad` | | | `application/x-dtbncx+xml` | `ncx` | | | `application/x-dtbook+xml` | `dtb` | | @@ -511,12 +509,9 @@ Supported media types and file extensions. | `application/x-font-bdf` | `bdf` | | | `application/x-font-ghostscript` | `gsf` | | | `application/x-font-linux-psf` | `psf` | | -| `application/x-font-otf` | `otf` | | | `application/x-font-pcf` | `pcf` | | | `application/x-font-snf` | `snf` | | -| `application/x-font-ttf` | `ttf` | `ttc` | -| `application/x-font-type1` | `pfm` | `afm`, `pfa`, `pfb` | -| `application/x-font-woff` | `woff` | | +| `application/x-font-type1` | `pfa` | `afm`, `pfb`, `pfm` | | `application/x-freearc` | `arc` | | | `application/x-futuresplash` | `spl` | | | `application/x-gca-compressed` | `gca` | | @@ -535,15 +530,14 @@ Supported media types and file extensions. | `application/x-ms-application` | `application` | | | `application/x-ms-shortcut` | `lnk` | | | `application/x-ms-wmd` | `wmd` | | -| `application/x-ms-wmz` | `wmz` | | | `application/x-ms-xbap` | `xbap` | | | `application/x-msaccess` | `mdb` | | | `application/x-msbinder` | `obd` | | | `application/x-mscardfile` | `crd` | | | `application/x-msclip` | `clp` | | -| `application/x-msdownload` | `msi` | `bat`, `com`, `dll`, `exe` | +| `application/x-msdownload` | `exe` | `bat`, `com`, `dll`, `msi` | | `application/x-msmediaview` | `mvb` | `m13`, `m14` | -| `application/x-msmetafile` | `wmf` | `emf`, `emz` | +| `application/x-msmetafile` | `wmf` | `emf`, `emz`, `wmz` | | `application/x-msmoney` | `mny` | | | `application/x-mspublisher` | `pub` | | | `application/x-msschedule` | `scd` | | @@ -551,8 +545,8 @@ Supported media types and file extensions. | `application/x-mswrite` | `wri` | | | `application/x-netcdf` | `nc` | `cdf` | | `application/x-nzb` | `nzb` | | -| `application/x-pkcs12` | `pfx` | `p12` | -| `application/x-pkcs7-certificates` | `spc` | `p7b` | +| `application/x-pkcs12` | `p12` | `pfx` | +| `application/x-pkcs7-certificates` | `p7b` | `spc` | | `application/x-pkcs7-certreqresp` | `p7r` | | | `application/x-rar-compressed` | `rar` | | | `application/x-research-info-systems` | `ris` | | @@ -581,7 +575,7 @@ Supported media types and file extensions. | `application/x-xliff+xml` | `xlf` | | | `application/x-xpinstall` | `xpi` | | | `application/x-xz` | `xz` | | -| `application/x-zmachine` | `z8` | `z1`, `z2`, `z3`, `z4`, `z5`, `z6`, `z7` | +| `application/x-zmachine` | `z1` | `z2`, `z3`, `z4`, `z5`, `z6`, `z7`, `z8` | | `application/xaml+xml` | `xaml` | | | `application/xcap-diff+xml` | `xdf` | | | `application/xenc+xml` | `xenc` | | @@ -592,20 +586,19 @@ Supported media types and file extensions. | `application/xproc+xml` | `xpl` | | | `application/xslt+xml` | `xslt` | | | `application/xspf+xml` | `xspf` | | -| `application/xv+xml` | `xvml` | `mxml`, `xhvml`, `xvm` | +| `application/xv+xml` | `mxml` | `xhvml`, `xvm`, `xvml` | | `application/yang` | `yang` | | | `application/yin+xml` | `yin` | | | `application/zip` | `zip` | | -| `audio/aac` | `aac` | | | `audio/adpcm` | `adp` | | -| `audio/basic` | `snd` | `au` | +| `audio/basic` | `au` | `snd` | | `audio/midi` | `mid` | `kar`, `midi`, `rmi` | -| `audio/mp4` | `m4a` | `m4b`, `mp4a` | +| `audio/mp4` | `m4a` | `mp4a` | | `audio/mpeg` | `mpga` | `m2a`, `m3a`, `mp2`, `mp2a`, `mp3` | -| `audio/ogg` | `ogg` | `oga`, `spx` | +| `audio/ogg` | `oga` | `ogg`, `opus`, `spx` | | `audio/s3m` | `s3m` | | | `audio/silk` | `sil` | | -| `audio/vnd.dece.audio` | `uvva` | `uva` | +| `audio/vnd.dece.audio` | `uva` | `uvva` | | `audio/vnd.digital-winds` | `eol` | | | `audio/vnd.dra` | `dra` | | | `audio/vnd.dts` | `dts` | | @@ -617,6 +610,7 @@ Supported media types and file extensions. | `audio/vnd.nuera.ecelp9600` | `ecelp9600` | | | `audio/vnd.rip` | `rip` | | | `audio/webm` | `weba` | | +| `audio/x-aac` | `aac` | | | `audio/x-aiff` | `aif` | `aifc`, `aiff` | | `audio/x-caf` | `caf` | | | `audio/x-flac` | `flac` | | @@ -634,24 +628,27 @@ Supported media types and file extensions. | `chemical/x-cml` | `cml` | | | `chemical/x-csml` | `csml` | | | `chemical/x-xyz` | `xyz` | | +| `font/collection` | `ttc` | | +| `font/otf` | `otf` | | +| `font/ttf` | `ttf` | | +| `font/woff` | `woff` | | | `font/woff2` | `woff2` | | | `image/avif` | `avif` | | | `image/bmp` | `bmp` | | | `image/cgm` | `cgm` | | | `image/g3fax` | `g3` | | | `image/gif` | `gif` | | -| `image/heic` | `heic` | | -| `image/heif` | `heif` | | | `image/ief` | `ief` | | -| `image/jpeg` | `jpg` | `jpe`, `jpeg` | +| `image/jpeg` | `jpeg` | `jpe`, `jpg` | +| `image/jxl` | `jxl` | | | `image/ktx` | `ktx` | | | `image/png` | `png` | | | `image/prs.btif` | `btif` | | | `image/sgi` | `sgi` | | | `image/svg+xml` | `svg` | `svgz` | -| `image/tiff` | `tif` | `tiff` | +| `image/tiff` | `tiff` | `tif` | | `image/vnd.adobe.photoshop` | `psd` | | -| `image/vnd.dece.graphic` | `uvvi` | `uvg`, `uvi`, `uvvg` | +| `image/vnd.dece.graphic` | `uvi` | `uvg`, `uvvg`, `uvvi` | | `image/vnd.djvu` | `djvu` | `djv` | | `image/vnd.dwg` | `dwg` | | | `image/vnd.dxf` | `dxf` | | @@ -669,7 +666,7 @@ Supported media types and file extensions. | `image/x-3ds` | `3ds` | | | `image/x-cmu-raster` | `ras` | | | `image/x-cmx` | `cmx` | | -| `image/x-freehand` | `fhc` | `fh`, `fh4`, `fh5`, `fh7` | +| `image/x-freehand` | `fh` | `fh4`, `fh5`, `fh7`, `fhc` | | `image/x-icon` | `ico` | | | `image/x-mrsid-image` | `sid` | | | `image/x-pcx` | `pcx` | | @@ -683,21 +680,18 @@ Supported media types and file extensions. | `image/x-xbitmap` | `xbm` | | | `image/x-xpixmap` | `xpm` | | | `image/x-xwindowdump` | `xwd` | | -| `message/rfc822` | `mime` | `eml` | -| `model/gltf+json` | `gltf` | | -| `model/gltf-binary` | `glb` | | +| `message/rfc822` | `eml` | `mime` | | `model/iges` | `igs` | `iges` | -| `model/mesh` | `silo` | `mesh`, `msh` | +| `model/mesh` | `msh` | `mesh`, `silo` | | `model/vnd.collada+xml` | `dae` | | | `model/vnd.dwf` | `dwf` | | | `model/vnd.gdl` | `gdl` | | | `model/vnd.gtw` | `gtw` | | -| `model/vnd.mts` | `mts` | | | `model/vnd.vtu` | `vtu` | | -| `model/vrml` | `vrml` | `wrl` | -| `model/x3d+binary` | `x3dbz` | `x3db` | -| `model/x3d+vrml` | `x3dvz` | `x3dv` | -| `model/x3d+xml` | `x3dz` | `x3d` | +| `model/vrml` | `wrl` | `vrml` | +| `model/x3d+binary` | `x3db` | `x3dbz` | +| `model/x3d+vrml` | `x3dv` | `x3dvz` | +| `model/x3d+xml` | `x3d` | `x3dz` | | `text/cache-manifest` | `appcache` | | | `text/calendar` | `ics` | `ifb` | | `text/css` | `css` | | @@ -711,9 +705,9 @@ Supported media types and file extensions. | `text/richtext` | `rtx` | | | `text/sgml` | `sgml` | `sgm` | | `text/tab-separated-values` | `tsv` | | -| `text/troff` | `tr` | `man`, `me`, `ms`, `roff`, `t` | +| `text/troff` | `t` | `man`, `me`, `ms`, `roff`, `tr` | | `text/turtle` | `ttl` | | -| `text/uri-list` | `urls` | `uri`, `uris` | +| `text/uri-list` | `uri` | `uris`, `urls` | | `text/vcard` | `vcard` | | | `text/vnd.curl` | `curl` | | | `text/vnd.curl.dcurl` | `dcurl` | | @@ -728,14 +722,14 @@ Supported media types and file extensions. | `text/vnd.sun.j2me.app-descriptor` | `jad` | | | `text/vnd.wap.wml` | `wml` | | | `text/vnd.wap.wmlscript` | `wmls` | | -| `text/x-asm` | `asm` | `s` | +| `text/x-asm` | `s` | `asm` | | `text/x-c` | `c` | `cc`, `cpp`, `cxx`, `dic`, `h`, `hh` | | `text/x-dart` | `dart` | | -| `text/x-fortran` | `for` | `f`, `f77`, `f90` | +| `text/x-fortran` | `f` | `f77`, `f90`, `for` | | `text/x-java-source` | `java` | | | `text/x-nfo` | `nfo` | | | `text/x-opml` | `opml` | | -| `text/x-pascal` | `pas` | `p` | +| `text/x-pascal` | `p` | `pas` | | `text/x-setext` | `etx` | | | `text/x-sfv` | `sfv` | | | `text/x-uuencode` | `uu` | | @@ -748,21 +742,22 @@ Supported media types and file extensions. | `video/h264` | `h264` | | | `video/jpeg` | `jpgv` | | | `video/jpm` | `jpm` | `jpgm` | -| `video/mj2` | `mjp2` | `mj2` | +| `video/mj2` | `mj2` | `mjp2` | +| `video/mp2t` | `ts` | `m2t`, `m2ts`, `mts` | | `video/mp4` | `mp4` | `mp4v`, `mpg4` | -| `video/mpeg` | `mpg` | `m1v`, `m2v`, `mpe`, `mpeg` | +| `video/mpeg` | `mpeg` | `m1v`, `m2v`, `mpe`, `mpg` | | `video/ogg` | `ogv` | | -| `video/quicktime` | `mov` | `qt` | -| `video/vnd.dece.hd` | `uvvh` | `uvh` | -| `video/vnd.dece.mobile` | `uvvm` | `uvm` | -| `video/vnd.dece.pd` | `uvvp` | `uvp` | -| `video/vnd.dece.sd` | `uvvs` | `uvs` | -| `video/vnd.dece.video` | `uvvv` | `uvv` | +| `video/quicktime` | `qt` | `mov` | +| `video/vnd.dece.hd` | `uvh` | `uvvh` | +| `video/vnd.dece.mobile` | `uvm` | `uvvm` | +| `video/vnd.dece.pd` | `uvp` | `uvvp` | +| `video/vnd.dece.sd` | `uvs` | `uvvs` | +| `video/vnd.dece.video` | `uvv` | `uvvv` | | `video/vnd.dvb.file` | `dvb` | | | `video/vnd.fvt` | `fvt` | | | `video/vnd.mpegurl` | `mxu` | `m4u` | | `video/vnd.ms-playready.media.pyv` | `pyv` | | -| `video/vnd.uvvu.mp4` | `uvvu` | `uvu` | +| `video/vnd.uvvu.mp4` | `uvu` | `uvvu` | | `video/vnd.vivo` | `viv` | | | `video/webm` | `webm` | | | `video/x-f4v` | `f4v` | | @@ -771,7 +766,7 @@ Supported media types and file extensions. | `video/x-m4v` | `m4v` | | | `video/x-matroska` | `mkv` | `mk3d`, `mks` | | `video/x-mng` | `mng` | | -| `video/x-ms-asf` | `asx` | `asf` | +| `video/x-ms-asf` | `asf` | `asx` | | `video/x-ms-vob` | `vob` | | | `video/x-ms-wm` | `wm` | | | `video/x-ms-wmv` | `wmv` | | diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart index cb450981fe..0383ec740a 100644 --- a/pkgs/mime/lib/mime.dart +++ b/pkgs/mime/lib/mime.dart @@ -2,14 +2,14 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -/// Help for working with file format identifiers -/// such as `text/html` and `image/png`. +/// Help for working with file format identifiers such as `text/html` and +/// `image/png`. /// /// More details, including a list of types, are in the Wikipedia article /// [Internet media type](http://en.wikipedia.org/wiki/Internet_media_type). library; -export 'src/extension.dart'; -export 'src/mime_multipart_transformer.dart'; +export 'src/mime.dart'; export 'src/mime_shared.dart'; export 'src/mime_type.dart'; +export 'src/multipart_transformer.dart'; diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart deleted file mode 100644 index 293449a0e0..0000000000 --- a/pkgs/mime/lib/src/extension.dart +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'default_extension_map.dart'; - -/// Default extension for recognized MIME types. -/// -/// Is the inverse of [defaultExtensionMap], and where that -/// map has multiple extensions which map to the same -/// MIME type, this map maps that MIME type to a *default* -/// extension. -/// -/// Used by [extensionFromMime]. -final Map _defaultMimeTypeMap = { - for (var entry in defaultExtensionMap.entries) entry.value: entry.key, - 'application/msword': 'doc', - 'application/vnd.ms-excel': 'xls', - 'application/vnd.ms-powerpoint': 'ppt', - 'application/x-debian-package': 'deb', - 'application/xhtml+xml': 'xhtml', - 'application/xml': 'xml', - 'audio/x-aiff': 'aif', - 'audio/midi': 'mid', - 'audio/mp4': 'm4a', - 'audio/ogg': 'ogg', - 'image/jpeg': 'jpg', - 'image/tiff': 'tif', - 'image/svg+xml': 'svg', - 'model/vrml': 'vrml', - 'text/calendar': 'ics', - 'text/html': 'html', - 'text/javascript': 'js', - 'text/markdown': 'md', - 'text/plain': 'txt', - 'text/sgml': 'sgml', - 'text/x-asm': 'asm', - 'text/x-c': 'c', - 'text/x-pascal': 'pas', - 'video/mp4': 'mp4', - 'video/mpeg': 'mpg', - 'video/quicktime': 'mov', - 'video/x-matroska': 'mkv', -}; - -/// The default file extension for a given MIME type. -/// -/// If [mimeType] has multiple associated extensions, -/// the returned string is one of those, chosen as the default -/// extension for that MIME type. -/// -/// Returns `null` if [mimeType] is not a recognized and -/// supported MIME type. -String? extensionFromMime(String mimeType) => - _defaultMimeTypeMap[mimeType.toLowerCase()]; diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart deleted file mode 100644 index c8b5c3be13..0000000000 --- a/pkgs/mime/lib/src/magic_number.dart +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -class MagicNumber { - final String mimeType; - final List numbers; - final List? mask; - - const MagicNumber(this.mimeType, this.numbers, {this.mask}); - - bool matches(List header) { - if (header.length < numbers.length) return false; - - for (var i = 0; i < numbers.length; i++) { - if (mask != null) { - if ((mask![i] & numbers[i]) != (mask![i] & header[i])) return false; - } else { - if (numbers[i] != header[i]) return false; - } - } - - return true; - } -} - -const int initialMagicNumbersMaxLength = 12; - -const List initialMagicNumbers = [ - MagicNumber('application/pdf', [0x25, 0x50, 0x44, 0x46]), - MagicNumber('application/postscript', [0x25, 0x51]), - - /// AIFF is based on the EA IFF 85 Standard for Interchange Format Files. - /// -> 4 bytes have the ASCII characters 'F' 'O' 'R' 'M'. - /// -> 4 bytes indicating the size of the file - /// -> 4 bytes have the ASCII characters 'A' 'I' 'F' 'F'. - /// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/Docs/AIFF-1.3.pdf - MagicNumber('audio/x-aiff', [ - 0x46, - 0x4F, - 0x52, - 0x4D, - 0x00, - 0x00, - 0x00, - 0x00, - 0x41, - 0x49, - 0x46, - 0x46 - ], mask: [ - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), - - /// -> 4 bytes have the ASCII characters 'f' 'L' 'a' 'C'. - /// https://xiph.org/flac/format.html - MagicNumber('audio/x-flac', [0x66, 0x4C, 0x61, 0x43]), - - /// The WAVE file format is based on the RIFF document format. - /// -> 4 bytes have the ASCII characters 'R' 'I' 'F' 'F'. - /// -> 4 bytes indicating the size of the file - /// -> 4 bytes have the ASCII characters 'W' 'A' 'V' 'E'. - /// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/riffmci.pdf - MagicNumber('audio/x-wav', [ - 0x52, - 0x49, - 0x46, - 0x46, - 0x00, - 0x00, - 0x00, - 0x00, - 0x57, - 0x41, - 0x56, - 0x45 - ], mask: [ - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), - MagicNumber('image/gif', [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), - MagicNumber('image/gif', [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), - MagicNumber('image/jpeg', [0xFF, 0xD8]), - MagicNumber('image/png', [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), - MagicNumber('image/tiff', [0x49, 0x49, 0x2A, 0x00]), - MagicNumber('image/tiff', [0x4D, 0x4D, 0x00, 0x2A]), - MagicNumber('audio/aac', [0xFF, 0xF1]), - MagicNumber('audio/aac', [0xFF, 0xF9]), - MagicNumber('audio/weba', [0x1A, 0x45, 0xDF, 0xA3]), - MagicNumber('audio/mpeg', [0x49, 0x44, 0x33]), - MagicNumber('audio/mpeg', [0xFF, 0xFB]), - MagicNumber('audio/ogg', [0x4F, 0x70, 0x75]), - MagicNumber('video/3gpp', [ - 0x00, - 0x00, - 0x00, - 0x00, - 0x66, - 0x74, - 0x79, - 0x70, - 0x33, - 0x67, - 0x70, - 0x35 - ], mask: [ - 0xFF, - 0xFF, - 0xFF, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), - MagicNumber('video/mp4', [ - 0x00, - 0x00, - 0x00, - 0x00, - 0x66, - 0x74, - 0x79, - 0x70, - 0x61, - 0x76, - 0x63, - 0x31 - ], mask: [ - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), - MagicNumber('video/mp4', [ - 0x00, - 0x00, - 0x00, - 0x00, - 0x66, - 0x74, - 0x79, - 0x70, - 0x69, - 0x73, - 0x6F, - 0x32 - ], mask: [ - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), - MagicNumber('video/mp4', [ - 0x00, - 0x00, - 0x00, - 0x00, - 0x66, - 0x74, - 0x79, - 0x70, - 0x69, - 0x73, - 0x6F, - 0x6D - ], mask: [ - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), - MagicNumber('video/mp4', [ - 0x00, - 0x00, - 0x00, - 0x00, - 0x66, - 0x74, - 0x79, - 0x70, - 0x6D, - 0x70, - 0x34, - 0x31 - ], mask: [ - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), - MagicNumber('video/mp4', [ - 0x00, - 0x00, - 0x00, - 0x00, - 0x66, - 0x74, - 0x79, - 0x70, - 0x6D, - 0x70, - 0x34, - 0x32 - ], mask: [ - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), - MagicNumber('model/gltf-binary', [0x46, 0x54, 0x6C, 0x67]), - - /// The WebP file format is based on the RIFF document format. - /// -> 4 bytes have the ASCII characters 'R' 'I' 'F' 'F'. - /// -> 4 bytes indicating the size of the file - /// -> 4 bytes have the ASCII characters 'W' 'E' 'B' 'P'. - /// https://developers.google.com/speed/webp/docs/riff_container - MagicNumber('image/webp', [ - 0x52, - 0x49, - 0x46, - 0x46, - 0x00, - 0x00, - 0x00, - 0x00, - 0x57, - 0x45, - 0x42, - 0x50 - ], mask: [ - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), - - MagicNumber('font/woff2', [0x77, 0x4f, 0x46, 0x32]), - - /// High Efficiency Image File Format (ISO/IEC 23008-12). - /// -> 4 bytes indicating the ftyp box length. - /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. - /// -> 4 bytes have the ASCII characters 'h' 'e' 'i' 'c'. - /// https://www.iana.org/assignments/media-types/image/heic - MagicNumber('image/heic', [ - 0x00, - 0x00, - 0x00, - 0x00, - 0x66, - 0x74, - 0x79, - 0x70, - 0x68, - 0x65, - 0x69, - 0x63 - ], mask: [ - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), - - /// -> 4 bytes indicating the ftyp box length. - /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. - /// -> 4 bytes have the ASCII characters 'h' 'e' 'i' 'x'. - MagicNumber('image/heic', [ - 0x00, - 0x00, - 0x00, - 0x00, - 0x66, - 0x74, - 0x79, - 0x70, - 0x68, - 0x65, - 0x69, - 0x78 - ], mask: [ - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), - - /// -> 4 bytes indicating the ftyp box length. - /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. - /// -> 4 bytes have the ASCII characters 'm' 'i' 'f' '1'. - MagicNumber('image/heif', [ - 0x00, - 0x00, - 0x00, - 0x00, - 0x66, - 0x74, - 0x79, - 0x70, - 0x6D, - 0x69, - 0x66, - 0x31 - ], mask: [ - 0x00, - 0x00, - 0x00, - 0x00, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF - ]), -]; diff --git a/pkgs/mime/lib/src/magic_numbers.dart b/pkgs/mime/lib/src/magic_numbers.dart new file mode 100644 index 0000000000..1d7270fe43 --- /dev/null +++ b/pkgs/mime/lib/src/magic_numbers.dart @@ -0,0 +1,154 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:typed_data'; + +const int initialMagicNumbersMaxLength = 12; + +class MagicNumber { + final String mimeType; + final List numbers; + final List? mask; + + const MagicNumber(this.mimeType, this.numbers, {this.mask}); + + bool matches(List header) { + if (header.length < numbers.length) return false; + + for (var i = 0; i < numbers.length; i++) { + if (mask != null) { + if ((mask![i] & numbers[i]) != (mask![i] & header[i])) return false; + } else { + if (numbers[i] != header[i]) return false; + } + } + + return true; + } +} + +final List initialMagicNumbers = [ + MagicNumber('application/pdf', hex('25504446')), + MagicNumber('application/postscript', hex('2551')), + + /// AIFF is based on the EA IFF 85 Standard for Interchange Format Files. + /// -> 4 bytes have the ASCII characters 'F' 'O' 'R' 'M'. + /// -> 4 bytes indicating the size of the file + /// -> 4 bytes have the ASCII characters 'A' 'I' 'F' 'F'. + /// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/Docs/AIFF-1.3.pdf + MagicNumber( + 'audio/x-aiff', + hex('464F524D0000000041494646'), + mask: hex('FFFFFFFF00000000FFFFFFFF'), + ), + + /// -> 4 bytes have the ASCII characters 'f' 'L' 'a' 'C'. + /// https://xiph.org/flac/format.html + MagicNumber('audio/x-flac', hex('664C6143')), + + /// The WAVE file format is based on the RIFF document format. + /// -> 4 bytes have the ASCII characters 'R' 'I' 'F' 'F'. + /// -> 4 bytes indicating the size of the file + /// -> 4 bytes have the ASCII characters 'W' 'A' 'V' 'E'. + /// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/riffmci.pdf + MagicNumber( + 'audio/x-wav', + hex('524946460000000057415645'), + mask: hex('FFFFFFFF00000000FFFFFFFF'), + ), + MagicNumber('image/gif', hex('474946383761')), + MagicNumber('image/gif', hex('474946383961')), + MagicNumber('image/jpeg', hex('FFD8')), + MagicNumber('image/png', hex('89504E470D0A1A0A')), + MagicNumber('image/tiff', hex('49492A00')), + MagicNumber('image/tiff', hex('4D4D002A')), + MagicNumber('audio/aac', hex('FFF1')), + MagicNumber('audio/aac', hex('FFF9')), + MagicNumber('audio/weba', hex('1A45DFA3')), + MagicNumber('audio/mpeg', hex('494433')), + MagicNumber('audio/mpeg', hex('FFFB')), + MagicNumber('audio/ogg', hex('4F7075')), + MagicNumber( + 'video/3gpp', + hex('000000006674797033677035'), + mask: hex('FFFFFF00FFFFFFFFFFFFFFFF'), + ), + MagicNumber( + 'video/mp4', + hex('000000006674797061766331'), + mask: hex('00000000FFFFFFFFFFFFFFFF'), + ), + MagicNumber( + 'video/mp4', + hex('000000006674797069736F32'), + mask: hex('00000000FFFFFFFFFFFFFFFF'), + ), + MagicNumber( + 'video/mp4', + hex('000000006674797069736F6D'), + mask: hex('00000000FFFFFFFFFFFFFFFF'), + ), + MagicNumber( + 'video/mp4', + hex('00000000667479706D703431'), + mask: hex('00000000FFFFFFFFFFFFFFFF'), + ), + MagicNumber( + 'video/mp4', + hex('00000000667479706D703432'), + mask: hex('00000000FFFFFFFFFFFFFFFF'), + ), + MagicNumber('model/gltf-binary', hex('46546C67')), + + /// The WebP file format is based on the RIFF document format. + /// -> 4 bytes have the ASCII characters 'R' 'I' 'F' 'F'. + /// -> 4 bytes indicating the size of the file + /// -> 4 bytes have the ASCII characters 'W' 'E' 'B' 'P'. + /// https://developers.google.com/speed/webp/docs/riff_container + MagicNumber( + 'image/webp', + hex('524946460000000057454250'), + mask: hex('FFFFFFFF00000000FFFFFFFF'), + ), + + MagicNumber('font/woff2', hex('774f4632')), + + /// High Efficiency Image File Format (ISO/IEC 23008-12). + /// -> 4 bytes indicating the ftyp box length. + /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. + /// -> 4 bytes have the ASCII characters 'h' 'e' 'i' 'c'. + /// https://www.iana.org/assignments/media-types/image/heic + MagicNumber( + 'image/heic', + hex('000000006674797068656963'), + mask: hex('00000000FFFFFFFFFFFFFFFF'), + ), + + /// -> 4 bytes indicating the ftyp box length. + /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. + /// -> 4 bytes have the ASCII characters 'h' 'e' 'i' 'x'. + MagicNumber( + 'image/heic', + hex('000000006674797068656978'), + mask: hex('00000000FFFFFFFFFFFFFFFF'), + ), + + /// -> 4 bytes indicating the ftyp box length. + /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. + /// -> 4 bytes have the ASCII characters 'm' 'i' 'f' '1'. + MagicNumber( + 'image/heif', + hex('00000000667479706D696631'), + mask: hex('00000000FFFFFFFFFFFFFFFF'), + ), +]; + +Uint8List hex(String encoded) { + final result = Uint8List(encoded.length ~/ 2); + for (var i = 0; i < result.length; i++) { + final offset = i * 2; + result[i] = int.parse(encoded.substring(offset, offset + 2), radix: 16); + } + return result; +} diff --git a/pkgs/mime/lib/src/mime.dart b/pkgs/mime/lib/src/mime.dart new file mode 100644 index 0000000000..16e4ecd1cf --- /dev/null +++ b/pkgs/mime/lib/src/mime.dart @@ -0,0 +1,35 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'mime_tables.g.dart' show mimeToExtensions; +import 'mime_type.dart'; + +final MimeTypeResolver _globalResolver = MimeTypeResolver(); + +/// The maximum number of bytes needed, to match all default magic-numbers. +int get defaultMagicNumbersMaxLength => _globalResolver.magicNumbersMaxLength; + +/// The default file extension for a given MIME type. +/// +/// If [mimeType] has multiple associated extensions, the returned string is one +/// of those, chosen as the default extension for that MIME type. +/// +/// Returns `null` if [mimeType] is not a recognized and supported MIME type. +String? extensionFromMime(String mimeType) { + return mimeToExtensions[mimeType.toLowerCase()]?.first; +} + +/// Extract the extension from [path] and use that for MIME-type lookup, using +/// the default extension map. +/// +/// If no matching MIME-type was found, `null` is returned. +/// +/// If [headerBytes] is present, a match for known magic-numbers will be +/// performed first. This allows the correct mime-type to be found, even though +/// a file have been saved using the wrong file-name extension. If less than +/// [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't +/// be matched against. +String? lookupMimeType(String path, {List? headerBytes}) { + return _globalResolver.lookup(path, headerBytes: headerBytes); +} diff --git a/pkgs/mime/lib/src/mime_shared.dart b/pkgs/mime/lib/src/mime_shared.dart index 1c98971e90..637bef7e8d 100644 --- a/pkgs/mime/lib/src/mime_shared.dart +++ b/pkgs/mime/lib/src/mime_shared.dart @@ -2,7 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'mime_multipart_transformer.dart'; +import 'multipart_transformer.dart'; class MimeMultipartException implements Exception { final String message; diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/mime_tables.g.dart similarity index 52% rename from pkgs/mime/lib/src/default_extension_map.dart rename to pkgs/mime/lib/src/mime_tables.g.dart index 287c957dc5..61ad8ed1ba 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/mime_tables.g.dart @@ -1,8 +1,830 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -const Map defaultExtensionMap = { +// Generated file - do not edit. + +const Map> mimeToExtensions = { + 'application/andrew-inset': ['ez'], + 'application/applixware': ['aw'], + 'application/atom+xml': ['atom'], + 'application/atomcat+xml': ['atomcat'], + 'application/atomsvc+xml': ['atomsvc'], + 'application/ccxml+xml': ['ccxml'], + 'application/cdmi-capability': ['cdmia'], + 'application/cdmi-container': ['cdmic'], + 'application/cdmi-domain': ['cdmid'], + 'application/cdmi-object': ['cdmio'], + 'application/cdmi-queue': ['cdmiq'], + 'application/cu-seeme': ['cu'], + 'application/davmount+xml': ['davmount'], + 'application/docbook+xml': ['dbk'], + 'application/dssc+der': ['dssc'], + 'application/dssc+xml': ['xdssc'], + 'application/ecmascript': ['ecma'], + 'application/emma+xml': ['emma'], + 'application/epub+zip': ['epub'], + 'application/exi': ['exi'], + 'application/font-tdpfr': ['pfr'], + 'application/gml+xml': ['gml'], + 'application/gpx+xml': ['gpx'], + 'application/gxf': ['gxf'], + 'application/hyperstudio': ['stk'], + 'application/inkml+xml': ['ink', 'inkml'], + 'application/ipfix': ['ipfix'], + 'application/java-archive': ['jar'], + 'application/java-serialized-object': ['ser'], + 'application/java-vm': ['class'], + 'application/json': ['json'], + 'application/jsonml+json': ['jsonml'], + 'application/lost+xml': ['lostxml'], + 'application/mac-binhex40': ['hqx'], + 'application/mac-compactpro': ['cpt'], + 'application/mads+xml': ['mads'], + 'application/marc': ['mrc'], + 'application/marcxml+xml': ['mrcx'], + 'application/mathematica': ['ma', 'nb', 'mb'], + 'application/mathml+xml': ['mathml'], + 'application/mbox': ['mbox'], + 'application/mediaservercontrol+xml': ['mscml'], + 'application/metalink+xml': ['metalink'], + 'application/metalink4+xml': ['meta4'], + 'application/mets+xml': ['mets'], + 'application/mods+xml': ['mods'], + 'application/mp21': ['m21', 'mp21'], + 'application/mp4': ['mp4s'], + 'application/msword': ['doc', 'dot'], + 'application/mxf': ['mxf'], + 'application/octet-stream': [ + 'bin', + 'dms', + 'lrf', + 'mar', + 'so', + 'dist', + 'distz', + 'pkg', + 'bpk', + 'dump', + 'elc', + 'deploy' + ], + 'application/oda': ['oda'], + 'application/oebps-package+xml': ['opf'], + 'application/ogg': ['ogx'], + 'application/omdoc+xml': ['omdoc'], + 'application/onenote': ['onetoc', 'onetoc2', 'onetmp', 'onepkg'], + 'application/oxps': ['oxps'], + 'application/patch-ops-error+xml': ['xer'], + 'application/pdf': ['pdf'], + 'application/pgp-encrypted': ['pgp'], + 'application/pgp-signature': ['asc', 'sig'], + 'application/pics-rules': ['prf'], + 'application/pkcs10': ['p10'], + 'application/pkcs7-mime': ['p7m', 'p7c'], + 'application/pkcs7-signature': ['p7s'], + 'application/pkcs8': ['p8'], + 'application/pkix-attr-cert': ['ac'], + 'application/pkix-cert': ['cer'], + 'application/pkix-crl': ['crl'], + 'application/pkix-pkipath': ['pkipath'], + 'application/pkixcmp': ['pki'], + 'application/pls+xml': ['pls'], + 'application/postscript': ['ai', 'eps', 'ps'], + 'application/prs.cww': ['cww'], + 'application/pskc+xml': ['pskcxml'], + 'application/rdf+xml': ['rdf'], + 'application/reginfo+xml': ['rif'], + 'application/relax-ng-compact-syntax': ['rnc'], + 'application/resource-lists+xml': ['rl'], + 'application/resource-lists-diff+xml': ['rld'], + 'application/rls-services+xml': ['rs'], + 'application/rpki-ghostbusters': ['gbr'], + 'application/rpki-manifest': ['mft'], + 'application/rpki-roa': ['roa'], + 'application/rsd+xml': ['rsd'], + 'application/rss+xml': ['rss'], + 'application/rtf': ['rtf'], + 'application/sbml+xml': ['sbml'], + 'application/scvp-cv-request': ['scq'], + 'application/scvp-cv-response': ['scs'], + 'application/scvp-vp-request': ['spq'], + 'application/scvp-vp-response': ['spp'], + 'application/sdp': ['sdp'], + 'application/set-payment-initiation': ['setpay'], + 'application/set-registration-initiation': ['setreg'], + 'application/shf+xml': ['shf'], + 'application/smil+xml': ['smi', 'smil'], + 'application/sparql-query': ['rq'], + 'application/sparql-results+xml': ['srx'], + 'application/srgs': ['gram'], + 'application/srgs+xml': ['grxml'], + 'application/sru+xml': ['sru'], + 'application/ssdl+xml': ['ssdl'], + 'application/ssml+xml': ['ssml'], + 'application/tei+xml': ['tei', 'teicorpus'], + 'application/thraud+xml': ['tfi'], + 'application/timestamped-data': ['tsd'], + 'application/vnd.3gpp.pic-bw-large': ['plb'], + 'application/vnd.3gpp.pic-bw-small': ['psb'], + 'application/vnd.3gpp.pic-bw-var': ['pvb'], + 'application/vnd.3gpp2.tcap': ['tcap'], + 'application/vnd.3m.post-it-notes': ['pwn'], + 'application/vnd.accpac.simply.aso': ['aso'], + 'application/vnd.accpac.simply.imp': ['imp'], + 'application/vnd.acucobol': ['acu'], + 'application/vnd.acucorp': ['atc', 'acutc'], + 'application/vnd.adobe.air-application-installer-package+zip': ['air'], + 'application/vnd.adobe.formscentral.fcdt': ['fcdt'], + 'application/vnd.adobe.fxp': ['fxp', 'fxpl'], + 'application/vnd.adobe.xdp+xml': ['xdp'], + 'application/vnd.adobe.xfdf': ['xfdf'], + 'application/vnd.ahead.space': ['ahead'], + 'application/vnd.airzip.filesecure.azf': ['azf'], + 'application/vnd.airzip.filesecure.azs': ['azs'], + 'application/vnd.amazon.ebook': ['azw'], + 'application/vnd.americandynamics.acc': ['acc'], + 'application/vnd.amiga.ami': ['ami'], + 'application/vnd.android.package-archive': ['apk'], + 'application/vnd.anser-web-certificate-issue-initiation': ['cii'], + 'application/vnd.anser-web-funds-transfer-initiation': ['fti'], + 'application/vnd.antix.game-component': ['atx'], + 'application/vnd.apple.installer+xml': ['mpkg'], + 'application/vnd.apple.mpegurl': ['m3u8'], + 'application/vnd.aristanetworks.swi': ['swi'], + 'application/vnd.astraea-software.iota': ['iota'], + 'application/vnd.audiograph': ['aep'], + 'application/vnd.blueice.multipass': ['mpm'], + 'application/vnd.bmi': ['bmi'], + 'application/vnd.businessobjects': ['rep'], + 'application/vnd.chemdraw+xml': ['cdxml'], + 'application/vnd.chipnuts.karaoke-mmd': ['mmd'], + 'application/vnd.cinderella': ['cdy'], + 'application/vnd.claymore': ['cla'], + 'application/vnd.cloanto.rp9': ['rp9'], + 'application/vnd.clonk.c4group': ['c4g', 'c4d', 'c4f', 'c4p', 'c4u'], + 'application/vnd.cluetrust.cartomobile-config': ['c11amc'], + 'application/vnd.cluetrust.cartomobile-config-pkg': ['c11amz'], + 'application/vnd.commonspace': ['csp'], + 'application/vnd.contact.cmsg': ['cdbcmsg'], + 'application/vnd.cosmocaller': ['cmc'], + 'application/vnd.crick.clicker': ['clkx'], + 'application/vnd.crick.clicker.keyboard': ['clkk'], + 'application/vnd.crick.clicker.palette': ['clkp'], + 'application/vnd.crick.clicker.template': ['clkt'], + 'application/vnd.crick.clicker.wordbank': ['clkw'], + 'application/vnd.criticaltools.wbs+xml': ['wbs'], + 'application/vnd.ctc-posml': ['pml'], + 'application/vnd.cups-ppd': ['ppd'], + 'application/vnd.curl.car': ['car'], + 'application/vnd.curl.pcurl': ['pcurl'], + 'application/vnd.dart': ['dart'], + 'application/vnd.data-vision.rdz': ['rdz'], + 'application/vnd.dece.data': ['uvf', 'uvvf', 'uvd', 'uvvd'], + 'application/vnd.dece.ttml+xml': ['uvt', 'uvvt'], + 'application/vnd.dece.unspecified': ['uvx', 'uvvx'], + 'application/vnd.dece.zip': ['uvz', 'uvvz'], + 'application/vnd.denovo.fcselayout-link': ['fe_launch'], + 'application/vnd.dna': ['dna'], + 'application/vnd.dolby.mlp': ['mlp'], + 'application/vnd.dpgraph': ['dpg'], + 'application/vnd.dreamfactory': ['dfac'], + 'application/vnd.ds-keypoint': ['kpxx'], + 'application/vnd.dvb.ait': ['ait'], + 'application/vnd.dvb.service': ['svc'], + 'application/vnd.dynageo': ['geo'], + 'application/vnd.ecowin.chart': ['mag'], + 'application/vnd.enliven': ['nml'], + 'application/vnd.epson.esf': ['esf'], + 'application/vnd.epson.msf': ['msf'], + 'application/vnd.epson.quickanime': ['qam'], + 'application/vnd.epson.salt': ['slt'], + 'application/vnd.epson.ssf': ['ssf'], + 'application/vnd.eszigno3+xml': ['es3', 'et3'], + 'application/vnd.ezpix-album': ['ez2'], + 'application/vnd.ezpix-package': ['ez3'], + 'application/vnd.fdf': ['fdf'], + 'application/vnd.fdsn.mseed': ['mseed'], + 'application/vnd.fdsn.seed': ['seed', 'dataless'], + 'application/vnd.flographit': ['gph'], + 'application/vnd.fluxtime.clip': ['ftc'], + 'application/vnd.framemaker': ['fm', 'frame', 'maker', 'book'], + 'application/vnd.frogans.fnc': ['fnc'], + 'application/vnd.frogans.ltf': ['ltf'], + 'application/vnd.fsc.weblaunch': ['fsc'], + 'application/vnd.fujitsu.oasys': ['oas'], + 'application/vnd.fujitsu.oasys2': ['oa2'], + 'application/vnd.fujitsu.oasys3': ['oa3'], + 'application/vnd.fujitsu.oasysgp': ['fg5'], + 'application/vnd.fujitsu.oasysprs': ['bh2'], + 'application/vnd.fujixerox.ddd': ['ddd'], + 'application/vnd.fujixerox.docuworks': ['xdw'], + 'application/vnd.fujixerox.docuworks.binder': ['xbd'], + 'application/vnd.fuzzysheet': ['fzs'], + 'application/vnd.genomatix.tuxedo': ['txd'], + 'application/vnd.geogebra.file': ['ggb'], + 'application/vnd.geogebra.slides': ['ggs'], + 'application/vnd.geogebra.tool': ['ggt'], + 'application/vnd.geometry-explorer': ['gex', 'gre'], + 'application/vnd.geonext': ['gxt'], + 'application/vnd.geoplan': ['g2w'], + 'application/vnd.geospace': ['g3w'], + 'application/vnd.gmx': ['gmx'], + 'application/vnd.google-earth.kml+xml': ['kml'], + 'application/vnd.google-earth.kmz': ['kmz'], + 'application/vnd.grafeq': ['gqf', 'gqs'], + 'application/vnd.groove-account': ['gac'], + 'application/vnd.groove-help': ['ghf'], + 'application/vnd.groove-identity-message': ['gim'], + 'application/vnd.groove-injector': ['grv'], + 'application/vnd.groove-tool-message': ['gtm'], + 'application/vnd.groove-tool-template': ['tpl'], + 'application/vnd.groove-vcard': ['vcg'], + 'application/vnd.hal+xml': ['hal'], + 'application/vnd.handheld-entertainment+xml': ['zmm'], + 'application/vnd.hbci': ['hbci'], + 'application/vnd.hhe.lesson-player': ['les'], + 'application/vnd.hp-hpgl': ['hpgl'], + 'application/vnd.hp-hpid': ['hpid'], + 'application/vnd.hp-hps': ['hps'], + 'application/vnd.hp-jlyt': ['jlt'], + 'application/vnd.hp-pcl': ['pcl'], + 'application/vnd.hp-pclxl': ['pclxl'], + 'application/vnd.hydrostatix.sof-data': ['sfd-hdstx'], + 'application/vnd.ibm.minipay': ['mpy'], + 'application/vnd.ibm.modcap': ['afp', 'listafp', 'list3820'], + 'application/vnd.ibm.rights-management': ['irm'], + 'application/vnd.ibm.secure-container': ['sc'], + 'application/vnd.iccprofile': ['icc', 'icm'], + 'application/vnd.igloader': ['igl'], + 'application/vnd.immervision-ivp': ['ivp'], + 'application/vnd.immervision-ivu': ['ivu'], + 'application/vnd.insors.igm': ['igm'], + 'application/vnd.intercon.formnet': ['xpw', 'xpx'], + 'application/vnd.intergeo': ['i2g'], + 'application/vnd.intu.qbo': ['qbo'], + 'application/vnd.intu.qfx': ['qfx'], + 'application/vnd.ipunplugged.rcprofile': ['rcprofile'], + 'application/vnd.irepository.package+xml': ['irp'], + 'application/vnd.is-xpr': ['xpr'], + 'application/vnd.isac.fcs': ['fcs'], + 'application/vnd.jam': ['jam'], + 'application/vnd.jcp.javame.midlet-rms': ['rms'], + 'application/vnd.jisp': ['jisp'], + 'application/vnd.joost.joda-archive': ['joda'], + 'application/vnd.kahootz': ['ktz', 'ktr'], + 'application/vnd.kde.karbon': ['karbon'], + 'application/vnd.kde.kchart': ['chrt'], + 'application/vnd.kde.kformula': ['kfo'], + 'application/vnd.kde.kivio': ['flw'], + 'application/vnd.kde.kontour': ['kon'], + 'application/vnd.kde.kpresenter': ['kpr', 'kpt'], + 'application/vnd.kde.kspread': ['ksp'], + 'application/vnd.kde.kword': ['kwd', 'kwt'], + 'application/vnd.kenameaapp': ['htke'], + 'application/vnd.kidspiration': ['kia'], + 'application/vnd.kinar': ['kne', 'knp'], + 'application/vnd.koan': ['skp', 'skd', 'skt', 'skm'], + 'application/vnd.kodak-descriptor': ['sse'], + 'application/vnd.las.las+xml': ['lasxml'], + 'application/vnd.llamagraphics.life-balance.desktop': ['lbd'], + 'application/vnd.llamagraphics.life-balance.exchange+xml': ['lbe'], + 'application/vnd.lotus-1-2-3': ['123'], + 'application/vnd.lotus-approach': ['apr'], + 'application/vnd.lotus-freelance': ['pre'], + 'application/vnd.lotus-notes': ['nsf'], + 'application/vnd.lotus-organizer': ['org'], + 'application/vnd.lotus-screencam': ['scm'], + 'application/vnd.lotus-wordpro': ['lwp'], + 'application/vnd.macports.portpkg': ['portpkg'], + 'application/vnd.mcd': ['mcd'], + 'application/vnd.medcalcdata': ['mc1'], + 'application/vnd.mediastation.cdkey': ['cdkey'], + 'application/vnd.mfer': ['mwf'], + 'application/vnd.mfmp': ['mfm'], + 'application/vnd.micrografx.flo': ['flo'], + 'application/vnd.micrografx.igx': ['igx'], + 'application/vnd.mif': ['mif'], + 'application/vnd.mobius.daf': ['daf'], + 'application/vnd.mobius.dis': ['dis'], + 'application/vnd.mobius.mbk': ['mbk'], + 'application/vnd.mobius.mqy': ['mqy'], + 'application/vnd.mobius.msl': ['msl'], + 'application/vnd.mobius.plc': ['plc'], + 'application/vnd.mobius.txf': ['txf'], + 'application/vnd.mophun.application': ['mpn'], + 'application/vnd.mophun.certificate': ['mpc'], + 'application/vnd.mozilla.xul+xml': ['xul'], + 'application/vnd.ms-artgalry': ['cil'], + 'application/vnd.ms-cab-compressed': ['cab'], + 'application/vnd.ms-excel': ['xls', 'xlm', 'xla', 'xlc', 'xlt', 'xlw'], + 'application/vnd.ms-excel.addin.macroenabled.12': ['xlam'], + 'application/vnd.ms-excel.sheet.binary.macroenabled.12': ['xlsb'], + 'application/vnd.ms-excel.sheet.macroenabled.12': ['xlsm'], + 'application/vnd.ms-excel.template.macroenabled.12': ['xltm'], + 'application/vnd.ms-fontobject': ['eot'], + 'application/vnd.ms-htmlhelp': ['chm'], + 'application/vnd.ms-ims': ['ims'], + 'application/vnd.ms-lrm': ['lrm'], + 'application/vnd.ms-officetheme': ['thmx'], + 'application/vnd.ms-pki.seccat': ['cat'], + 'application/vnd.ms-pki.stl': ['stl'], + 'application/vnd.ms-powerpoint': ['ppt', 'pps', 'pot'], + 'application/vnd.ms-powerpoint.addin.macroenabled.12': ['ppam'], + 'application/vnd.ms-powerpoint.presentation.macroenabled.12': ['pptm'], + 'application/vnd.ms-powerpoint.slide.macroenabled.12': ['sldm'], + 'application/vnd.ms-powerpoint.slideshow.macroenabled.12': ['ppsm'], + 'application/vnd.ms-powerpoint.template.macroenabled.12': ['potm'], + 'application/vnd.ms-project': ['mpp', 'mpt'], + 'application/vnd.ms-word.document.macroenabled.12': ['docm'], + 'application/vnd.ms-word.template.macroenabled.12': ['dotm'], + 'application/vnd.ms-works': ['wps', 'wks', 'wcm', 'wdb'], + 'application/vnd.ms-wpl': ['wpl'], + 'application/vnd.ms-xpsdocument': ['xps'], + 'application/vnd.mseq': ['mseq'], + 'application/vnd.musician': ['mus'], + 'application/vnd.muvee.style': ['msty'], + 'application/vnd.mynfc': ['taglet'], + 'application/vnd.neurolanguage.nlu': ['nlu'], + 'application/vnd.nitf': ['ntf', 'nitf'], + 'application/vnd.noblenet-directory': ['nnd'], + 'application/vnd.noblenet-sealer': ['nns'], + 'application/vnd.noblenet-web': ['nnw'], + 'application/vnd.nokia.n-gage.data': ['ngdat'], + 'application/vnd.nokia.n-gage.symbian.install': ['n-gage'], + 'application/vnd.nokia.radio-preset': ['rpst'], + 'application/vnd.nokia.radio-presets': ['rpss'], + 'application/vnd.novadigm.edm': ['edm'], + 'application/vnd.novadigm.edx': ['edx'], + 'application/vnd.novadigm.ext': ['ext'], + 'application/vnd.oasis.opendocument.chart': ['odc'], + 'application/vnd.oasis.opendocument.chart-template': ['otc'], + 'application/vnd.oasis.opendocument.database': ['odb'], + 'application/vnd.oasis.opendocument.formula': ['odf'], + 'application/vnd.oasis.opendocument.formula-template': ['odft'], + 'application/vnd.oasis.opendocument.graphics': ['odg'], + 'application/vnd.oasis.opendocument.graphics-template': ['otg'], + 'application/vnd.oasis.opendocument.image': ['odi'], + 'application/vnd.oasis.opendocument.image-template': ['oti'], + 'application/vnd.oasis.opendocument.presentation': ['odp'], + 'application/vnd.oasis.opendocument.presentation-template': ['otp'], + 'application/vnd.oasis.opendocument.spreadsheet': ['ods'], + 'application/vnd.oasis.opendocument.spreadsheet-template': ['ots'], + 'application/vnd.oasis.opendocument.text': ['odt'], + 'application/vnd.oasis.opendocument.text-master': ['odm'], + 'application/vnd.oasis.opendocument.text-template': ['ott'], + 'application/vnd.oasis.opendocument.text-web': ['oth'], + 'application/vnd.olpc-sugar': ['xo'], + 'application/vnd.oma.dd2+xml': ['dd2'], + 'application/vnd.openofficeorg.extension': ['oxt'], + 'application/vnd.openxmlformats-officedocument.presentationml.presentation': [ + 'pptx' + ], + 'application/vnd.openxmlformats-officedocument.presentationml.slide': [ + 'sldx' + ], + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow': [ + 'ppsx' + ], + 'application/vnd.openxmlformats-officedocument.presentationml.template': [ + 'potx' + ], + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['xlsx'], + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template': [ + 'xltx' + ], + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': [ + 'docx' + ], + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template': [ + 'dotx' + ], + 'application/vnd.osgeo.mapguide.package': ['mgp'], + 'application/vnd.osgi.dp': ['dp'], + 'application/vnd.osgi.subsystem': ['esa'], + 'application/vnd.palm': ['pdb', 'pqa', 'oprc'], + 'application/vnd.pawaafile': ['paw'], + 'application/vnd.pg.format': ['str'], + 'application/vnd.pg.osasli': ['ei6'], + 'application/vnd.picsel': ['efif'], + 'application/vnd.pmi.widget': ['wg'], + 'application/vnd.pocketlearn': ['plf'], + 'application/vnd.powerbuilder6': ['pbd'], + 'application/vnd.previewsystems.box': ['box'], + 'application/vnd.proteus.magazine': ['mgz'], + 'application/vnd.publishare-delta-tree': ['qps'], + 'application/vnd.pvi.ptid1': ['ptid'], + 'application/vnd.quark.quarkxpress': [ + 'qxd', + 'qxt', + 'qwd', + 'qwt', + 'qxl', + 'qxb' + ], + 'application/vnd.realvnc.bed': ['bed'], + 'application/vnd.recordare.musicxml': ['mxl'], + 'application/vnd.recordare.musicxml+xml': ['musicxml'], + 'application/vnd.rig.cryptonote': ['cryptonote'], + 'application/vnd.rim.cod': ['cod'], + 'application/vnd.rn-realmedia': ['rm'], + 'application/vnd.rn-realmedia-vbr': ['rmvb'], + 'application/vnd.route66.link66+xml': ['link66'], + 'application/vnd.sailingtracker.track': ['st'], + 'application/vnd.seemail': ['see'], + 'application/vnd.sema': ['sema'], + 'application/vnd.semd': ['semd'], + 'application/vnd.semf': ['semf'], + 'application/vnd.shana.informed.formdata': ['ifm'], + 'application/vnd.shana.informed.formtemplate': ['itp'], + 'application/vnd.shana.informed.interchange': ['iif'], + 'application/vnd.shana.informed.package': ['ipk'], + 'application/vnd.simtech-mindmapper': ['twd', 'twds'], + 'application/vnd.smaf': ['mmf'], + 'application/vnd.smart.teacher': ['teacher'], + 'application/vnd.solent.sdkm+xml': ['sdkm', 'sdkd'], + 'application/vnd.spotfire.dxp': ['dxp'], + 'application/vnd.spotfire.sfs': ['sfs'], + 'application/vnd.stardivision.calc': ['sdc'], + 'application/vnd.stardivision.draw': ['sda'], + 'application/vnd.stardivision.impress': ['sdd'], + 'application/vnd.stardivision.math': ['smf'], + 'application/vnd.stardivision.writer': ['sdw', 'vor'], + 'application/vnd.stardivision.writer-global': ['sgl'], + 'application/vnd.stepmania.package': ['smzip'], + 'application/vnd.stepmania.stepchart': ['sm'], + 'application/vnd.sun.xml.calc': ['sxc'], + 'application/vnd.sun.xml.calc.template': ['stc'], + 'application/vnd.sun.xml.draw': ['sxd'], + 'application/vnd.sun.xml.draw.template': ['std'], + 'application/vnd.sun.xml.impress': ['sxi'], + 'application/vnd.sun.xml.impress.template': ['sti'], + 'application/vnd.sun.xml.math': ['sxm'], + 'application/vnd.sun.xml.writer': ['sxw'], + 'application/vnd.sun.xml.writer.global': ['sxg'], + 'application/vnd.sun.xml.writer.template': ['stw'], + 'application/vnd.sus-calendar': ['sus', 'susp'], + 'application/vnd.svd': ['svd'], + 'application/vnd.symbian.install': ['sis', 'sisx'], + 'application/vnd.syncml+xml': ['xsm'], + 'application/vnd.syncml.dm+wbxml': ['bdm'], + 'application/vnd.syncml.dm+xml': ['xdm'], + 'application/vnd.tao.intent-module-archive': ['tao'], + 'application/vnd.tcpdump.pcap': ['pcap', 'cap', 'dmp'], + 'application/vnd.tmobile-livetv': ['tmo'], + 'application/vnd.trid.tpt': ['tpt'], + 'application/vnd.triscape.mxs': ['mxs'], + 'application/vnd.trueapp': ['tra'], + 'application/vnd.ufdl': ['ufd', 'ufdl'], + 'application/vnd.uiq.theme': ['utz'], + 'application/vnd.umajin': ['umj'], + 'application/vnd.unity': ['unityweb'], + 'application/vnd.uoml+xml': ['uoml'], + 'application/vnd.vcx': ['vcx'], + 'application/vnd.visio': ['vsd', 'vst', 'vss', 'vsw'], + 'application/vnd.visionary': ['vis'], + 'application/vnd.vsf': ['vsf'], + 'application/vnd.wap.wbxml': ['wbxml'], + 'application/vnd.wap.wmlc': ['wmlc'], + 'application/vnd.wap.wmlscriptc': ['wmlsc'], + 'application/vnd.webturbo': ['wtb'], + 'application/vnd.wolfram.player': ['nbp'], + 'application/vnd.wordperfect': ['wpd'], + 'application/vnd.wqd': ['wqd'], + 'application/vnd.wt.stf': ['stf'], + 'application/vnd.xara': ['xar'], + 'application/vnd.xfdl': ['xfdl'], + 'application/vnd.yamaha.hv-dic': ['hvd'], + 'application/vnd.yamaha.hv-script': ['hvs'], + 'application/vnd.yamaha.hv-voice': ['hvp'], + 'application/vnd.yamaha.openscoreformat': ['osf'], + 'application/vnd.yamaha.openscoreformat.osfpvg+xml': ['osfpvg'], + 'application/vnd.yamaha.smaf-audio': ['saf'], + 'application/vnd.yamaha.smaf-phrase': ['spf'], + 'application/vnd.yellowriver-custom-menu': ['cmp'], + 'application/vnd.zul': ['zir', 'zirz'], + 'application/vnd.zzazz.deck+xml': ['zaz'], + 'application/voicexml+xml': ['vxml'], + 'application/wasm': ['wasm'], + 'application/widget': ['wgt'], + 'application/winhlp': ['hlp'], + 'application/wsdl+xml': ['wsdl'], + 'application/wspolicy+xml': ['wspolicy'], + 'application/x-7z-compressed': ['7z'], + 'application/x-abiword': ['abw'], + 'application/x-ace-compressed': ['ace'], + 'application/x-apple-diskimage': ['dmg'], + 'application/x-authorware-bin': ['aab', 'x32', 'u32', 'vox'], + 'application/x-authorware-map': ['aam'], + 'application/x-authorware-seg': ['aas'], + 'application/x-bcpio': ['bcpio'], + 'application/x-bittorrent': ['torrent'], + 'application/x-blorb': ['blb', 'blorb'], + 'application/x-bzip': ['bz'], + 'application/x-bzip2': ['bz2', 'boz'], + 'application/x-cbr': ['cbr', 'cba', 'cbt', 'cbz', 'cb7'], + 'application/x-cdlink': ['vcd'], + 'application/x-cfs-compressed': ['cfs'], + 'application/x-chat': ['chat'], + 'application/x-chess-pgn': ['pgn'], + 'application/x-conference': ['nsc'], + 'application/x-cpio': ['cpio'], + 'application/x-csh': ['csh'], + 'application/x-debian-package': ['deb', 'udeb'], + 'application/x-dgc-compressed': ['dgc'], + 'application/x-director': [ + 'dir', + 'dcr', + 'dxr', + 'cst', + 'cct', + 'cxt', + 'w3d', + 'fgd', + 'swa' + ], + 'application/x-doom': ['wad'], + 'application/x-dtbncx+xml': ['ncx'], + 'application/x-dtbook+xml': ['dtb'], + 'application/x-dtbresource+xml': ['res'], + 'application/x-dvi': ['dvi'], + 'application/x-envoy': ['evy'], + 'application/x-eva': ['eva'], + 'application/x-font-bdf': ['bdf'], + 'application/x-font-ghostscript': ['gsf'], + 'application/x-font-linux-psf': ['psf'], + 'application/x-font-pcf': ['pcf'], + 'application/x-font-snf': ['snf'], + 'application/x-font-type1': ['pfa', 'pfb', 'pfm', 'afm'], + 'application/x-freearc': ['arc'], + 'application/x-futuresplash': ['spl'], + 'application/x-gca-compressed': ['gca'], + 'application/x-glulx': ['ulx'], + 'application/x-gnumeric': ['gnumeric'], + 'application/x-gramps-xml': ['gramps'], + 'application/x-gtar': ['gtar'], + 'application/x-hdf': ['hdf'], + 'application/x-install-instructions': ['install'], + 'application/x-iso9660-image': ['iso'], + 'application/x-java-jnlp-file': ['jnlp'], + 'application/x-latex': ['latex'], + 'application/x-lzh-compressed': ['lzh', 'lha'], + 'application/x-mie': ['mie'], + 'application/x-mobipocket-ebook': ['prc', 'mobi'], + 'application/x-ms-application': ['application'], + 'application/x-ms-shortcut': ['lnk'], + 'application/x-ms-wmd': ['wmd'], + 'application/x-ms-wmz': ['wmz'], + 'application/x-ms-xbap': ['xbap'], + 'application/x-msaccess': ['mdb'], + 'application/x-msbinder': ['obd'], + 'application/x-mscardfile': ['crd'], + 'application/x-msclip': ['clp'], + 'application/x-msdownload': ['exe', 'dll', 'com', 'bat', 'msi'], + 'application/x-msmediaview': ['mvb', 'm13', 'm14'], + 'application/x-msmetafile': ['wmf', 'wmz', 'emf', 'emz'], + 'application/x-msmoney': ['mny'], + 'application/x-mspublisher': ['pub'], + 'application/x-msschedule': ['scd'], + 'application/x-msterminal': ['trm'], + 'application/x-mswrite': ['wri'], + 'application/x-netcdf': ['nc', 'cdf'], + 'application/x-nzb': ['nzb'], + 'application/x-pkcs12': ['p12', 'pfx'], + 'application/x-pkcs7-certificates': ['p7b', 'spc'], + 'application/x-pkcs7-certreqresp': ['p7r'], + 'application/x-rar-compressed': ['rar'], + 'application/x-research-info-systems': ['ris'], + 'application/x-sh': ['sh'], + 'application/x-shar': ['shar'], + 'application/x-shockwave-flash': ['swf'], + 'application/x-silverlight-app': ['xap'], + 'application/x-sql': ['sql'], + 'application/x-stuffit': ['sit'], + 'application/x-stuffitx': ['sitx'], + 'application/x-subrip': ['srt'], + 'application/x-sv4cpio': ['sv4cpio'], + 'application/x-sv4crc': ['sv4crc'], + 'application/x-t3vm-image': ['t3'], + 'application/x-tads': ['gam'], + 'application/x-tar': ['tar'], + 'application/x-tcl': ['tcl'], + 'application/x-tex': ['tex'], + 'application/x-tex-tfm': ['tfm'], + 'application/x-texinfo': ['texinfo', 'texi'], + 'application/x-tgif': ['obj'], + 'application/x-ustar': ['ustar'], + 'application/x-wais-source': ['src'], + 'application/x-x509-ca-cert': ['der', 'crt'], + 'application/x-xfig': ['fig'], + 'application/x-xliff+xml': ['xlf'], + 'application/x-xpinstall': ['xpi'], + 'application/x-xz': ['xz'], + 'application/x-zmachine': ['z1', 'z2', 'z3', 'z4', 'z5', 'z6', 'z7', 'z8'], + 'application/xaml+xml': ['xaml'], + 'application/xcap-diff+xml': ['xdf'], + 'application/xenc+xml': ['xenc'], + 'application/xhtml+xml': ['xhtml', 'xht'], + 'application/xml': ['xml', 'xsl'], + 'application/xml-dtd': ['dtd'], + 'application/xop+xml': ['xop'], + 'application/xproc+xml': ['xpl'], + 'application/xslt+xml': ['xslt'], + 'application/xspf+xml': ['xspf'], + 'application/xv+xml': ['mxml', 'xhvml', 'xvml', 'xvm'], + 'application/yang': ['yang'], + 'application/yin+xml': ['yin'], + 'application/zip': ['zip'], + 'audio/adpcm': ['adp'], + 'audio/basic': ['au', 'snd'], + 'audio/midi': ['mid', 'midi', 'kar', 'rmi'], + 'audio/mp4': ['m4a', 'mp4a'], + 'audio/mpeg': ['mpga', 'mp2', 'mp2a', 'mp3', 'm2a', 'm3a'], + 'audio/ogg': ['oga', 'ogg', 'spx', 'opus'], + 'audio/s3m': ['s3m'], + 'audio/silk': ['sil'], + 'audio/vnd.dece.audio': ['uva', 'uvva'], + 'audio/vnd.digital-winds': ['eol'], + 'audio/vnd.dra': ['dra'], + 'audio/vnd.dts': ['dts'], + 'audio/vnd.dts.hd': ['dtshd'], + 'audio/vnd.lucent.voice': ['lvp'], + 'audio/vnd.ms-playready.media.pya': ['pya'], + 'audio/vnd.nuera.ecelp4800': ['ecelp4800'], + 'audio/vnd.nuera.ecelp7470': ['ecelp7470'], + 'audio/vnd.nuera.ecelp9600': ['ecelp9600'], + 'audio/vnd.rip': ['rip'], + 'audio/webm': ['weba'], + 'audio/x-aac': ['aac'], + 'audio/x-aiff': ['aif', 'aiff', 'aifc'], + 'audio/x-caf': ['caf'], + 'audio/x-flac': ['flac'], + 'audio/x-matroska': ['mka'], + 'audio/x-mpegurl': ['m3u'], + 'audio/x-ms-wax': ['wax'], + 'audio/x-ms-wma': ['wma'], + 'audio/x-pn-realaudio': ['ram', 'ra'], + 'audio/x-pn-realaudio-plugin': ['rmp'], + 'audio/x-wav': ['wav'], + 'audio/xm': ['xm'], + 'chemical/x-cdx': ['cdx'], + 'chemical/x-cif': ['cif'], + 'chemical/x-cmdf': ['cmdf'], + 'chemical/x-cml': ['cml'], + 'chemical/x-csml': ['csml'], + 'chemical/x-xyz': ['xyz'], + 'font/collection': ['ttc'], + 'font/otf': ['otf'], + 'font/ttf': ['ttf'], + 'font/woff': ['woff'], + 'font/woff2': ['woff2'], + 'image/avif': ['avif'], + 'image/bmp': ['bmp'], + 'image/cgm': ['cgm'], + 'image/g3fax': ['g3'], + 'image/gif': ['gif'], + 'image/ief': ['ief'], + 'image/jpeg': ['jpeg', 'jpg', 'jpe'], + 'image/jxl': ['jxl'], + 'image/ktx': ['ktx'], + 'image/png': ['png'], + 'image/prs.btif': ['btif'], + 'image/sgi': ['sgi'], + 'image/svg+xml': ['svg', 'svgz'], + 'image/tiff': ['tiff', 'tif'], + 'image/vnd.adobe.photoshop': ['psd'], + 'image/vnd.dece.graphic': ['uvi', 'uvvi', 'uvg', 'uvvg'], + 'image/vnd.djvu': ['djvu', 'djv'], + 'image/vnd.dvb.subtitle': ['sub'], + 'image/vnd.dwg': ['dwg'], + 'image/vnd.dxf': ['dxf'], + 'image/vnd.fastbidsheet': ['fbs'], + 'image/vnd.fpx': ['fpx'], + 'image/vnd.fst': ['fst'], + 'image/vnd.fujixerox.edmics-mmr': ['mmr'], + 'image/vnd.fujixerox.edmics-rlc': ['rlc'], + 'image/vnd.ms-modi': ['mdi'], + 'image/vnd.ms-photo': ['wdp'], + 'image/vnd.net-fpx': ['npx'], + 'image/vnd.wap.wbmp': ['wbmp'], + 'image/vnd.xiff': ['xif'], + 'image/webp': ['webp'], + 'image/x-3ds': ['3ds'], + 'image/x-cmu-raster': ['ras'], + 'image/x-cmx': ['cmx'], + 'image/x-freehand': ['fh', 'fhc', 'fh4', 'fh5', 'fh7'], + 'image/x-icon': ['ico'], + 'image/x-mrsid-image': ['sid'], + 'image/x-pcx': ['pcx'], + 'image/x-pict': ['pic', 'pct'], + 'image/x-portable-anymap': ['pnm'], + 'image/x-portable-bitmap': ['pbm'], + 'image/x-portable-graymap': ['pgm'], + 'image/x-portable-pixmap': ['ppm'], + 'image/x-rgb': ['rgb'], + 'image/x-tga': ['tga'], + 'image/x-xbitmap': ['xbm'], + 'image/x-xpixmap': ['xpm'], + 'image/x-xwindowdump': ['xwd'], + 'message/rfc822': ['eml', 'mime'], + 'model/iges': ['igs', 'iges'], + 'model/mesh': ['msh', 'mesh', 'silo'], + 'model/vnd.collada+xml': ['dae'], + 'model/vnd.dwf': ['dwf'], + 'model/vnd.gdl': ['gdl'], + 'model/vnd.gtw': ['gtw'], + 'model/vnd.vtu': ['vtu'], + 'model/vrml': ['wrl', 'vrml'], + 'model/x3d+binary': ['x3db', 'x3dbz'], + 'model/x3d+vrml': ['x3dv', 'x3dvz'], + 'model/x3d+xml': ['x3d', 'x3dz'], + 'text/cache-manifest': ['appcache'], + 'text/calendar': ['ics', 'ifb'], + 'text/css': ['css'], + 'text/csv': ['csv'], + 'text/html': ['html', 'htm'], + 'text/javascript': ['js', 'mjs'], + 'text/markdown': ['md', 'markdown'], + 'text/n3': ['n3'], + 'text/plain': ['txt', 'text', 'conf', 'def', 'list', 'log', 'in'], + 'text/prs.lines.tag': ['dsc'], + 'text/richtext': ['rtx'], + 'text/sgml': ['sgml', 'sgm'], + 'text/tab-separated-values': ['tsv'], + 'text/troff': ['t', 'tr', 'roff', 'man', 'me', 'ms'], + 'text/turtle': ['ttl'], + 'text/uri-list': ['uri', 'uris', 'urls'], + 'text/vcard': ['vcard'], + 'text/vnd.curl': ['curl'], + 'text/vnd.curl.dcurl': ['dcurl'], + 'text/vnd.curl.mcurl': ['mcurl'], + 'text/vnd.curl.scurl': ['scurl'], + 'text/vnd.dvb.subtitle': ['sub'], + 'text/vnd.fly': ['fly'], + 'text/vnd.fmi.flexstor': ['flx'], + 'text/vnd.graphviz': ['gv'], + 'text/vnd.in3d.3dml': ['3dml'], + 'text/vnd.in3d.spot': ['spot'], + 'text/vnd.sun.j2me.app-descriptor': ['jad'], + 'text/vnd.wap.wml': ['wml'], + 'text/vnd.wap.wmlscript': ['wmls'], + 'text/x-asm': ['s', 'asm'], + 'text/x-c': ['c', 'cc', 'cxx', 'cpp', 'h', 'hh', 'dic'], + 'text/x-dart': ['dart'], + 'text/x-fortran': ['f', 'for', 'f77', 'f90'], + 'text/x-java-source': ['java'], + 'text/x-nfo': ['nfo'], + 'text/x-opml': ['opml'], + 'text/x-pascal': ['p', 'pas'], + 'text/x-setext': ['etx'], + 'text/x-sfv': ['sfv'], + 'text/x-uuencode': ['uu'], + 'text/x-vcalendar': ['vcs'], + 'text/x-vcard': ['vcf'], + 'video/3gpp': ['3gp'], + 'video/3gpp2': ['3g2'], + 'video/h261': ['h261'], + 'video/h263': ['h263'], + 'video/h264': ['h264'], + 'video/jpeg': ['jpgv'], + 'video/jpm': ['jpm', 'jpgm'], + 'video/mj2': ['mj2', 'mjp2'], + 'video/mp2t': ['ts', 'm2t', 'm2ts', 'mts'], + 'video/mp4': ['mp4', 'mp4v', 'mpg4'], + 'video/mpeg': ['mpeg', 'mpg', 'mpe', 'm1v', 'm2v'], + 'video/ogg': ['ogv'], + 'video/quicktime': ['qt', 'mov'], + 'video/vnd.dece.hd': ['uvh', 'uvvh'], + 'video/vnd.dece.mobile': ['uvm', 'uvvm'], + 'video/vnd.dece.pd': ['uvp', 'uvvp'], + 'video/vnd.dece.sd': ['uvs', 'uvvs'], + 'video/vnd.dece.video': ['uvv', 'uvvv'], + 'video/vnd.dvb.file': ['dvb'], + 'video/vnd.fvt': ['fvt'], + 'video/vnd.mpegurl': ['mxu', 'm4u'], + 'video/vnd.ms-playready.media.pyv': ['pyv'], + 'video/vnd.uvvu.mp4': ['uvu', 'uvvu'], + 'video/vnd.vivo': ['viv'], + 'video/webm': ['webm'], + 'video/x-f4v': ['f4v'], + 'video/x-fli': ['fli'], + 'video/x-flv': ['flv'], + 'video/x-m4v': ['m4v'], + 'video/x-matroska': ['mkv', 'mk3d', 'mks'], + 'video/x-mng': ['mng'], + 'video/x-ms-asf': ['asf', 'asx'], + 'video/x-ms-vob': ['vob'], + 'video/x-ms-wm': ['wm'], + 'video/x-ms-wmv': ['wmv'], + 'video/x-ms-wmx': ['wmx'], + 'video/x-ms-wvx': ['wvx'], + 'video/x-msvideo': ['avi'], + 'video/x-sgi-movie': ['movie'], + 'video/x-smv': ['smv'], + 'x-conference/x-cooltalk': ['ice'], +}; + +const Map extensionToMime = { '123': 'application/vnd.lotus-1-2-3', '3dml': 'text/vnd.in3d.3dml', '3ds': 'image/x-3ds', @@ -10,7 +832,7 @@ const Map defaultExtensionMap = { '3gp': 'video/3gpp', '7z': 'application/x-7z-compressed', 'aab': 'application/x-authorware-bin', - 'aac': 'audio/aac', + 'aac': 'audio/x-aac', 'aam': 'application/x-authorware-map', 'aas': 'application/x-authorware-seg', 'abw': 'application/x-abiword', @@ -152,7 +974,6 @@ const Map defaultExtensionMap = { 'dataless': 'application/vnd.fdsn.seed', 'davmount': 'application/davmount+xml', 'dbk': 'application/docbook+xml', - 'dcm': 'application/dicom', 'dcr': 'application/x-director', 'dcurl': 'text/vnd.curl.dcurl', 'dd2': 'application/vnd.oma.dd2+xml', @@ -278,12 +1099,11 @@ const Map defaultExtensionMap = { 'geo': 'application/vnd.dynageo', 'gex': 'application/vnd.geometry-explorer', 'ggb': 'application/vnd.geogebra.file', + 'ggs': 'application/vnd.geogebra.slides', 'ggt': 'application/vnd.geogebra.tool', 'ghf': 'application/vnd.groove-help', 'gif': 'image/gif', 'gim': 'application/vnd.groove-identity-message', - 'glb': 'model/gltf-binary', - 'gltf': 'model/gltf+json', 'gml': 'application/gml+xml', 'gmx': 'application/vnd.gmx', 'gnumeric': 'application/x-gnumeric', @@ -310,8 +1130,6 @@ const Map defaultExtensionMap = { 'hal': 'application/vnd.hal+xml', 'hbci': 'application/vnd.hbci', 'hdf': 'application/x-hdf', - 'heic': 'image/heic', - 'heif': 'image/heif', 'hh': 'text/x-c', 'hlp': 'application/winhlp', 'hpgl': 'application/vnd.hp-hpgl', @@ -371,6 +1189,7 @@ const Map defaultExtensionMap = { 'js': 'text/javascript', 'json': 'application/json', 'jsonml': 'application/jsonml+json', + 'jxl': 'image/jxl', 'kar': 'audio/midi', 'karbon': 'application/vnd.kde.karbon', 'kfo': 'application/vnd.kde.kformula', @@ -413,13 +1232,13 @@ const Map defaultExtensionMap = { 'm1v': 'video/mpeg', 'm21': 'application/mp21', 'm2a': 'audio/mpeg', + 'm2t': 'video/mp2t', + 'm2ts': 'video/mp2t', 'm2v': 'video/mpeg', 'm3a': 'audio/mpeg', 'm3u': 'audio/x-mpegurl', 'm3u8': 'application/vnd.apple.mpegurl', - // Source: https://datatracker.ietf.org/doc/html/rfc4337#section-2 'm4a': 'audio/mp4', - 'm4b': 'audio/mp4', 'm4u': 'video/vnd.mpegurl', 'm4v': 'video/x-m4v', 'ma': 'application/mathematica', @@ -428,6 +1247,7 @@ const Map defaultExtensionMap = { 'maker': 'application/vnd.framemaker', 'man': 'text/troff', 'mar': 'application/octet-stream', + 'markdown': 'text/markdown', 'mathml': 'application/mathml+xml', 'mb': 'application/mathematica', 'mbk': 'application/vnd.mobius.mbk', @@ -435,9 +1255,7 @@ const Map defaultExtensionMap = { 'mc1': 'application/vnd.medcalcdata', 'mcd': 'application/vnd.mcd', 'mcurl': 'text/vnd.curl.mcurl', - // https://www.rfc-editor.org/rfc/rfc7763 'md': 'text/markdown', - 'markdown': 'text/markdown', 'mdb': 'application/x-msaccess', 'mdi': 'image/vnd.ms-modi', 'me': 'text/troff', @@ -503,7 +1321,7 @@ const Map defaultExtensionMap = { 'msi': 'application/x-msdownload', 'msl': 'application/vnd.mobius.msl', 'msty': 'application/vnd.muvee.style', - 'mts': 'model/vnd.mts', + 'mts': 'video/mp2t', 'mus': 'application/vnd.musician', 'musicxml': 'application/vnd.recordare.musicxml+xml', 'mvb': 'application/x-msmediaview', @@ -560,11 +1378,12 @@ const Map defaultExtensionMap = { 'opf': 'application/oebps-package+xml', 'opml': 'text/x-opml', 'oprc': 'application/vnd.palm', + 'opus': 'audio/ogg', 'org': 'application/vnd.lotus-organizer', 'osf': 'application/vnd.yamaha.openscoreformat', 'osfpvg': 'application/vnd.yamaha.openscoreformat.osfpvg+xml', 'otc': 'application/vnd.oasis.opendocument.chart-template', - 'otf': 'application/x-font-otf', + 'otf': 'font/otf', 'otg': 'application/vnd.oasis.opendocument.graphics-template', 'oth': 'application/vnd.oasis.opendocument.text-web', 'oti': 'application/vnd.oasis.opendocument.image-template', @@ -812,18 +1631,17 @@ const Map defaultExtensionMap = { 'tif': 'image/tiff', 'tiff': 'image/tiff', 'tmo': 'application/vnd.tmobile-livetv', - // Source: https://toml.io/en/v1.0.0#mime-type - 'toml': 'application/toml', 'torrent': 'application/x-bittorrent', 'tpl': 'application/vnd.groove-tool-template', 'tpt': 'application/vnd.trid.tpt', 'tr': 'text/troff', 'tra': 'application/vnd.trueapp', 'trm': 'application/x-msterminal', + 'ts': 'video/mp2t', 'tsd': 'application/timestamped-data', 'tsv': 'text/tab-separated-values', - 'ttc': 'application/x-font-ttf', - 'ttf': 'application/x-font-ttf', + 'ttc': 'font/collection', + 'ttf': 'font/ttf', 'ttl': 'text/turtle', 'twd': 'application/vnd.simtech-mindmapper', 'twds': 'application/vnd.simtech-mindmapper', @@ -904,8 +1722,6 @@ const Map defaultExtensionMap = { 'wdp': 'image/vnd.ms-photo', 'weba': 'audio/webm', 'webm': 'video/webm', - // Source: https://w3c.github.io/manifest/#media-type-registration - 'webmanifest': 'application/manifest+json', 'webp': 'image/webp', 'wg': 'application/vnd.pmi.widget', 'wgt': 'application/widget', @@ -920,8 +1736,8 @@ const Map defaultExtensionMap = { 'wmlsc': 'application/vnd.wap.wmlscriptc', 'wmv': 'video/x-ms-wmv', 'wmx': 'video/x-ms-wmx', - 'wmz': 'application/x-ms-wmz', - 'woff': 'application/x-font-woff', + 'wmz': 'application/x-msmetafile', + 'woff': 'font/woff', 'woff2': 'font/woff2', 'wpd': 'application/vnd.wordperfect', 'wpl': 'application/vnd.ms-wpl', diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index 9cf9194a14..ae3c3cf1ec 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -2,32 +2,15 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'default_extension_map.dart'; -import 'magic_number.dart'; - -final MimeTypeResolver _globalResolver = MimeTypeResolver(); - -/// The maximum number of bytes needed, to match all default magic-numbers. -int get defaultMagicNumbersMaxLength => _globalResolver.magicNumbersMaxLength; - -/// Extract the extension from [path] and use that for MIME-type lookup, using -/// the default extension map. -/// -/// If no matching MIME-type was found, `null` is returned. -/// -/// If [headerBytes] is present, a match for known magic-numbers will be -/// performed first. This allows the correct mime-type to be found, even though -/// a file have been saved using the wrong file-name extension. If less than -/// [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't -/// be matched against. -String? lookupMimeType(String path, {List? headerBytes}) => - _globalResolver.lookup(path, headerBytes: headerBytes); +import 'magic_numbers.dart'; +import 'mime_tables.g.dart' show extensionToMime, mimeToExtensions; /// MIME-type resolver class, used to customize the lookup of mime-types. class MimeTypeResolver { - final Map _extensionMap = {}; + final Map _extensionToMime = {}; final List _magicNumbers = []; final bool _useDefault; + int _magicNumbersMaxLength; /// Create a new empty [MimeTypeResolver]. @@ -44,6 +27,11 @@ class MimeTypeResolver { /// performing [lookup] with headerBytes present. int get magicNumbersMaxLength => _magicNumbersMaxLength; + @Deprecated('See MimeTypeResolver.lookupMimeType') + String? lookup(String path, {List? headerBytes}) { + return lookupMimeType(path, headerBytes: headerBytes); + } + /// Extract the extension from [path] and use that for MIME-type lookup. /// /// If no matching MIME-type was found, `null` is returned. @@ -53,7 +41,7 @@ class MimeTypeResolver { /// though a file have been saved using the wrong file-name extension. If less /// than [magicNumbersMaxLength] bytes was provided, some magic-numbers won't /// be matched against. - String? lookup(String path, {List? headerBytes}) { + String? lookupMimeType(String path, {List? headerBytes}) { String? result; if (headerBytes != null) { result = _matchMagic(headerBytes, _magicNumbers); @@ -64,19 +52,39 @@ class MimeTypeResolver { } } final ext = _ext(path); - result = _extensionMap[ext]; + result = _extensionToMime[ext]; if (result != null) return result; if (_useDefault) { - result = defaultExtensionMap[ext]; + result = extensionToMime[ext]; if (result != null) return result; } return null; } + /// The default file extension for a given MIME type. + /// + /// If [mimeType] has multiple associated extensions, the returned string is + /// one of those, chosen as the default extension for that MIME type. + /// + /// Returns `null` if [mimeType] is not a recognized and supported MIME type. + String? extensionFromMime(String mimeType) { + if (_useDefault) { + return mimeToExtensions[mimeType.toLowerCase()]?.first; + } + + for (final entry in _extensionToMime.entries) { + if (entry.value == mimeType) { + return entry.key; + } + } + + return null; + } + /// Add a new MIME-type mapping to the [MimeTypeResolver]. If the [extension] /// is already present in the [MimeTypeResolver], it'll be overwritten. void addExtension(String extension, String mimeType) { - _extensionMap[extension] = mimeType; + _extensionToMime[extension] = mimeType; } /// Add a new magic-number mapping to the [MimeTypeResolver]. diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/multipart_stream.dart similarity index 100% rename from pkgs/mime/lib/src/bound_multipart_stream.dart rename to pkgs/mime/lib/src/multipart_stream.dart diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/multipart_transformer.dart similarity index 88% rename from pkgs/mime/lib/src/mime_multipart_transformer.dart rename to pkgs/mime/lib/src/multipart_transformer.dart index 2648d7d886..980b8b95a9 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/multipart_transformer.dart @@ -5,16 +5,15 @@ import 'dart:async'; import 'dart:typed_data'; -import 'bound_multipart_stream.dart'; import 'char_code.dart' as char_code; import 'mime_shared.dart'; +import 'multipart_stream.dart'; Uint8List _getBoundary(String boundary) { final charCodes = boundary.codeUnits; final boundaryList = Uint8List(4 + charCodes.length); - // Set-up the matching boundary preceding it with CRLF and two - // dashes. + // Set-up the matching boundary preceding it with CRLF and two dashes. boundaryList[0] = char_code.cr; boundaryList[1] = char_code.lf; boundaryList[2] = char_code.dash; @@ -24,8 +23,10 @@ Uint8List _getBoundary(String boundary) { } /// Parser for MIME multipart types of data as described in RFC 2046 -/// section 5.1.1. The data is transformed into [MimeMultipart] objects, each -/// of them streaming the multipart data. +/// section 5.1.1. +/// +/// The data is transformed into [MimeMultipart] objects, each of them streaming +/// the multipart data. class MimeMultipartTransformer extends StreamTransformerBase, MimeMultipart> { final List _boundary; diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 31ac74885f..9a48113694 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -17,4 +17,5 @@ environment: dev_dependencies: dart_flutter_team_lints: ^3.0.0 + http: ^1.3.0 test: ^1.16.0 diff --git a/pkgs/mime/test/default_extension_map_test.dart b/pkgs/mime/test/default_extension_map_test.dart index b5539dd483..26f95ef367 100644 --- a/pkgs/mime/test/default_extension_map_test.dart +++ b/pkgs/mime/test/default_extension_map_test.dart @@ -2,13 +2,13 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:mime/src/default_extension_map.dart'; +import 'package:mime/src/mime_tables.g.dart'; import 'package:test/test.dart'; void main() { group('defaultExtensionMap', () { test('keys are lowercase', () { - for (final key in defaultExtensionMap.keys) { + for (final key in extensionToMime.keys) { expect(key, equals(key.toLowerCase())); } }); diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index 40dae6df5f..52971cf451 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -14,7 +14,7 @@ void main() { expect(extensionFromMime('application/pdf'), equals('pdf')); expect(extensionFromMime('application/vnd.ms-excel'), equals('xls')); expect(extensionFromMime('application/xhtml+xml'), equals('xhtml')); - expect(extensionFromMime('image/jpeg'), equals('jpg')); + expect(extensionFromMime('image/jpeg'), equals('jpeg')); expect(extensionFromMime('image/png'), equals('png')); expect(extensionFromMime('text/css'), equals('css')); expect(extensionFromMime('text/html'), equals('html')); diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 23cb34af30..42e44a2f0f 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -5,7 +5,7 @@ import 'dart:math' as math; import 'package:mime/mime.dart'; -import 'package:mime/src/magic_number.dart'; +import 'package:mime/src/magic_numbers.dart'; import 'package:test/test.dart'; void _expectMimeType(String path, String? expectedMimeType, @@ -26,7 +26,6 @@ void main() { _expectMimeType('file.dart', 'text/x-dart'); // Test mixed-case _expectMimeType('file.DaRT', 'text/x-dart'); - _expectMimeType('file.dcm', 'application/dicom'); _expectMimeType('file.html', 'text/html'); _expectMimeType('file.xhtml', 'application/xhtml+xml'); _expectMimeType('file.jpeg', 'image/jpeg'); @@ -44,16 +43,12 @@ void main() { _expectMimeType('file.tif', 'image/tiff'); _expectMimeType('file.webp', 'image/webp'); _expectMimeType('file.mp3', 'audio/mpeg'); - _expectMimeType('file.aac', 'audio/aac'); + _expectMimeType('file.aac', 'audio/x-aac'); _expectMimeType('file.ogg', 'audio/ogg'); _expectMimeType('file.aiff', 'audio/x-aiff'); _expectMimeType('file.m4a', 'audio/mp4'); - _expectMimeType('file.m4b', 'audio/mp4'); - _expectMimeType('file.toml', 'application/toml'); _expectMimeType('file.md', 'text/markdown'); _expectMimeType('file.markdown', 'text/markdown'); - _expectMimeType('file.heif', 'image/heif'); - _expectMimeType('file.heic', 'image/heic'); }); test('unknown-mime-type', () { diff --git a/pkgs/mime/tool/media_types.dart b/pkgs/mime/tool/generate_markdown.dart similarity index 83% rename from pkgs/mime/tool/media_types.dart rename to pkgs/mime/tool/generate_markdown.dart index 8e1684006c..ce6e9d001b 100644 --- a/pkgs/mime/tool/media_types.dart +++ b/pkgs/mime/tool/generate_markdown.dart @@ -2,20 +2,19 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -/// Script to update the `../doc/media_types.md` file from -/// [defaultExtensionMap]. +/// Script to update the `../doc/media_types.md` file. library; import 'dart:io'; import 'package:mime/mime.dart'; -import 'package:mime/src/default_extension_map.dart' show defaultExtensionMap; +import 'package:mime/src/mime_tables.g.dart' show extensionToMime; void main() { // Find all the mime types and extensions. final mimeToExts = >{}; - for (final entry in defaultExtensionMap.entries) { + for (final entry in extensionToMime.entries) { final ext = entry.key; final mime = entry.value; @@ -37,8 +36,8 @@ void main() { final buf = StringBuffer(prefix); buf.writeln(); buf.write(''' -| MIME type | Default | Additional | -| --- | --- | --- | +| MIME type | Default | Additional extensions | +| :--- | :--- | :--- | '''); for (final mime in mimeTypes) { diff --git a/pkgs/mime/tool/update_media_types.dart b/pkgs/mime/tool/update_media_types.dart new file mode 100644 index 0000000000..422adf62a9 --- /dev/null +++ b/pkgs/mime/tool/update_media_types.dart @@ -0,0 +1,110 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:http/http.dart' as http; + +/// Define additions to the base apache/httpd mime set. +/// +/// These are deltas to the base set that make sense in a Dart context +/// (programming environments, Dart implemented web servers, ...). +const Map> mimeAdditions = { + 'text/markdown': ['md', 'markdown'], + 'text/x-dart': ['dart'], +}; + +void main() async { + // https://github.com/apache/httpd/blob/trunk/docs/conf/mime.types + const mimeTypesUrl = + 'https://raw.githubusercontent.com/apache/httpd/refs/heads/trunk/docs/conf/mime.types'; + + print('Reading from $mimeTypesUrl ...'); + final response = await http.get(Uri.parse(mimeTypesUrl)); + + final lines = response.body + .split('\n') + .where((line) => !line.startsWith('#')) + .map((line) => line.trim()) + .where((line) => line.isNotEmpty); + + final extensionToMime = {}; + final mimeToExtensions = >{}; + + final wsRegex = RegExp(' +'); + for (var line in lines) { + line = line.replaceAll('\t', ' ').replaceAll(wsRegex, ' '); + + final segments = line.split(' '); + + final mime = segments[0]; + final extensions = segments.sublist(1); + + mimeToExtensions[mime] = extensions; + for (final ext in extensions) { + extensionToMime[ext] = mime; + } + } + + print('read ${mimeToExtensions.length} mime types.'); + + // Augment the table with additional types. + + for (final entry in mimeAdditions.entries) { + final mime = entry.key; + final extensions = entry.value; + + mimeToExtensions[mime] = extensions; + for (final ext in extensions) { + extensionToMime[ext] = mime; + } + } + + print(''); + + // write mimeToExtensions + final buf = StringBuffer(); + buf.writeln('const Map> mimeToExtensions = {'); + final sortedMimeTypes = mimeToExtensions.keys.toList()..sort(); + for (final mime in sortedMimeTypes) { + final exts = mimeToExtensions[mime]!; + final describe = exts.map((ext) => "'$ext'").join(', '); + buf.writeln(" '$mime': [$describe],"); + } + buf.writeln('};'); + + buf.writeln(); + + // write extensionToMime + buf.writeln('const Map extensionToMime = {'); + final sortedExtensions = extensionToMime.keys.toList()..sort(); + for (final ext in sortedExtensions) { + final mime = extensionToMime[ext]; + buf.writeln(" '$ext': '$mime',"); + } + buf.writeln('};'); + + // Write Dart file. + final out = writeDartFile('mime_tables.g.dart', buf.toString()); + print('wrote ${out.path}.'); +} + +File writeDartFile(String name, String content) { + final file = File.fromUri(Platform.script.resolve('../lib/src/$name')); + + file.writeAsStringSync(''' +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Generated file - do not edit. + +$content +'''); + + // Format the generated file. + Process.runSync(Platform.resolvedExecutable, ['format', file.path]); + + return file; +} From df0d61d5092960bcf98ffbba6bdb0bddab5db439 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 17 Mar 2025 07:47:12 -0700 Subject: [PATCH 2/2] update workflow file --- .github/workflows/mime.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mime.yaml b/.github/workflows/mime.yaml index 03144c4e45..fcc7aab45d 100644 --- a/.github/workflows/mime.yaml +++ b/.github/workflows/mime.yaml @@ -45,6 +45,6 @@ jobs: - name: Run tests run: dart test - - name: "Re run 'dart tool/media_types.dart' to update doc/media_types.md" - run: dart tool/media_types.dart + - name: "Re run 'dart tool/generate_markdown.dart' to update doc/media_types.md" + run: dart tool/generate_markdown.dart - run: git diff --exit-code