├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ ├── github-pages.yml │ ├── test-coverage.yaml │ └── update-mimemap.yml ├── .gitignore ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── mime.R ├── mimeextra.R ├── mimemap.R └── parse.R ├── README.md ├── inst └── NEWS.Rd ├── man ├── guess_type.Rd ├── mimemap.Rd └── parse_multipart.Rd ├── mime.Rproj ├── src ├── init.c └── rawmatch.c ├── tests └── mime.R └── tools └── update.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^\.travis\.yml$ 4 | ^\.github$ 5 | ^NEWS\.md$ 6 | ^tools$ 7 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macOS-latest, r: 'release'} 22 | - {os: windows-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 24 | - {os: ubuntu-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'oldrel'} 26 | 27 | env: 28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 29 | R_KEEP_PKG_SOURCE: yes 30 | 31 | steps: 32 | - uses: actions/checkout@HEAD 33 | 34 | - uses: r-lib/actions/setup-r@HEAD 35 | with: 36 | r-version: ${{ matrix.config.r }} 37 | http-user-agent: ${{ matrix.config.http-user-agent }} 38 | use-public-rspm: true 39 | 40 | - uses: r-lib/actions/setup-r-dependencies@HEAD 41 | with: 42 | extra-packages: any::rcmdcheck 43 | needs: check 44 | 45 | - uses: r-lib/actions/check-r-package@HEAD 46 | with: 47 | upload-snapshots: true 48 | -------------------------------------------------------------------------------- /.github/workflows/github-pages.yml: -------------------------------------------------------------------------------- 1 | name: Build and deploy package site 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | 7 | permissions: 8 | contents: read 9 | pages: write 10 | id-token: write 11 | 12 | jobs: 13 | deploy: 14 | environment: 15 | name: github-pages 16 | url: ${{ steps.deployment.outputs.page_url }} 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: actions/configure-pages@v5 21 | with: 22 | enablement: true 23 | - uses: r-lib/actions/setup-r@HEAD 24 | with: 25 | use-public-rspm: true 26 | - uses: r-lib/actions/setup-r-dependencies@HEAD 27 | - uses: yihui/litedown/site@HEAD 28 | with: 29 | site-dir: 'site' 30 | - uses: actions/upload-pages-artifact@v3 31 | with: 32 | path: 'site' 33 | - id: deployment 34 | uses: actions/deploy-pages@v4 35 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: [main] 4 | pull_request: 5 | branches: [main] 6 | 7 | name: test-coverage 8 | 9 | jobs: 10 | test-coverage: 11 | runs-on: macOS-latest 12 | env: 13 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 14 | steps: 15 | - uses: actions/checkout@HEAD 16 | 17 | - uses: r-lib/actions/setup-r@HEAD 18 | 19 | - uses: r-lib/actions/setup-r-dependencies@HEAD 20 | with: 21 | extra-packages: any::covr 22 | 23 | - name: Test coverage 24 | run: covr::codecov() 25 | shell: Rscript {0} 26 | -------------------------------------------------------------------------------- /.github/workflows/update-mimemap.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: [main] 4 | pull_request: 5 | branches: [main] 6 | workflow_dispatch: 7 | schedule: 8 | - cron: '5 3 1 * *' 9 | 10 | name: Update mimemap 11 | 12 | jobs: 13 | update-mimemap: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@HEAD 18 | 19 | - uses: r-lib/actions/setup-r@HEAD 20 | with: 21 | use-public-rspm: true 22 | 23 | - uses: r-lib/actions/setup-r-dependencies@HEAD 24 | 25 | - run: | 26 | Rscript tools/update.R 27 | echo "OS_INFO=$(uname -sr)" >> $GITHUB_ENV 28 | 29 | - name: Create Pull Request 30 | uses: peter-evans/create-pull-request@v5 31 | with: 32 | title: Update mimemap 33 | body: Update mimemap by running `tools/update.R`. 34 | commit-message: Update mimemap from ${{ env.OS_INFO }} 35 | add-paths: | 36 | R/mimemap.R 37 | R/mimeextra.R 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | src/*.o 5 | src/*.so 6 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: mime 2 | Type: Package 3 | Title: Map Filenames to MIME Types 4 | Version: 0.13.1 5 | Authors@R: c( 6 | person("Yihui", "Xie", role = c("aut", "cre"), email = "xie@yihui.name", comment = c(ORCID = "0000-0003-0645-5666", URL = "https://yihui.org")), 7 | person("Jeffrey", "Horner", role = "ctb"), 8 | person("Beilei", "Bian", role = "ctb") 9 | ) 10 | Description: Guesses the MIME type from a filename extension using the data 11 | derived from /etc/mime.types in UNIX-type systems. 12 | Imports: 13 | tools 14 | License: GPL 15 | URL: https://github.com/yihui/mime 16 | BugReports: https://github.com/yihui/mime/issues 17 | Roxygen: list(markdown = TRUE) 18 | RoxygenNote: 7.3.2 19 | Encoding: UTF-8 20 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(guess_type) 4 | export(mimemap) 5 | export(parse_multipart) 6 | import(utils) 7 | useDynLib(mime, .registration = TRUE) 8 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # CHANGES IN mime VERSION 0.14 2 | 3 | 4 | # CHANGES IN mime VERSION 0.13 5 | 6 | - Synced the MIME types from the latest version of Ubuntu, so that `.wasm` files can be recognized (thanks, @wch, #22). 7 | 8 | # CHANGES IN mime VERSION 0.12 9 | 10 | - Fixed bugs #15 and #16 in `parse_multipart()` (thanks, @michalkouril). 11 | 12 | # CHANGES IN mime VERSION 0.11 13 | 14 | - Removed the unused `LazyData` field in `DESCRIPTION`. 15 | 16 | # CHANGES IN mime VERSION 0.10 17 | 18 | - Add mimetype for OGC GeoPackage (.gpkg extension) (thanks, @eblondel, #14). 19 | 20 | # CHANGES IN mime VERSION 0.9 21 | 22 | - Added the MIME type for .jsonp files (thanks, @clabornd, #11). 23 | 24 | # CHANGES IN mime VERSION 0.8 25 | 26 | - Added the MIME type for .scss files (thanks, @cpsievert, #10). 27 | 28 | # CHANGES IN mime VERSION 0.7 29 | 30 | - Added more types for .Rnw, .Rproj, and .yml files (thanks, @beanumber, #9). 31 | 32 | # CHANGES IN mime VERSION 0.6 33 | 34 | - Updated the MIME types from Ubuntu 18.04. 35 | 36 | # CHANGES IN mime VERSION 0.5 37 | 38 | - the package license was changed from GPL-2 to GPL 39 | 40 | # CHANGES IN mime VERSION 0.4 41 | 42 | - added a new content type: .geojson -> application/vnd.geo+json (thanks, @dmpe, #3) 43 | 44 | - guess_type() may fail on Windows when the file paths are too long (#2) 45 | 46 | # CHANGES IN mime VERSION 0.3 47 | 48 | - added a few more content types 49 | 50 | # CHANGES IN mime VERSION 0.2 51 | 52 | - added a function parse_multipart() to parse multipart form data submitted via HTTP POST 53 | 54 | # CHANGES IN mime VERSION 0.1.2 55 | 56 | - guess_type() returned wrong values for filenames without extensions: it should have used the 'empty' argument. 57 | 58 | # CHANGES IN mime VERSION 0.1.1 59 | 60 | - mime::guess_type() may not work when mime is loaded but not attached, because R does not load the mimemap data in this case. Now mimemap is exported in the package namespace. 61 | 62 | # CHANGES IN mime VERSION 0.1 63 | 64 | - The initial version of mime. The main function is mime::guess_type(). 65 | 66 | -------------------------------------------------------------------------------- /R/mime.R: -------------------------------------------------------------------------------- 1 | #' @import utils 2 | NULL 3 | 4 | #' Tables for mapping filename extensions to MIME types 5 | #' 6 | #' The data `mimemap` is a named character vector that stores the filename 7 | #' extensions and the corresponding MIME types, e.g. `c(html = 'text/html', pdf 8 | #' = 'application/pdf', ...)`. The character vector `mime:::mimeextra` stores 9 | #' some additional types that we know, such as Markdown files (`.md`), or R 10 | #' scripts (`.R`). 11 | #' @docType data 12 | #' @usage NULL 13 | #' @format NULL 14 | #' @source The file `/etc/mime.types` on Debian. 15 | #' @export 16 | #' @examples str(as.list(mimemap)) 17 | #' mimemap['pdf'] 18 | #' mimemap[c('html', 'js', 'css')] 19 | #' # additional MIME types (not exported) 20 | #' mime:::mimeextra 21 | 'mimemap' 22 | 23 | #' Guess the MIME types from filenames 24 | #' 25 | #' Look up in the [`mimemap`] table for the MIME types based on the extensions of 26 | #' the given filenames. 27 | #' @param file a character vector of filenames, or filename extensions 28 | #' @param unknown the MIME type to return when the file extension was not found 29 | #' in the table 30 | #' @param empty the MIME type for files that do not have extensions 31 | #' @param mime_extra a named character vector of the form `c(extension = type)` 32 | #' providing extra MIME types (by default, `mime:::mimeextra`); note this MIME 33 | #' table takes precedence over the standard table [`mimemap`] 34 | #' @param subtype a character vector of MIME subtypes, which should be of the 35 | #' same length as `file` if provided (use an empty character string for a file 36 | #' if we do not want a subtype for it) 37 | #' @examples 38 | #' library(mime) 39 | #' # well-known file types 40 | #' guess_type(c('a/b/c.html', 'd.pdf', 'e.odt', 'foo.docx', 'tex')) 41 | #' # not in the standard table, but in mimeextra 42 | #' guess_type(c('a.md', 'b.R'), mime_extra = NULL) 43 | #' guess_type(c('a.md', 'b.R')) 44 | #' 45 | #' # override the standard MIME table (tex is text/x-tex by default) 46 | #' guess_type('tex', mime_extra = c(tex = 'text/plain')) 47 | #' # unknown extension 'zzz' 48 | #' guess_type('foo.zzz') 49 | #' # force unknown types to be plain text 50 | #' guess_type('foo.zzz', unknown = 'text/plain') 51 | #' 52 | #' # empty file extension 53 | #' guess_type('Makefile') 54 | #' # we know it is a plain text file 55 | #' guess_type('Makefile', empty = 'text/plain') 56 | #' 57 | #' # subtypes 58 | #' guess_type(c('abc.html', 'def.htm'), subtype = c('charset=UTF-8', '')) 59 | #' @export 60 | guess_type = function(file, unknown = 'application/octet-stream', 61 | empty = 'text/plain', mime_extra = mimeextra, subtype = '') { 62 | # TODO: remove this workaround 63 | if ('RestRserve' %in% loadedNamespaces() && packageVersion('RestRserve') <= '1.2.4') 64 | mimemap['js'] = 'application/javascript' 65 | file = basename(file) 66 | # only need 'bar' from 'foo.bar' 67 | file = tools::file_ext(file) 68 | type = unname(c(mime_extra, mimemap)[tolower(file)]) 69 | type[file == ''] = empty 70 | type[is.na(type)] = unknown # unknown file extensions 71 | if (any(i <- subtype != '')) { 72 | if (length(type) != length(file)) 73 | stop("'subtype' must be of the same length as 'file'") 74 | type[i] = paste(type[i], subtype[i], sep = '; ') 75 | } 76 | type 77 | } 78 | 79 | if (.Platform$OS.type == 'windows') basename = function(path) { 80 | if (length(path) == 0) return(path) 81 | tryCatch(base::basename(path), error = function(e) { 82 | vapply(strsplit(path, '[\\/]+'), tail, character(1), 1, USE.NAMES = FALSE) 83 | }) 84 | } 85 | -------------------------------------------------------------------------------- /R/mimeextra.R: -------------------------------------------------------------------------------- 1 | mimeextra = c( 2 | jsonp = "application/javascript", 3 | r = "text/plain", 4 | rd = "text/plain", 5 | rmd = "text/x-markdown", 6 | rnw = "text/x-sweave", 7 | rproj = "text/rstudio", 8 | scss = "text/css" 9 | ) 10 | -------------------------------------------------------------------------------- /R/mimemap.R: -------------------------------------------------------------------------------- 1 | mimemap = c( 2 | `%` = "application/x-trash", 3 | `~` = "application/x-trash", 4 | `123` = "application/vnd.lotus-1-2-3", 5 | `1905.1` = "application/vnd.ieee.1905", 6 | `1clr` = "application/clr", 7 | `1km` = "application/vnd.1000minds.decision-model+xml", 8 | `210` = "application/p21", 9 | `3dm` = "text/vnd.in3d.3dml", 10 | `3dml` = "text/vnd.in3d.3dml", 11 | `3mf` = "application/vnd.ms-3mfdocument", 12 | `3tz` = "application/vnd.maxar.archive.3tz+zip", 13 | `726` = "audio/32kadpcm", 14 | `7z` = "application/x-7z-compressed", 15 | a = "text/vnd.a", 16 | a2l = "application/A2L", 17 | aa3 = "audio/ATRAC3", 18 | aac = "audio/aac", 19 | aal = "audio/ATRAC-ADVANCED-LOSSLESS", 20 | abc = "text/vnd.abc", 21 | abw = "application/x-abiword", 22 | ac = "application/pkix-attr-cert", 23 | ac2 = "application/vnd.banana-accounting", 24 | ac3 = "audio/ac3", 25 | acc = "application/vnd.americandynamics.acc", 26 | acn = "audio/asc", 27 | acu = "application/vnd.acucobol", 28 | acutc = "application/vnd.acucorp", 29 | adts = "audio/aac", 30 | aep = "application/vnd.audiograph", 31 | afp = "application/vnd.afpc.modca", 32 | age = "application/vnd.age", 33 | ahead = "application/vnd.ahead.space", 34 | ai = "application/postscript", 35 | aif = "audio/x-aiff", 36 | aifc = "audio/x-aiff", 37 | aiff = "audio/x-aiff", 38 | aion = "application/vnd.veritone.aion+json", 39 | ait = "application/vnd.dvb.ait", 40 | alc = "chemical/x-alchemy", 41 | ami = "application/vnd.amiga.ami", 42 | aml = "application/AML", 43 | amlx = "application/automationml-amlx+zip", 44 | amr = "audio/AMR", 45 | AMR = "audio/AMR", 46 | anx = "application/annodex", 47 | apex = "application/vnd.apexlang", 48 | apexlang = "application/vnd.apexlang", 49 | apk = "application/vnd.android.package-archive", 50 | apkg = "application/vnd.anki", 51 | apng = "image/apng", 52 | appcache = "text/cache-manifest", 53 | apr = "application/vnd.lotus-approach", 54 | apxml = "application/auth-policy+xml", 55 | arrow = "application/vnd.apache.arrow.file", 56 | arrows = "application/vnd.apache.arrow.stream", 57 | art = "image/x-jg", 58 | artisan = "application/vnd.artisan+json", 59 | asc = "application/pgp-keys", 60 | ascii = "text/vnd.ascii-art", 61 | asf = "application/vnd.ms-asf", 62 | asice = "application/vnd.etsi.asic-e+zip", 63 | asics = "application/vnd.etsi.asic-s+zip", 64 | asn = "chemical/x-ncbi-asn1", 65 | aso = "application/vnd.accpac.simply.aso", 66 | ass = "audio/aac", 67 | at3 = "audio/ATRAC3", 68 | atc = "application/vnd.acucorp", 69 | atf = "application/ATF", 70 | atfx = "application/ATFX", 71 | atom = "application/atom+xml", 72 | atomcat = "application/atomcat+xml", 73 | atomdeleted = "application/atomdeleted+xml", 74 | atomsrv = "application/atomserv+xml", 75 | atomsvc = "application/atomsvc+xml", 76 | atx = "audio/ATRAC-X", 77 | atxml = "application/ATXML", 78 | au = "audio/basic", 79 | auc = "application/tamp-apex-update-confirm", 80 | avci = "image/avci", 81 | avcs = "image/avcs", 82 | avi = "video/x-msvideo", 83 | avif = "image/avif", 84 | awb = "audio/AMR-WB", 85 | AWB = "audio/AMR-WB", 86 | axa = "audio/annodex", 87 | axv = "video/annodex", 88 | azf = "application/vnd.airzip.filesecure.azf", 89 | azs = "application/vnd.airzip.filesecure.azs", 90 | azv = "image/vnd.airzip.accelerator.azv", 91 | azw3 = "application/vnd.amazon.mobi8-ebook", 92 | b = "chemical/x-molconn-Z", 93 | b16 = "image/vnd.pco.b16", 94 | bak = "application/x-trash", 95 | bar = "application/vnd.qualcomm.brew-app-res", 96 | bary = "model/vnd.bary", 97 | bat = "application/x-msdos-program", 98 | bcpio = "application/x-bcpio", 99 | bdm = "application/vnd.syncml.dm+wbxml", 100 | bed = "application/vnd.realvnc.bed", 101 | bh2 = "application/vnd.fujitsu.oasysprs", 102 | bib = "text/x-bibtex", 103 | bik = "video/vnd.radgamettools.bink", 104 | bin = "application/octet-stream", 105 | bk2 = "video/vnd.radgamettools.bink", 106 | bkm = "application/vnd.nervana", 107 | bmed = "multipart/vnd.bint.med-plus", 108 | bmi = "application/vnd.bmi", 109 | bmml = "application/vnd.balsamiq.bmml+xml", 110 | bmp = "image/bmp", 111 | bmpr = "application/vnd.balsamiq.bmpr", 112 | boo = "text/x-boo", 113 | book = "application/x-maker", 114 | box = "application/vnd.previewsystems.box", 115 | bpd = "application/vnd.hbci", 116 | brf = "text/plain", 117 | bsd = "chemical/x-crossfire", 118 | bsp = "model/vnd.valve.source.compiled-map", 119 | btf = "image/prs.btif", 120 | btif = "image/prs.btif", 121 | c = "text/x-csrc", 122 | `c++` = "text/x-c++src", 123 | c11amc = "application/vnd.cluetrust.cartomobile-config", 124 | c11amz = "application/vnd.cluetrust.cartomobile-config-pkg", 125 | c3d = "chemical/x-chem3d", 126 | c3ex = "application/cccex", 127 | c4d = "application/vnd.clonk.c4group", 128 | c4f = "application/vnd.clonk.c4group", 129 | c4g = "application/vnd.clonk.c4group", 130 | c4p = "application/vnd.clonk.c4group", 131 | c4u = "application/vnd.clonk.c4group", 132 | c9r = "application/vnd.cryptomator.encrypted", 133 | c9s = "application/vnd.cryptomator.encrypted", 134 | cab = "application/vnd.ms-cab-compressed", 135 | cac = "chemical/x-cache", 136 | cache = "chemical/x-cache", 137 | cap = "application/vnd.tcpdump.pcap", 138 | car = "application/vnd.ipld.car", 139 | carjson = "application/vnd.eu.kasparian.car+json", 140 | cascii = "chemical/x-cactvs-binary", 141 | cat = "application/vnd.ms-pki.seccat", 142 | cbin = "chemical/x-cactvs-binary", 143 | cbor = "application/cbor", 144 | cbr = "application/vnd.comicbook-rar", 145 | cbz = "application/vnd.comicbook+zip", 146 | cc = "text/x-c++src", 147 | ccc = "text/vnd.net2phone.commcenter.command", 148 | ccmp = "application/ccmp+xml", 149 | ccxml = "application/ccxml+xml", 150 | cda = "application/x-cdf", 151 | cdbcmsg = "application/vnd.contact.cmsg", 152 | cdf = "application/x-cdf", 153 | cdfx = "application/CDFX+XML", 154 | cdkey = "application/vnd.mediastation.cdkey", 155 | cdmia = "application/cdmi-capability", 156 | cdmic = "application/cdmi-container", 157 | cdmid = "application/cdmi-domain", 158 | cdmio = "application/cdmi-object", 159 | cdmiq = "application/cdmi-queue", 160 | cdr = "image/x-coreldraw", 161 | cdt = "image/x-coreldrawtemplate", 162 | cdx = "chemical/x-cdx", 163 | cdxml = "application/vnd.chemdraw+xml", 164 | cdy = "application/vnd.cinderella", 165 | cea = "application/CEA", 166 | cef = "chemical/x-cxf", 167 | cellml = "application/cellml+xml", 168 | cer = "application/pkix-cert", 169 | cgm = "image/cgm", 170 | chm = "application/vnd.ms-htmlhelp", 171 | chrt = "application/vnd.kde.kchart", 172 | cif = "application/vnd.multiad.creator.cif", 173 | cii = "application/vnd.anser-web-certificate-issue-initiation", 174 | cil = "application/vnd.ms-artgalry", 175 | cl = "application/simple-filter+xml", 176 | cla = "application/vnd.claymore", 177 | class = "application/java-vm", 178 | cld = "model/vnd.cld", 179 | clkk = "application/vnd.crick.clicker.keyboard", 180 | clkp = "application/vnd.crick.clicker.palette", 181 | clkt = "application/vnd.crick.clicker.template", 182 | clkw = "application/vnd.crick.clicker.wordbank", 183 | clkx = "application/vnd.crick.clicker", 184 | cls = "text/x-tex", 185 | clue = "application/clue_info+xml", 186 | cmc = "application/vnd.cosmocaller", 187 | cmdf = "chemical/x-cmdf", 188 | cml = "application/cellml+xml", 189 | cmp = "application/vnd.yellowriver-custom-menu", 190 | cmsc = "application/cms", 191 | cnd = "text/jcr-cnd", 192 | cod = "application/vnd.rim.cod", 193 | coffee = "application/vnd.coffeescript", 194 | com = "application/x-msdos-program", 195 | copyright = "text/vnd.debian.copyright", 196 | coswid = "application/swid+cbor", 197 | cpa = "chemical/x-compass", 198 | cpio = "application/x-cpio", 199 | cpkg = "application/vnd.xmpie.cpkg", 200 | cpl = "application/cpl+xml", 201 | cpp = "text/x-c++src", 202 | cpt = "application/mac-compactpro", 203 | CQL = "text/cql", 204 | cr2 = "image/x-canon-cr2", 205 | crl = "application/pkix-crl", 206 | crt = "application/x-x509-ca-cert", 207 | crtr = "application/vnd.multiad.creator", 208 | crw = "image/x-canon-crw", 209 | cryptomator = "application/vnd.cryptomator.vault", 210 | cryptonote = "application/vnd.rig.cryptonote", 211 | csd = "audio/csound", 212 | csf = "chemical/x-cache-csf", 213 | csh = "application/x-csh", 214 | csl = "application/vnd.citationstyles.style+xml", 215 | csm = "chemical/x-csml", 216 | csml = "chemical/x-csml", 217 | csp = "application/vnd.commonspace", 218 | csrattrs = "application/csrattrs", 219 | css = "text/css", 220 | cst = "application/vnd.commonspace", 221 | csv = "text/csv", 222 | csvs = "text/csv-schema", 223 | ctab = "chemical/x-cactvs-binary", 224 | ctx = "chemical/x-ctx", 225 | cu = "application/cu-seeme", 226 | cub = "chemical/x-gaussian-cube", 227 | cuc = "application/tamp-community-update-confirm", 228 | curl = "text/vnd.curl", 229 | cw = "application/prs.cww", 230 | cwl = "application/cwl", 231 | cwl.json = "application/cwl+json", 232 | cww = "application/prs.cww", 233 | cxf = "chemical/x-cxf", 234 | cxx = "text/x-c++src", 235 | d = "text/x-dsrc", 236 | dae = "model/vnd.collada+xml", 237 | daf = "application/vnd.Mobius.DAF", 238 | dart = "application/vnd.dart", 239 | dataless = "application/vnd.fdsn.seed", 240 | davmount = "application/davmount+xml", 241 | dbf = "application/vnd.dbf", 242 | dcd = "application/DCD", 243 | dcm = "application/dicom", 244 | dcr = "application/x-director", 245 | dd2 = "application/vnd.oma.dd2+xml", 246 | ddd = "application/vnd.fujixerox.ddd", 247 | ddeb = "application/vnd.debian.binary-package", 248 | ddf = "application/vnd.syncml.dmddf+xml", 249 | deb = "application/vnd.debian.binary-package", 250 | deploy = "application/octet-stream", 251 | dfac = "application/vnd.dreamfactory", 252 | dif = "video/dv", 253 | diff = "text/x-diff", 254 | dii = "application/DII", 255 | dim = "application/vnd.fastcopy-disk-image", 256 | dir = "application/x-director", 257 | dis = "application/vnd.Mobius.DIS", 258 | dist = "application/vnd.apple.installer+xml", 259 | distz = "application/vnd.apple.installer+xml", 260 | dit = "application/DIT", 261 | dive = "application/vnd.patentdive", 262 | djv = "image/vnd.djvu", 263 | djvu = "image/vnd.djvu", 264 | dl = "application/vnd.datalog", 265 | dll = "application/x-msdos-program", 266 | dls = "audio/dls", 267 | dmg = "application/x-apple-diskimage", 268 | dmp = "application/vnd.tcpdump.pcap", 269 | dms = "text/vnd.DMClientScript", 270 | dna = "application/vnd.dna", 271 | doc = "application/msword", 272 | docjson = "application/vnd.document+json", 273 | docm = "application/vnd.ms-word.document.macroEnabled.12", 274 | docx = "application/vnd.openxmlformats-officedocument.wordprocessingml.document", 275 | dor = "model/vnd.gdl", 276 | dot = "text/vnd.graphviz", 277 | dotm = "application/vnd.ms-word.template.macroEnabled.12", 278 | dotx = "application/vnd.openxmlformats-officedocument.wordprocessingml.template", 279 | dp = "application/vnd.osgi.dp", 280 | dpg = "application/vnd.dpgraph", 281 | dpgraph = "application/vnd.dpgraph", 282 | dpkg = "application/vnd.xmpie.dpkg", 283 | dpx = "image/dpx", 284 | drle = "image/dicom-rle", 285 | dsc = "text/prs.lines.tag", 286 | dsm = "application/vnd.desmume.movie", 287 | dssc = "application/dssc+der", 288 | dtd = "application/xml-dtd", 289 | dts = "audio/vnd.dts", 290 | dtshd = "audio/vnd.dts.hd", 291 | dv = "video/dv", 292 | dvb = "video/vnd.dvb.file", 293 | dvc = "application/dvcs", 294 | dvi = "application/x-dvi", 295 | dwd = "application/atsc-dwd+xml", 296 | dwf = "model/vnd.dwf", 297 | dwg = "image/vnd.dwg", 298 | dx = "chemical/x-jcamp-dx", 299 | dxf = "image/vnd.dxf", 300 | dxp = "application/vnd.spotfire.dxp", 301 | dxr = "application/x-director", 302 | dzr = "application/vnd.dzr", 303 | ebuild = "application/vnd.gentoo.ebuild", 304 | ecelp4800 = "audio/vnd.nuera.ecelp4800", 305 | ecelp7470 = "audio/vnd.nuera.ecelp7470", 306 | ecelp9600 = "audio/vnd.nuera.ecelp9600", 307 | ecig = "application/vnd.evolv.ecig.settings", 308 | ecigprofile = "application/vnd.evolv.ecig.profile", 309 | ecigtheme = "application/vnd.evolv.ecig.theme", 310 | eclass = "application/vnd.gentoo.eclass", 311 | edm = "application/vnd.novadigm.EDM", 312 | edx = "application/vnd.novadigm.EDX", 313 | efi = "application/efi", 314 | efif = "application/vnd.picsel", 315 | ei6 = "application/vnd.pg.osasli", 316 | ELN = "application/vnd.eln+zip", 317 | emb = "chemical/x-embl-dl-nucleotide", 318 | embl = "chemical/x-embl-dl-nucleotide", 319 | emf = "image/emf", 320 | eml = "message/rfc822", 321 | emm = "application/vnd.ibm.electronic-media", 322 | emma = "application/emma+xml", 323 | emotionml = "application/emotionml+xml", 324 | ent = "application/xml-external-parsed-entity", 325 | entity = "application/vnd.nervana", 326 | enw = "audio/EVRCNW", 327 | eol = "audio/vnd.digital-winds", 328 | eot = "application/vnd.ms-fontobject", 329 | ep = "application/vnd.bluetooth.ep.oob", 330 | eps = "application/postscript", 331 | eps2 = "application/postscript", 332 | eps3 = "application/postscript", 333 | epsf = "application/postscript", 334 | epsi = "application/postscript", 335 | epub = "application/epub+zip", 336 | erf = "image/x-epson-erf", 337 | es = "text/javascript", 338 | es3 = "application/vnd.eszigno3+xml", 339 | esa = "application/vnd.osgi.subsystem", 340 | esf = "application/vnd.epson.esf", 341 | espass = "application/vnd.espass-espass+zip", 342 | et3 = "application/vnd.eszigno3+xml", 343 | etx = "text/x-setext", 344 | evb = "audio/EVRCB", 345 | evc = "audio/EVRC", 346 | evw = "audio/EVRCWB", 347 | exe = "application/x-msdos-program", 348 | exi = "application/exi", 349 | exp = "application/express", 350 | exr = "image/aces", 351 | ext = "application/vnd.novadigm.EXT", 352 | ez = "application/andrew-inset", 353 | ez2 = "application/vnd.ezpix-album", 354 | ez3 = "application/vnd.ezpix-package", 355 | fb = "application/x-maker", 356 | fbdoc = "application/x-maker", 357 | fbs = "image/vnd.fastbidsheet", 358 | fcdt = "application/vnd.adobe.formscentral.fcdt", 359 | fch = "chemical/x-gaussian-checkpoint", 360 | fchk = "chemical/x-gaussian-checkpoint", 361 | fcs = "application/vnd.isac.fcs", 362 | fdf = "application/fdf", 363 | fdt = "application/fdt+xml", 364 | fe_launch = "application/vnd.denovo.fcselayout-link", 365 | fg5 = "application/vnd.fujitsu.oasysgp", 366 | fig = "application/x-xfig", 367 | finf = "application/fastinfoset", 368 | fit = "image/fits", 369 | fits = "image/fits", 370 | fla = "application/vnd.dtg.local.flash", 371 | flac = "audio/flac", 372 | flb = "application/vnd.ficlab.flb+zip", 373 | fli = "video/fli", 374 | flo = "application/vnd.micrografx.flo", 375 | flt = "text/vnd.ficlab.flt", 376 | flv = "video/x-flv", 377 | flw = "application/vnd.kde.kivio", 378 | flx = "text/vnd.fmi.flexstor", 379 | fly = "text/vnd.fly", 380 | fm = "application/vnd.framemaker", 381 | fo = "application/vnd.software602.filler.form+xml", 382 | fpx = "image/vnd.fpx", 383 | frame = "application/x-maker", 384 | frm = "application/vnd.ufdl", 385 | fsc = "application/vnd.fsc.weblaunch", 386 | fst = "image/vnd.fst", 387 | ftc = "application/vnd.fluxtime.clip", 388 | fti = "application/vnd.anser-web-funds-transfer-initiation", 389 | fts = "image/fits", 390 | fvt = "video/vnd.fvt", 391 | fxp = "application/vnd.adobe.fxp", 392 | fxpl = "application/vnd.adobe.fxp", 393 | fzs = "application/vnd.fuzzysheet", 394 | g2w = "application/vnd.geoplan", 395 | g3w = "application/vnd.geospace", 396 | gac = "application/vnd.groove-account", 397 | gal = "chemical/x-gaussian-log", 398 | gam = "chemical/x-gamess-input", 399 | gamin = "chemical/x-gamess-input", 400 | gan = "application/x-ganttproject", 401 | gau = "chemical/x-gaussian-input", 402 | gbr = "application/rpki-ghostbusters", 403 | gcd = "text/x-pcs-gcd", 404 | gcf = "application/x-graphing-calculator", 405 | gcg = "chemical/x-gcg8-sequence", 406 | gdl = "model/vnd.gdl", 407 | gdz = "application/vnd.familysearch.gedcom+zip", 408 | ged = "text/vnd.familysearch.gedcom", 409 | gen = "chemical/x-genbank", 410 | genozip = "application/vnd.genozip", 411 | geo = "application/vnd.dynageo", 412 | geojson = "application/geo+json", 413 | gex = "application/vnd.geometry-explorer", 414 | gf = "application/x-tex-gf", 415 | gff3 = "text/gff3", 416 | ggb = "application/vnd.geogebra.file", 417 | ggs = "application/vnd.geogebra.slides", 418 | ggt = "application/vnd.geogebra.tool", 419 | ghf = "application/vnd.groove-help", 420 | gif = "image/gif", 421 | gim = "application/vnd.groove-identity-message", 422 | gjc = "chemical/x-gaussian-input", 423 | gjf = "chemical/x-gaussian-input", 424 | gl = "video/gl", 425 | glb = "model/gltf-binary", 426 | glbin = "application/gltf-buffer", 427 | glbuf = "application/gltf-buffer", 428 | gltf = "model/gltf+json", 429 | gml = "application/gml+xml", 430 | gnumeric = "application/x-gnumeric", 431 | gph = "application/vnd.FloGraphIt", 432 | gpkg = "application/geopackage+sqlite3", 433 | gpkg.tar = "application/vnd.gentoo.gpkg", 434 | gpt = "chemical/x-mopac-graph", 435 | gqf = "application/vnd.grafeq", 436 | gqs = "application/vnd.grafeq", 437 | gram = "application/srgs", 438 | grd = "application/vnd.gentics.grd+json", 439 | gre = "application/vnd.geometry-explorer", 440 | grv = "application/vnd.groove-injector", 441 | grxml = "application/srgs+xml", 442 | gsf = "application/x-font", 443 | gsheet = "application/urc-grpsheet+xml", 444 | gsm = "audio/x-gsm", 445 | gtar = "application/x-gtar", 446 | gtm = "application/vnd.groove-tool-message", 447 | gtw = "model/vnd.gtw", 448 | gv = "text/vnd.graphviz", 449 | gxt = "application/vnd.geonext", 450 | gz = "application/gzip", 451 | h = "text/x-chdr", 452 | `h++` = "text/x-c++hdr", 453 | hal = "application/vnd.hal+xml", 454 | hans = "text/vnd.hans", 455 | hbc = "application/vnd.hbci", 456 | hbci = "application/vnd.hbci", 457 | hdf = "application/x-hdf", 458 | hdr = "image/vnd.radiance", 459 | hdt = "application/vnd.hdt", 460 | heic = "image/heic", 461 | heics = "image/heic-sequence", 462 | heif = "image/heif", 463 | heifs = "image/heif-sequence", 464 | hej2 = "image/hej2k", 465 | held = "application/atsc-held+xml", 466 | hgl = "text/vnd.hgl", 467 | hh = "text/x-c++hdr", 468 | hif = "image/avif", 469 | hin = "chemical/x-hin", 470 | hpgl = "application/vnd.hp-HPGL", 471 | hpi = "application/vnd.hp-hpid", 472 | hpid = "application/vnd.hp-hpid", 473 | hpp = "text/x-c++hdr", 474 | hps = "application/vnd.hp-hps", 475 | hpub = "application/prs.hpub+zip", 476 | hqx = "application/mac-binhex40", 477 | hs = "text/x-haskell", 478 | hsj2 = "image/hsj2", 479 | hsl = "application/vnd.hsl", 480 | hta = "application/hta", 481 | htc = "text/x-component", 482 | htke = "application/vnd.kenameaapp", 483 | htm = "text/html", 484 | html = "text/html", 485 | hvd = "application/vnd.yamaha.hv-dic", 486 | hvp = "application/vnd.yamaha.hv-voice", 487 | hvs = "application/vnd.yamaha.hv-script", 488 | hwp = "application/x-hwp", 489 | hxx = "text/x-c++hdr", 490 | i2g = "application/vnd.intergeo", 491 | ic0 = "application/vnd.commerce-battelle", 492 | ic1 = "application/vnd.commerce-battelle", 493 | ic2 = "application/vnd.commerce-battelle", 494 | ic3 = "application/vnd.commerce-battelle", 495 | ic4 = "application/vnd.commerce-battelle", 496 | ic5 = "application/vnd.commerce-battelle", 497 | ic6 = "application/vnd.commerce-battelle", 498 | ic7 = "application/vnd.commerce-battelle", 499 | ic8 = "application/vnd.commerce-battelle", 500 | ica = "application/x-ica", 501 | icc = "application/vnd.iccprofile", 502 | icd = "application/vnd.commerce-battelle", 503 | icf = "application/vnd.commerce-battelle", 504 | icm = "application/vnd.iccprofile", 505 | ico = "image/vnd.microsoft.icon", 506 | ics = "text/calendar", 507 | ief = "image/ief", 508 | ifb = "text/calendar", 509 | ifc = "application/p21", 510 | ifm = "application/vnd.shana.informed.formdata", 511 | iges = "model/iges", 512 | igl = "application/vnd.igloader", 513 | igm = "application/vnd.insors.igm", 514 | ign = "application/vnd.coreos.ignition+json", 515 | ignition = "application/vnd.coreos.ignition+json", 516 | igs = "model/iges", 517 | igx = "application/vnd.micrografx.igx", 518 | iif = "application/vnd.shana.informed.interchange", 519 | iii = "application/x-iphone", 520 | imf = "application/vnd.imagemeter.folder+zip", 521 | imgcal = "application/vnd.3lightssoftware.imagescal", 522 | imi = "application/vnd.imagemeter.image+zip", 523 | imp = "application/vnd.accpac.simply.imp", 524 | ims = "application/vnd.ms-ims", 525 | imscc = "application/vnd.ims.imsccv1p1", 526 | info = "application/x-info", 527 | ink = "application/inkml+xml", 528 | inkml = "application/inkml+xml", 529 | inp = "chemical/x-gamess-input", 530 | ins = "application/x-internet-signup", 531 | iota = "application/vnd.astraea-software.iota", 532 | ipfix = "application/ipfix", 533 | ipk = "application/vnd.shana.informed.package", 534 | `ipns-record` = "application/vnd.ipfs.ipns-record", 535 | irm = "application/vnd.ibm.rights-management", 536 | irp = "application/vnd.irepository.package+xml", 537 | ism = "model/vnd.gdl", 538 | iso = "application/x-iso9660-image", 539 | isp = "application/x-internet-signup", 540 | ist = "chemical/x-isostar", 541 | istc = "application/vnd.veryant.thin", 542 | istr = "chemical/x-isostar", 543 | isws = "application/vnd.veryant.thin", 544 | itp = "application/vnd.shana.informed.formtemplate", 545 | its = "application/its+xml", 546 | ivp = "application/vnd.immervision-ivp", 547 | ivu = "application/vnd.immervision-ivu", 548 | j2c = "image/j2c", 549 | J2C = "image/j2c", 550 | j2k = "image/j2c", 551 | J2K = "image/j2c", 552 | jad = "text/vnd.sun.j2me.app-descriptor", 553 | jam = "application/vnd.jam", 554 | jar = "application/java-archive", 555 | java = "text/x-java", 556 | jdx = "chemical/x-jcamp-dx", 557 | jpeg = "image/jpeg", 558 | jhc = "image/jphc", 559 | jisp = "application/vnd.jisp", 560 | jls = "image/jls", 561 | jlt = "application/vnd.hp-jlyt", 562 | jmz = "application/x-jmol", 563 | jng = "image/x-jng", 564 | jnlp = "application/x-java-jnlp-file", 565 | joda = "application/vnd.joost.joda-archive", 566 | jp2 = "image/jp2", 567 | jpg = "image/jpeg", 568 | jpe = "image/jpeg", 569 | jpf = "image/jpx", 570 | jfif = "image/jpeg", 571 | jpg2 = "image/jp2", 572 | jpgm = "image/jpm", 573 | jph = "image/jph", 574 | jphc = "image/jphc", 575 | jpm = "image/jpm", 576 | jpx = "image/jpx", 577 | jrd = "application/jrd+json", 578 | js = "text/javascript", 579 | json = "application/json", 580 | `json-patch` = "application/json-patch+json", 581 | jsonld = "application/ld+json", 582 | jsontd = "application/td+json", 583 | jsontm = "application/tm+json", 584 | jt = "model/JT", 585 | jtd = "text/vnd.esmertec.theme-descriptor", 586 | jxl = "image/jxl", 587 | jxr = "image/jxr", 588 | jxra = "image/jxrA", 589 | jxrs = "image/jxrS", 590 | jxs = "image/jxs", 591 | jxsc = "image/jxsc", 592 | jxsi = "image/jxsi", 593 | jxss = "image/jxss", 594 | karbon = "application/vnd.kde.karbon", 595 | kcm = "application/vnd.nervana", 596 | key = "application/pgp-keys", 597 | keynote = "application/vnd.apple.keynote", 598 | kfo = "application/vnd.kde.kformula", 599 | kia = "application/vnd.kidspiration", 600 | kil = "application/x-killustrator", 601 | kin = "chemical/x-kinemage", 602 | kml = "application/vnd.google-earth.kml+xml", 603 | kmz = "application/vnd.google-earth.kmz", 604 | kne = "application/vnd.Kinar", 605 | knp = "application/vnd.Kinar", 606 | kom = "application/vnd.hbci", 607 | kon = "application/vnd.kde.kontour", 608 | koz = "audio/vnd.audiokoz", 609 | kpr = "application/vnd.kde.kpresenter", 610 | kpt = "application/vnd.kde.kpresenter", 611 | ksp = "application/vnd.kde.kspread", 612 | ktr = "application/vnd.kahootz", 613 | ktx = "image/ktx", 614 | ktx2 = "image/ktx2", 615 | ktz = "application/vnd.kahootz", 616 | kwd = "application/vnd.kde.kword", 617 | kwt = "application/vnd.kde.kword", 618 | l16 = "audio/L16", 619 | las = "application/vnd.las", 620 | lasjson = "application/vnd.las.las+json", 621 | lasxml = "application/vnd.las.las+xml", 622 | latex = "application/x-latex", 623 | lbc = "audio/iLBC", 624 | lbd = "application/vnd.llamagraphics.life-balance.desktop", 625 | lbe = "application/vnd.llamagraphics.life-balance.exchange+xml", 626 | lca = "application/vnd.logipipe.circuit+zip", 627 | lcs = "application/vnd.logipipe.circuit+zip", 628 | le = "application/vnd.bluetooth.le.oob", 629 | les = "application/vnd.hhe.lesson-player", 630 | lgr = "application/lgr+xml", 631 | lha = "application/x-lha", 632 | lhs = "text/x-literate-haskell", 633 | lhzd = "application/vnd.belightsoft.lhzd+zip", 634 | lhzl = "application/vnd.belightsoft.lhzl+zip", 635 | lin = "application/bbolin", 636 | line = "application/vnd.nebumind.line", 637 | link66 = "application/vnd.route66.link66+xml", 638 | list3820 = "application/vnd.afpc.modca", 639 | listafp = "application/vnd.afpc.modca", 640 | lmp = "model/vnd.gdl", 641 | loas = "audio/usac", 642 | loom = "application/vnd.loom", 643 | lostsyncxml = "application/lostsync+xml", 644 | lostxml = "application/lost+xml", 645 | lpf = "application/lpf+zip", 646 | lrm = "application/vnd.ms-lrm", 647 | lsf = "video/x-la-asf", 648 | lsx = "video/x-la-asf", 649 | ltx = "text/x-tex", 650 | lvp = "audio/vnd.lucent.voice", 651 | lwp = "application/vnd.lotus-wordpro", 652 | lxf = "application/LXF", 653 | ly = "text/x-lilypond", 654 | lyx = "application/x-lyx", 655 | lzh = "application/x-lzh", 656 | lzx = "application/x-lzx", 657 | m = "application/vnd.wolfram.mathematica.package", 658 | m1v = "video/mpeg", 659 | m21 = "application/mp21", 660 | m2v = "video/mpeg", 661 | m3g = "application/m3g", 662 | m3u = "audio/mpegurl", 663 | m3u8 = "application/vnd.apple.mpegurl", 664 | m4a = "audio/mp4", 665 | m4s = "video/iso.segment", 666 | m4u = "video/vnd.mpegurl", 667 | m4v = "video/mp4", 668 | ma = "application/mathematica", 669 | mads = "application/mads+xml", 670 | maei = "application/mmt-aei+xml", 671 | mag = "application/vnd.ecowin.chart", 672 | mail = "message/rfc822", 673 | maker = "application/x-maker", 674 | man = "application/x-troff-man", 675 | manifest = "text/cache-manifest", 676 | markdown = "text/markdown", 677 | mb = "application/mathematica", 678 | mbk = "application/vnd.Mobius.MBK", 679 | mbox = "application/mbox", 680 | mbsdf = "application/vnd.mdl-mbsdf", 681 | mc1 = "application/vnd.medcalcdata", 682 | mc2 = "text/vnd.senx.warpscript", 683 | mcd = "application/vnd.mcd", 684 | mcif = "chemical/x-mmcif", 685 | mcm = "chemical/x-macmolecule", 686 | md = "text/markdown", 687 | mdb = "application/msaccess", 688 | mdc = "application/vnd.marlin.drm.mdcf", 689 | mdi = "image/vnd.ms-modi", 690 | mdl = "application/vnd.mdl", 691 | me = "application/x-troff-me", 692 | mesh = "model/mesh", 693 | meta4 = "application/metalink4+xml", 694 | mets = "application/mets+xml", 695 | mf4 = "application/MF4", 696 | mfm = "application/vnd.mfmp", 697 | mft = "application/rpki-manifest", 698 | mgp = "application/vnd.osgeo.mapguide.package", 699 | mgz = "application/vnd.proteus.magazine", 700 | mhas = "audio/mhas", 701 | mid = "audio/sp-midi", 702 | mif = "application/vnd.mif", 703 | miz = "text/mizar", 704 | mj2 = "video/mj2", 705 | mjp2 = "video/mj2", 706 | mjs = "text/javascript", 707 | mkv = "video/x-matroska", 708 | ml2 = "application/vnd.sybyl.mol2", 709 | mlp = "audio/vnd.dolby.mlp", 710 | mm = "application/x-freemind", 711 | mmd = "application/vnd.chipnuts.karaoke-mmd", 712 | mmdb = "application/vnd.maxmind.maxmind-db", 713 | mmf = "application/vnd.smaf", 714 | mml = "application/mathml+xml", 715 | mmod = "chemical/x-macromodel-input", 716 | mmr = "image/vnd.fujixerox.edmics-mmr", 717 | mng = "video/x-mng", 718 | moc = "text/x-moc", 719 | mod = "application/xml-dtd", 720 | `model-inter` = "application/vnd.vd-study", 721 | modl = "application/vnd.modl", 722 | mods = "application/mods+xml", 723 | mol = "chemical/x-mdl-molfile", 724 | mol2 = "application/vnd.sybyl.mol2", 725 | moml = "model/vnd.moml+xml", 726 | moo = "chemical/x-mopac-out", 727 | mop = "chemical/x-mopac-input", 728 | mopcrt = "chemical/x-mopac-input", 729 | mov = "video/quicktime", 730 | movie = "video/x-sgi-movie", 731 | mp1 = "audio/mpeg", 732 | mp2 = "audio/mpeg", 733 | mp21 = "application/mp21", 734 | mp3 = "audio/mpeg", 735 | mp4 = "video/mp4", 736 | mpc = "application/vnd.mophun.certificate", 737 | mpd = "application/dash+xml", 738 | mpdd = "application/dashdelta", 739 | mpe = "video/mpeg", 740 | mpeg = "video/mpeg", 741 | mpega = "audio/mpeg", 742 | mpf = "text/vnd.ms-mediapackage", 743 | mpg = "video/mpeg", 744 | mpg4 = "video/mp4", 745 | mpga = "audio/mpeg", 746 | mph = "application/x-comsol", 747 | mpkg = "application/vnd.apple.installer+xml", 748 | mpm = "application/vnd.blueice.multipass", 749 | mpn = "application/vnd.mophun.application", 750 | mpp = "application/vnd.ms-project", 751 | mpt = "application/vnd.ms-project", 752 | mpv = "video/x-matroska", 753 | mpw = "application/vnd.exstream-empower+zip", 754 | mpy = "application/vnd.ibm.MiniPay", 755 | mqy = "application/vnd.Mobius.MQY", 756 | mrc = "application/marc", 757 | mrcx = "application/marcxml+xml", 758 | ms = "application/x-troff-ms", 759 | msa = "application/vnd.msa-disk-image", 760 | msd = "application/vnd.fdsn.mseed", 761 | mseed = "application/vnd.fdsn.mseed", 762 | mseq = "application/vnd.mseq", 763 | msf = "application/vnd.epson.msf", 764 | msh = "model/mesh", 765 | msi = "application/x-msi", 766 | msl = "application/vnd.Mobius.MSL", 767 | msm = "model/vnd.gdl", 768 | msp = "application/octet-stream", 769 | msty = "application/vnd.muvee.style", 770 | msu = "application/octet-stream", 771 | mtl = "model/mtl", 772 | mts = "model/vnd.mts", 773 | multitrack = "audio/vnd.presonus.multitrack", 774 | mus = "application/vnd.musician", 775 | musd = "application/mmt-usd+xml", 776 | mvb = "chemical/x-mopac-vib", 777 | mvt = "application/vnd.mapbox-vector-tile", 778 | mwc = "application/vnd.dpgraph", 779 | mwf = "application/vnd.MFER", 780 | mxf = "application/mxf", 781 | mxi = "application/vnd.vd-study", 782 | mxl = "application/vnd.recordare.musicxml", 783 | mxmf = "audio/mobile-xmf", 784 | mxml = "application/xv+xml", 785 | mxs = "application/vnd.triscape.mxs", 786 | mxu = "video/vnd.mpegurl", 787 | n3 = "text/n3", 788 | nb = "application/vnd.wolfram.mathematica", 789 | nbp = "application/vnd.wolfram.player", 790 | nc = "application/x-netcdf", 791 | ndc = "application/vnd.osa.netdeploy", 792 | ndl = "application/vnd.lotus-notes", 793 | nds = "application/vnd.nintendo.nitro.rom", 794 | nebul = "application/vnd.nebumind.line", 795 | nef = "image/x-nikon-nef", 796 | ngdat = "application/vnd.nokia.n-gage.data", 797 | nim = "video/vnd.nokia.interleaved-multimedia", 798 | nimn = "application/vnd.nimn", 799 | nitf = "application/vnd.nitf", 800 | nlu = "application/vnd.neurolanguage.nlu", 801 | nml = "application/vnd.enliven", 802 | nnd = "application/vnd.noblenet-directory", 803 | nns = "application/vnd.noblenet-sealer", 804 | nnw = "application/vnd.noblenet-web", 805 | notebook = "application/vnd.smart.notebook", 806 | nq = "application/n-quads", 807 | ns2 = "application/vnd.lotus-notes", 808 | ns3 = "application/vnd.lotus-notes", 809 | ns4 = "application/vnd.lotus-notes", 810 | nsf = "application/vnd.lotus-notes", 811 | nsg = "application/vnd.lotus-notes", 812 | nsh = "application/vnd.lotus-notes", 813 | nt = "application/n-triples", 814 | ntf = "application/vnd.lotus-notes", 815 | numbers = "application/vnd.apple.numbers", 816 | nwc = "application/x-nwc", 817 | o = "application/x-object", 818 | oa2 = "application/vnd.fujitsu.oasys2", 819 | oa3 = "application/vnd.fujitsu.oasys3", 820 | oas = "application/vnd.fujitsu.oasys", 821 | ob = "application/vnd.1ob", 822 | obg = "application/vnd.openblox.game-binary", 823 | obgx = "application/vnd.openblox.game+xml", 824 | obj = "model/obj", 825 | oda = "application/ODA", 826 | odb = "application/vnd.oasis.opendocument.base", 827 | odc = "application/vnd.oasis.opendocument.chart", 828 | odd = "application/tei+xml", 829 | odf = "application/vnd.oasis.opendocument.formula", 830 | odg = "application/vnd.oasis.opendocument.graphics", 831 | odi = "application/vnd.oasis.opendocument.image", 832 | odm = "application/vnd.oasis.opendocument.text-master", 833 | odp = "application/vnd.oasis.opendocument.presentation", 834 | ods = "application/vnd.oasis.opendocument.spreadsheet", 835 | odt = "application/vnd.oasis.opendocument.text", 836 | odx = "application/ODX", 837 | oeb = "application/vnd.openeye.oeb", 838 | oga = "audio/ogg", 839 | ogex = "model/vnd.opengex", 840 | ogg = "audio/ogg", 841 | ogv = "video/ogg", 842 | ogx = "application/ogg", 843 | old = "application/x-trash", 844 | omg = "audio/ATRAC3", 845 | one = "application/onenote", 846 | onepkg = "application/onenote", 847 | onetmp = "application/onenote", 848 | onetoc2 = "application/onenote", 849 | opf = "application/oebps-package+xml", 850 | oprc = "application/vnd.palm", 851 | opus = "audio/ogg", 852 | or2 = "application/vnd.lotus-organizer", 853 | or3 = "application/vnd.lotus-organizer", 854 | orc = "audio/csound", 855 | orf = "image/x-olympus-orf", 856 | org = "application/vnd.lotus-organizer", 857 | orq = "application/ocsp-request", 858 | ors = "application/ocsp-response", 859 | osf = "application/vnd.yamaha.openscoreformat", 860 | osm = "application/vnd.openstreetmap.data+xml", 861 | ota = "application/vnd.android.ota", 862 | otc = "application/vnd.oasis.opendocument.chart-template", 863 | otf = "font/otf", 864 | otg = "application/vnd.oasis.opendocument.graphics-template", 865 | oth = "application/vnd.oasis.opendocument.text-web", 866 | oti = "application/vnd.oasis.opendocument.image-template", 867 | otm = "application/vnd.oasis.opendocument.text-master-template", 868 | otp = "application/vnd.oasis.opendocument.presentation-template", 869 | ots = "application/vnd.oasis.opendocument.spreadsheet-template", 870 | ott = "application/vnd.oasis.opendocument.text-template", 871 | ovl = "application/vnd.afpc.modca-overlay", 872 | oxlicg = "application/vnd.oxli.countgraph", 873 | oxps = "application/oxps", 874 | oxt = "application/vnd.openofficeorg.extension", 875 | oza = "application/x-oz-application", 876 | p = "text/x-pascal", 877 | p10 = "application/pkcs10", 878 | p12 = "application/pkcs12", 879 | p21 = "application/p21", 880 | p2p = "application/vnd.wfa.p2p", 881 | p7c = "application/pkcs7-mime", 882 | p7m = "application/pkcs7-mime", 883 | p7r = "application/x-pkcs7-certreqresp", 884 | p7s = "application/pkcs7-signature", 885 | p7z = "application/pkcs7-mime", 886 | p8 = "application/pkcs8", 887 | p8e = "application/pkcs8-encrypted", 888 | pac = "application/x-ns-proxy-autoconfig", 889 | package = "application/vnd.autopackage", 890 | pages = "application/vnd.apple.pages", 891 | pas = "text/x-pascal", 892 | pat = "image/x-coreldrawpattern", 893 | patch = "text/x-diff", 894 | paw = "application/vnd.pawaafile", 895 | pbd = "application/vnd.powerbuilder6", 896 | pbm = "image/x-portable-bitmap", 897 | pcap = "application/vnd.tcpdump.pcap", 898 | pcf = "application/x-font-pcf", 899 | pcf.Z = "application/x-font-pcf", 900 | pcl = "application/vnd.hp-PCL", 901 | pcx = "image/vnd.zbrush.pcx", 902 | pdb = "application/vnd.palm", 903 | pdf = "application/pdf", 904 | pdx = "application/PDX", 905 | pem = "application/pem-certificate-chain", 906 | pfa = "application/x-font", 907 | pfb = "application/x-font", 908 | pfr = "application/font-tdpfr", 909 | pfx = "application/pkcs12", 910 | pgb = "image/vnd.globalgraphics.pgb", 911 | PGB = "image/vnd.globalgraphics.pgb", 912 | pgm = "image/x-portable-graymap", 913 | pgn = "application/vnd.chess-pgn", 914 | pgp = "application/pgp-encrypted", 915 | pil = "application/vnd.piaccess.application-licence", 916 | pk = "application/x-tex-pk", 917 | pkd = "application/vnd.hbci", 918 | pkg = "application/vnd.apple.installer+xml", 919 | pki = "application/pkixcmp", 920 | pkipath = "application/pkix-pkipath", 921 | pl = "text/x-perl", 922 | plb = "application/vnd.3gpp.pic-bw-large", 923 | plc = "application/vnd.Mobius.PLC", 924 | plf = "application/vnd.pocketlearn", 925 | plj = "audio/vnd.everad.plj", 926 | plp = "application/vnd.panoply", 927 | pls = "audio/x-scpls", 928 | pm = "text/x-perl", 929 | pml = "application/vnd.ctc-posml", 930 | png = "image/png", 931 | pnm = "image/x-portable-anymap", 932 | portpkg = "application/vnd.macports.portpkg", 933 | pot = "text/plain", 934 | potm = "application/vnd.ms-powerpoint.template.macroEnabled.12", 935 | potx = "application/vnd.openxmlformats-officedocument.presentationml.template", 936 | ppam = "application/vnd.ms-powerpoint.addin.macroEnabled.12", 937 | ppd = "application/vnd.cups-ppd", 938 | ppkg = "application/vnd.xmpie.ppkg", 939 | ppm = "image/x-portable-pixmap", 940 | pps = "application/vnd.ms-powerpoint", 941 | ppsm = "application/vnd.ms-powerpoint.slideshow.macroEnabled.12", 942 | ppsx = "application/vnd.openxmlformats-officedocument.presentationml.slideshow", 943 | ppt = "application/vnd.ms-powerpoint", 944 | pptm = "application/vnd.ms-powerpoint.presentation.macroEnabled.12", 945 | ppttc = "application/vnd.think-cell.ppttc+json", 946 | pptx = "application/vnd.openxmlformats-officedocument.presentationml.presentation", 947 | pqa = "application/vnd.palm", 948 | prc = "model/prc", 949 | pre = "application/vnd.lotus-freelance", 950 | preminet = "application/vnd.preminet", 951 | prf = "application/pics-rules", 952 | provn = "text/provenance-notation", 953 | provx = "application/provenance+xml", 954 | prt = "chemical/x-ncbi-asn1-ascii", 955 | prz = "application/vnd.lotus-freelance", 956 | ps = "application/postscript", 957 | psb = "application/vnd.3gpp.pic-bw-small", 958 | psd = "image/vnd.adobe.photoshop", 959 | pseg3820 = "application/vnd.afpc.modca", 960 | psfs = "application/vnd.psfs", 961 | psg = "application/vnd.afpc.modca-pagesegment", 962 | psid = "audio/prs.sid", 963 | pskcxml = "application/pskc+xml", 964 | pt = "application/vnd.snesdev-page-table", 965 | pti = "image/prs.pti", 966 | ptid = "application/vnd.pvi.ptid1", 967 | ptrom = "application/vnd.snesdev-page-table", 968 | pub = "application/vnd.exstream-package", 969 | pvb = "application/vnd.3gpp.pic-bw-var", 970 | pwn = "application/vnd.3M.Post-it-Notes", 971 | py = "text/x-python", 972 | pya = "audio/vnd.ms-playready.media.pya", 973 | pyc = "application/x-python-code", 974 | pyo = "application/x-python-code", 975 | pyox = "model/vnd.pytha.pyox", 976 | pyv = "video/vnd.ms-playready.media.pyv", 977 | qam = "application/vnd.epson.quickanime", 978 | qbo = "application/vnd.intu.qbo", 979 | qca = "application/vnd.ericsson.quickcall", 980 | qcall = "application/vnd.ericsson.quickcall", 981 | qcp = "audio/EVRC-QCP", 982 | QCP = "audio/EVRC-QCP", 983 | qfx = "application/vnd.intu.qfx", 984 | qgs = "application/x-qgis", 985 | qps = "application/vnd.publishare-delta-tree", 986 | qt = "video/quicktime", 987 | qtl = "application/x-quicktimeplayer", 988 | quiz = "application/vnd.quobject-quoxdocument", 989 | quox = "application/vnd.quobject-quoxdocument", 990 | qvd = "application/vnd.theqvd", 991 | qwd = "application/vnd.Quark.QuarkXPress", 992 | qwt = "application/vnd.Quark.QuarkXPress", 993 | qxb = "application/vnd.Quark.QuarkXPress", 994 | qxd = "application/vnd.Quark.QuarkXPress", 995 | qxl = "application/vnd.Quark.QuarkXPress", 996 | qxt = "application/vnd.Quark.QuarkXPress", 997 | ra = "audio/x-pn-realaudio", 998 | ram = "audio/x-pn-realaudio", 999 | rapd = "application/route-apd+xml", 1000 | rar = "application/vnd.rar", 1001 | ras = "image/x-cmu-raster", 1002 | rb = "application/x-ruby", 1003 | rcprofile = "application/vnd.ipunplugged.rcprofile", 1004 | rct = "application/prs.nprend", 1005 | rd = "chemical/x-mdl-rdfile", 1006 | rdf = "application/rdf+xml", 1007 | `rdf-crypt` = "application/prs.rdf-xml-crypt", 1008 | rdp = "application/x-rdp", 1009 | rdz = "application/vnd.data-vision.rdz", 1010 | relo = "application/p2p-overlay+xml", 1011 | reload = "application/vnd.resilient.logic", 1012 | rep = "application/vnd.businessobjects", 1013 | request = "application/vnd.nervana", 1014 | rfcxml = "application/rfc+xml", 1015 | rgb = "image/x-rgb", 1016 | rgbe = "image/vnd.radiance", 1017 | rif = "application/reginfo+xml", 1018 | rip = "audio/vnd.rip", 1019 | rl = "application/resource-lists+xml", 1020 | rlc = "image/vnd.fujixerox.edmics-rlc", 1021 | rld = "application/resource-lists-diff+xml", 1022 | rlm = "application/vnd.resilient.logic", 1023 | rm = "audio/x-pn-realaudio", 1024 | rms = "application/vnd.jcp.javame.midlet-rms", 1025 | rnc = "application/relax-ng-compact-syntax", 1026 | rnd = "application/prs.nprend", 1027 | roa = "application/rpki-roa", 1028 | roff = "text/troff", 1029 | ros = "chemical/x-rosdal", 1030 | rp9 = "application/vnd.cloanto.rp9", 1031 | rpm = "application/x-redhat-package-manager", 1032 | rpss = "application/vnd.nokia.radio-presets", 1033 | rpst = "application/vnd.nokia.radio-preset", 1034 | rq = "application/sparql-query", 1035 | rs = "application/rls-services+xml", 1036 | rsat = "application/atsc-rsat+xml", 1037 | rsheet = "application/urc-ressheet+xml", 1038 | rsm = "model/vnd.gdl", 1039 | rss = "application/x-rss+xml", 1040 | rst = "text/prs.fallenstein.rst", 1041 | rtf = "application/rtf", 1042 | rusd = "application/route-usd+xml", 1043 | rxn = "chemical/x-mdl-rxnfile", 1044 | rxt = "application/vnd.medicalholodeck.recordxr", 1045 | s11 = "video/vnd.sealed.mpeg1", 1046 | s14 = "video/vnd.sealed.mpeg4", 1047 | s1a = "application/vnd.sealedmedia.softseal.pdf", 1048 | s1e = "application/vnd.sealed.xls", 1049 | s1g = "image/vnd.sealedmedia.softseal.gif", 1050 | s1h = "application/vnd.sealedmedia.softseal.html", 1051 | s1j = "image/vnd.sealedmedia.softseal.jpg", 1052 | s1m = "audio/vnd.sealedmedia.softseal.mpeg", 1053 | s1n = "image/vnd.sealed.png", 1054 | s1p = "application/vnd.sealed.ppt", 1055 | s1q = "video/vnd.sealedmedia.softseal.mov", 1056 | s1w = "application/vnd.sealed.doc", 1057 | s3df = "application/vnd.sealed.3df", 1058 | sac = "application/tamp-sequence-adjust-confirm", 1059 | saf = "application/vnd.yamaha.smaf-audio", 1060 | sam = "application/vnd.lotus-wordpro", 1061 | SAR = "application/vnd.sar", 1062 | sarif = "application/sarif+json", 1063 | `sarif-external-properties` = "application/sarif-external-properties+json", 1064 | `sarif-external-properties.json` = "application/sarif-external-properties+json", 1065 | sarif.json = "application/sarif+json", 1066 | sc = "application/vnd.ibm.secure-container", 1067 | scala = "text/x-scala", 1068 | scd = "application/vnd.scribus", 1069 | sce = "application/vnd.etsi.asic-e+zip", 1070 | sci = "application/x-scilab", 1071 | scim = "application/scim+json", 1072 | scl = "application/vnd.sycle+xml", 1073 | scld = "application/vnd.doremir.scorecloud-binary-document", 1074 | scm = "application/vnd.lotus-screencam", 1075 | sco = "audio/csound", 1076 | scq = "application/scvp-cv-request", 1077 | scr = "application/x-silverlight", 1078 | scs = "application/scvp-cv-response", 1079 | scsf = "application/vnd.sealed.csf", 1080 | sd = "chemical/x-mdl-sdfile", 1081 | sd2 = "audio/x-sd2", 1082 | sda = "application/vnd.stardivision.draw", 1083 | sdc = "application/vnd.stardivision.calc", 1084 | sdd = "application/vnd.stardivision.impress", 1085 | sdf = "application/vnd.Kinar", 1086 | sdkd = "application/vnd.solent.sdkm+xml", 1087 | sdkm = "application/vnd.solent.sdkm+xml", 1088 | sdo = "application/vnd.sealed.doc", 1089 | sdoc = "application/vnd.sealed.doc", 1090 | sdp = "application/sdp", 1091 | sds = "application/vnd.stardivision.chart", 1092 | sdw = "application/vnd.stardivision.writer", 1093 | see = "application/vnd.seemail", 1094 | seed = "application/vnd.fdsn.seed", 1095 | sem = "application/vnd.sealed.eml", 1096 | sema = "application/vnd.sema", 1097 | semd = "application/vnd.semd", 1098 | semf = "application/vnd.semf", 1099 | seml = "application/vnd.sealed.eml", 1100 | senml = "application/senml+json", 1101 | `senml-etchc` = "application/senml-etch+cbor", 1102 | `senml-etchj` = "application/senml-etch+json", 1103 | senmlc = "application/senml+cbor", 1104 | senmle = "application/senml-exi", 1105 | senmlx = "application/senml+xml", 1106 | sensml = "application/sensml+json", 1107 | sensmlc = "application/sensml+cbor", 1108 | sensmle = "application/sensml-exi", 1109 | sensmlx = "application/sensml+xml", 1110 | ser = "application/java-serialized-object", 1111 | sfc = "application/vnd.nintendo.snes.rom", 1112 | sfd = "application/vnd.font-fontforge-sfd", 1113 | `sfd-hdstx` = "application/vnd.hydrostatix.sof-data", 1114 | sfs = "application/vnd.spotfire.sfs", 1115 | sfv = "text/x-sfv", 1116 | sgf = "application/x-go-sgf", 1117 | sgi = "image/vnd.sealedmedia.softseal.gif", 1118 | sgif = "image/vnd.sealedmedia.softseal.gif", 1119 | sgl = "application/vnd.stardivision.writer-global", 1120 | sgm = "text/SGML", 1121 | sgml = "text/SGML", 1122 | sh = "application/x-sh", 1123 | shaclc = "text/shaclc", 1124 | shar = "application/x-shar", 1125 | shc = "text/shaclc", 1126 | shex = "text/shex", 1127 | shf = "application/shf+xml", 1128 | shp = "application/vnd.shp", 1129 | shtml = "text/html", 1130 | shx = "application/vnd.shx", 1131 | si = "text/vnd.wap.si", 1132 | sic = "application/vnd.wap.sic", 1133 | sid = "audio/prs.sid", 1134 | sieve = "application/sieve", 1135 | sig = "application/pgp-signature", 1136 | sik = "application/x-trash", 1137 | silo = "model/mesh", 1138 | sipa = "application/vnd.smintio.portals.archive", 1139 | sis = "application/vnd.symbian.install", 1140 | sit = "application/x-stuffit", 1141 | sitx = "application/x-stuffit", 1142 | siv = "application/sieve", 1143 | sjp = "image/vnd.sealedmedia.softseal.jpg", 1144 | sjpg = "image/vnd.sealedmedia.softseal.jpg", 1145 | skd = "application/vnd.koan", 1146 | skm = "application/vnd.koan", 1147 | skp = "application/vnd.koan", 1148 | skt = "application/vnd.koan", 1149 | sl = "text/vnd.wap.sl", 1150 | sla = "application/vnd.scribus", 1151 | slaz = "application/vnd.scribus", 1152 | slc = "application/vnd.wap.slc", 1153 | sldm = "application/vnd.ms-powerpoint.slide.macroEnabled.12", 1154 | sldx = "application/vnd.openxmlformats-officedocument.presentationml.slide", 1155 | sls = "application/route-s-tsid+xml", 1156 | slt = "application/vnd.epson.salt", 1157 | sm = "application/vnd.stepmania.stepchart", 1158 | smc = "application/vnd.nintendo.snes.rom", 1159 | smf = "application/vnd.stardivision.math", 1160 | smh = "application/vnd.sealed.mht", 1161 | smht = "application/vnd.sealed.mht", 1162 | smi = "application/smil+xml", 1163 | smil = "application/smil+xml", 1164 | smk = "video/vnd.radgamettools.smacker", 1165 | sml = "application/smil+xml", 1166 | smo = "video/vnd.sealedmedia.softseal.mov", 1167 | smov = "video/vnd.sealedmedia.softseal.mov", 1168 | smp = "audio/vnd.sealedmedia.softseal.mpeg", 1169 | smp3 = "audio/vnd.sealedmedia.softseal.mpeg", 1170 | smpg = "video/vnd.sealed.mpeg1", 1171 | sms = "application/vnd.3gpp2.sms", 1172 | smv = "audio/SMV", 1173 | smzip = "application/vnd.stepmania.package", 1174 | snd = "audio/basic", 1175 | soa = "text/dns", 1176 | soc = "application/sgml-open-catalog", 1177 | sofa = "audio/sofa", 1178 | sos = "text/vnd.sosi", 1179 | spc = "chemical/x-galactic-spc", 1180 | spd = "application/vnd.sealedmedia.softseal.pdf", 1181 | spdf = "application/vnd.sealedmedia.softseal.pdf", 1182 | spdx = "text/spdx", 1183 | spdx.json = "application/spdx+json", 1184 | spf = "application/vnd.yamaha.smaf-phrase", 1185 | spl = "application/futuresplash", 1186 | spn = "image/vnd.sealed.png", 1187 | spng = "image/vnd.sealed.png", 1188 | spo = "text/vnd.in3d.spot", 1189 | spot = "text/vnd.in3d.spot", 1190 | spp = "application/scvp-vp-response", 1191 | sppt = "application/vnd.sealed.ppt", 1192 | spq = "application/scvp-vp-request", 1193 | spx = "audio/ogg", 1194 | sql = "application/sql", 1195 | sqlite = "application/vnd.sqlite3", 1196 | sqlite3 = "application/vnd.sqlite3", 1197 | sr = "application/vnd.sigrok.session", 1198 | src = "application/x-wais-source", 1199 | srt = "text/plain", 1200 | sru = "application/sru+xml", 1201 | srx = "application/sparql-results+xml", 1202 | sse = "application/vnd.kodak-descriptor", 1203 | ssf = "application/vnd.epson.ssf", 1204 | ssml = "application/ssml+xml", 1205 | ssv = "application/vnd.shade-save-file", 1206 | ssvc = "application/vnd.crypto-shade-file", 1207 | ssw = "video/vnd.sealed.swf", 1208 | sswf = "video/vnd.sealed.swf", 1209 | st = "application/vnd.sailingtracker.track", 1210 | stc = "application/vnd.sun.xml.calc.template", 1211 | std = "application/vnd.sun.xml.draw.template", 1212 | step = "model/step", 1213 | stf = "application/vnd.wt.stf", 1214 | sti = "application/vnd.sun.xml.impress.template", 1215 | stif = "application/vnd.sealed.tiff", 1216 | stix = "application/stix+json", 1217 | stk = "application/hyperstudio", 1218 | stl = "model/stl", 1219 | stml = "application/vnd.sealedmedia.softseal.html", 1220 | stp = "model/step", 1221 | stpnc = "application/p21", 1222 | stpx = "model/step+xml", 1223 | stpxz = "model/step-xml+zip", 1224 | stpz = "model/step+zip", 1225 | str = "application/vnd.pg.format", 1226 | `study-inter` = "application/vnd.vd-study", 1227 | stw = "application/vnd.sun.xml.writer.template", 1228 | sty = "text/x-tex", 1229 | sus = "application/vnd.sus-calendar", 1230 | susp = "application/vnd.sus-calendar", 1231 | sv4cpio = "application/x-sv4cpio", 1232 | sv4crc = "application/x-sv4crc", 1233 | svc = "application/vnd.dvb.service", 1234 | svg = "image/svg+xml", 1235 | svgz = "image/svg+xml", 1236 | sw = "chemical/x-swissprot", 1237 | swf = "application/vnd.adobe.flash.movie", 1238 | swi = "application/vnd.aristanetworks.swi", 1239 | swidtag = "application/swid+xml", 1240 | sxc = "application/vnd.sun.xml.calc", 1241 | sxd = "application/vnd.sun.xml.draw", 1242 | sxg = "application/vnd.sun.xml.writer.global", 1243 | sxi = "application/vnd.sun.xml.impress", 1244 | sxl = "application/vnd.sealed.xls", 1245 | sxls = "application/vnd.sealed.xls", 1246 | sxm = "application/vnd.sun.xml.math", 1247 | sxw = "application/vnd.sun.xml.writer", 1248 | sy2 = "application/vnd.sybyl.mol2", 1249 | syft.json = "application/vnd.syft+json", 1250 | t = "text/troff", 1251 | tag = "text/prs.lines.tag", 1252 | taglet = "application/vnd.mynfc", 1253 | tam = "application/vnd.onepager", 1254 | tamp = "application/vnd.onepagertamp", 1255 | tamx = "application/vnd.onepagertamx", 1256 | tao = "application/vnd.tao.intent-module-archive", 1257 | tap = "image/vnd.tencent.tap", 1258 | tar = "application/x-tar", 1259 | tat = "application/vnd.onepagertat", 1260 | tatp = "application/vnd.onepagertatp", 1261 | tatx = "application/vnd.onepagertatx", 1262 | tau = "application/tamp-apex-update", 1263 | taz = "application/x-gtar-compressed", 1264 | tcap = "application/vnd.3gpp2.tcap", 1265 | tcl = "application/x-tcl", 1266 | tcu = "application/tamp-community-update", 1267 | td = "application/urc-targetdesc+xml", 1268 | teacher = "application/vnd.smart.teacher", 1269 | tei = "application/tei+xml", 1270 | teiCorpus = "application/tei+xml", 1271 | ter = "application/tamp-error", 1272 | tex = "text/x-tex", 1273 | texi = "application/x-texinfo", 1274 | texinfo = "application/x-texinfo", 1275 | text = "text/plain", 1276 | tfi = "application/thraud+xml", 1277 | tfx = "image/tiff-fx", 1278 | tgf = "chemical/x-mdl-tgf", 1279 | tgz = "application/x-gtar-compressed", 1280 | thmx = "application/vnd.ms-officetheme", 1281 | tif = "image/tiff", 1282 | tiff = "image/tiff", 1283 | tk = "text/x-tcl", 1284 | tlclient = "application/vnd.cendio.thinlinc.clientconf", 1285 | tm = "text/texmacs", 1286 | tm.json = "application/tm+json", 1287 | tm.jsonld = "application/tm+json", 1288 | tmo = "application/vnd.tmobile-livetv", 1289 | tnef = "application/vnd.ms-tnef", 1290 | tnf = "application/vnd.ms-tnef", 1291 | torrent = "application/x-bittorrent", 1292 | tpl = "application/vnd.groove-tool-template", 1293 | tpt = "application/vnd.trid.tpt", 1294 | tr = "text/troff", 1295 | tra = "application/vnd.trueapp", 1296 | tree = "application/vnd.rainstor.data", 1297 | trig = "application/trig", 1298 | ts = "text/vnd.trolltech.linguist", 1299 | tsa = "application/tamp-sequence-adjust", 1300 | tsd = "application/timestamped-data", 1301 | tsp = "application/dsptype", 1302 | tsq = "application/timestamp-query", 1303 | tsr = "application/timestamp-reply", 1304 | tst = "application/vnd.etsi.timestamp-token", 1305 | tsv = "text/tab-separated-values", 1306 | ttc = "font/collection", 1307 | ttf = "font/ttf", 1308 | ttl = "text/turtle", 1309 | ttml = "application/ttml+xml", 1310 | tuc = "application/tamp-update-confirm", 1311 | tur = "application/tamp-update", 1312 | twd = "application/vnd.SimTech-MindMapper", 1313 | twds = "application/vnd.SimTech-MindMapper", 1314 | txd = "application/vnd.genomatix.tuxedo", 1315 | txf = "application/vnd.Mobius.TXF", 1316 | txt = "text/plain", 1317 | u3d = "model/u3d", 1318 | u8dsn = "message/global-delivery-status", 1319 | u8hdr = "message/global-headers", 1320 | u8mdn = "message/global-disposition-notification", 1321 | u8msg = "message/global", 1322 | udeb = "application/vnd.debian.binary-package", 1323 | ufd = "application/vnd.ufdl", 1324 | ufdl = "application/vnd.ufdl", 1325 | uis = "application/urc-uisocketdesc+xml", 1326 | umj = "application/vnd.umajin", 1327 | unityweb = "application/vnd.unity", 1328 | uo = "application/vnd.uoml+xml", 1329 | uoml = "application/vnd.uoml+xml", 1330 | upa = "application/vnd.hbci", 1331 | uri = "text/uri-list", 1332 | urim = "application/vnd.uri-map", 1333 | urimap = "application/vnd.uri-map", 1334 | uris = "text/uri-list", 1335 | usda = "model/vnd.usda", 1336 | usdz = "model/vnd.usdz+zip", 1337 | ustar = "application/x-ustar", 1338 | utz = "application/vnd.uiq.theme", 1339 | uva = "audio/vnd.dece.audio", 1340 | uvd = "application/vnd.dece.data", 1341 | uvf = "application/vnd.dece.data", 1342 | uvg = "image/vnd.dece.graphic", 1343 | uvh = "video/vnd.dece.hd", 1344 | uvi = "image/vnd.dece.graphic", 1345 | uvm = "video/vnd.dece.mobile", 1346 | uvp = "video/vnd.dece.pd", 1347 | uvs = "video/vnd.dece.sd", 1348 | uvt = "application/vnd.dece.ttml+xml", 1349 | uvu = "video/vnd.dece.mp4", 1350 | uvv = "video/vnd.dece.video", 1351 | uvva = "audio/vnd.dece.audio", 1352 | uvvd = "application/vnd.dece.data", 1353 | uvvf = "application/vnd.dece.data", 1354 | uvvg = "image/vnd.dece.graphic", 1355 | uvvh = "video/vnd.dece.hd", 1356 | uvvi = "image/vnd.dece.graphic", 1357 | uvvm = "video/vnd.dece.mobile", 1358 | uvvp = "video/vnd.dece.pd", 1359 | uvvs = "video/vnd.dece.sd", 1360 | uvvt = "application/vnd.dece.ttml+xml", 1361 | uvvu = "video/vnd.dece.mp4", 1362 | uvvv = "video/vnd.dece.video", 1363 | uvvx = "application/vnd.dece.unspecified", 1364 | uvvz = "application/vnd.dece.zip", 1365 | uvx = "application/vnd.dece.unspecified", 1366 | uvz = "application/vnd.dece.zip", 1367 | val = "chemical/x-ncbi-asn1-binary", 1368 | vbk = "audio/vnd.nortel.vbk", 1369 | vbox = "application/vnd.previewsystems.box", 1370 | vcard = "text/vcard", 1371 | vcd = "application/x-cdlink", 1372 | vcf = "text/vcard", 1373 | vcg = "application/vnd.groove-vcard", 1374 | vcj = "application/voucher-cms+json", 1375 | vcs = "text/x-vcalendar", 1376 | vcx = "application/vnd.vcx", 1377 | vds = "model/vnd.sap.vds", 1378 | VES = "application/vnd.ves.encrypted", 1379 | vew = "application/vnd.lotus-approach", 1380 | VFK = "text/vnd.exchangeable", 1381 | vfr = "application/vnd.tml", 1382 | viaframe = "application/vnd.tml", 1383 | vis = "application/vnd.visionary", 1384 | viv = "video/vnd.vivo", 1385 | vmd = "chemical/x-vmd", 1386 | vms = "chemical/x-vamas-iso14976", 1387 | vmt = "application/vnd.valve.source.material", 1388 | vpm = "multipart/voice-message", 1389 | vrm = "model/vrml", 1390 | vrml = "model/vrml", 1391 | vsc = "application/vnd.vidsoft.vidconference", 1392 | vsd = "application/vnd.visio", 1393 | vsf = "application/vnd.vsf", 1394 | vss = "application/vnd.visio", 1395 | vst = "application/vnd.visio", 1396 | vsw = "application/vnd.visio", 1397 | vtf = "image/vnd.valve.source.texture", 1398 | vtnstd = "application/vnd.veritone.aion+json", 1399 | vtt = "text/vtt", 1400 | vtu = "model/vnd.vtu", 1401 | vwx = "application/vnd.vectorworks", 1402 | vxml = "application/voicexml+xml", 1403 | wad = "application/x-doom", 1404 | wadl = "application/vnd.sun.wadl+xml", 1405 | wafl = "application/vnd.wasmflow.wafl", 1406 | wasm = "application/wasm", 1407 | wav = "audio/x-wav", 1408 | wax = "audio/x-ms-wax", 1409 | wbmp = "image/vnd.wap.wbmp", 1410 | wbs = "application/vnd.criticaltools.wbs+xml", 1411 | wbxml = "application/vnd.wap.wbxml", 1412 | wcm = "application/vnd.ms-works", 1413 | wdb = "application/vnd.ms-works", 1414 | webm = "video/webm", 1415 | webmanifest = "application/manifest+json", 1416 | webp = "image/webp", 1417 | wg = "application/vnd.pmi.widget", 1418 | wgsl = "text/wgsl", 1419 | wgt = "application/widget", 1420 | wif = "application/watcherinfo+xml", 1421 | win = "model/vnd.gdl", 1422 | wk = "application/x-123", 1423 | wk1 = "application/vnd.lotus-1-2-3", 1424 | wk3 = "application/vnd.lotus-1-2-3", 1425 | wk4 = "application/vnd.lotus-1-2-3", 1426 | wks = "application/vnd.ms-works", 1427 | wlnk = "application/link-format", 1428 | wm = "video/x-ms-wm", 1429 | wma = "audio/x-ms-wma", 1430 | wmc = "application/vnd.wmc", 1431 | wmd = "application/x-ms-wmd", 1432 | wmf = "image/wmf", 1433 | wml = "text/vnd.wap.wml", 1434 | wmlc = "application/vnd.wap.wmlc", 1435 | wmls = "text/vnd.wap.wmlscript", 1436 | wmlsc = "application/vnd.wap.wmlscriptc", 1437 | wmv = "video/x-ms-wmv", 1438 | wmx = "video/x-ms-wmx", 1439 | wmz = "application/x-ms-wmz", 1440 | woff = "font/woff", 1441 | woff2 = "font/woff2", 1442 | wpd = "application/vnd.wordperfect", 1443 | wpl = "application/vnd.ms-wpl", 1444 | wps = "application/vnd.ms-works", 1445 | wqd = "application/vnd.wqd", 1446 | wrl = "model/vrml", 1447 | wsc = "application/vnd.wfa.wsc", 1448 | wsdl = "application/wsdl+xml", 1449 | wspolicy = "application/wspolicy+xml", 1450 | wtb = "application/vnd.webturbo", 1451 | wv = "application/vnd.wv.csp+wbxml", 1452 | wvx = "video/x-ms-wvx", 1453 | wz = "application/x-wingz", 1454 | x_b = "model/vnd.parasolid.transmit.binary", 1455 | x_t = "model/vnd.parasolid.transmit.text", 1456 | x3d = "model/x3d+xml", 1457 | x3db = "model/x3d+fastinfoset", 1458 | x3dv = "model/x3d-vrml", 1459 | x3dvz = "model/x3d-vrml", 1460 | x3dz = "model/x3d+xml", 1461 | xar = "application/vnd.xara", 1462 | xav = "application/xcap-att+xml", 1463 | xbd = "application/vnd.fujixerox.docuworks.binder", 1464 | xbm = "image/x-xbitmap", 1465 | xca = "application/xcap-caps+xml", 1466 | xcf = "image/x-xcf", 1467 | xcos = "application/x-scilab-xcos", 1468 | xcs = "application/calendar+xml", 1469 | xct = "application/vnd.fujixerox.docuworks.container", 1470 | xdd = "application/bacnet-xdd+zip", 1471 | xdf = "application/xcap-diff+xml", 1472 | xdm = "application/vnd.syncml.dm+xml", 1473 | xdp = "application/vnd.adobe.xdp+xml", 1474 | xdssc = "application/dssc+xml", 1475 | xdw = "application/vnd.fujixerox.docuworks", 1476 | xel = "application/xcap-el+xml", 1477 | xer = "application/xcap-error+xml", 1478 | xfd = "application/vnd.xfdl", 1479 | xfdf = "application/xfdf", 1480 | xfdl = "application/vnd.xfdl", 1481 | xhe = "audio/usac", 1482 | xht = "application/xhtml+xml", 1483 | xhtm = "application/xhtml+xml", 1484 | xhtml = "application/xhtml+xml", 1485 | xhvml = "application/xv+xml", 1486 | xif = "image/vnd.xiff", 1487 | xla = "application/vnd.ms-excel", 1488 | xlam = "application/vnd.ms-excel.addin.macroEnabled.12", 1489 | xlc = "application/vnd.ms-excel", 1490 | xlf = "application/xliff+xml", 1491 | xlim = "application/vnd.xmpie.xlim", 1492 | xlm = "application/vnd.ms-excel", 1493 | xls = "application/vnd.ms-excel", 1494 | xlsb = "application/vnd.ms-excel.sheet.binary.macroEnabled.12", 1495 | xlsm = "application/vnd.ms-excel.sheet.macroEnabled.12", 1496 | xlsx = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", 1497 | xlt = "application/vnd.ms-excel", 1498 | xltm = "application/vnd.ms-excel.template.macroEnabled.12", 1499 | xltx = "application/vnd.openxmlformats-officedocument.spreadsheetml.template", 1500 | xlw = "application/vnd.ms-excel", 1501 | xml = "application/xml", 1502 | xmls = "application/dskpp+xml", 1503 | xmt_bin = "model/vnd.parasolid.transmit.binary", 1504 | xmt_txt = "model/vnd.parasolid.transmit.text", 1505 | xns = "application/xcap-ns+xml", 1506 | xo = "application/vnd.olpc-sugar", 1507 | xodp = "application/vnd.collabio.xodocuments.presentation", 1508 | xods = "application/vnd.collabio.xodocuments.spreadsheet", 1509 | xodt = "application/vnd.collabio.xodocuments.document", 1510 | xop = "application/xop+xml", 1511 | xotp = "application/vnd.collabio.xodocuments.presentation-template", 1512 | xots = "application/vnd.collabio.xodocuments.spreadsheet-template", 1513 | xott = "application/vnd.collabio.xodocuments.document-template", 1514 | xpak = "application/vnd.gentoo.xpak", 1515 | xpi = "application/x-xpinstall", 1516 | xpm = "image/x-xpixmap", 1517 | xpr = "application/vnd.is-xpr", 1518 | xps = "application/vnd.ms-xpsdocument", 1519 | xpw = "application/vnd.intercon.formnet", 1520 | xpx = "application/vnd.intercon.formnet", 1521 | xsf = "application/prs.xsf+xml", 1522 | xsl = "application/xslt+xml", 1523 | xslt = "application/xslt+xml", 1524 | xsm = "application/vnd.syncml+xml", 1525 | xspf = "application/xspf+xml", 1526 | xtel = "chemical/x-xtel", 1527 | xul = "application/vnd.mozilla.xul+xml", 1528 | xvm = "application/xv+xml", 1529 | xvml = "application/xv+xml", 1530 | xwd = "image/x-xwindowdump", 1531 | xyz = "chemical/x-xyz", 1532 | xyze = "image/vnd.radiance", 1533 | xz = "application/x-xz", 1534 | yaml = "application/yaml", 1535 | yang = "application/yang", 1536 | yin = "application/yin+xml", 1537 | yme = "application/vnd.yaoweme", 1538 | yml = "application/yaml", 1539 | yt = "video/vnd.youtube.yt", 1540 | zaz = "application/vnd.zzazz.deck+xml", 1541 | zfc = "application/vnd.filmit.zfc", 1542 | zfo = "application/vnd.software602.filler.form-xml-zip", 1543 | zip = "application/zip", 1544 | zir = "application/vnd.zul", 1545 | zirz = "application/vnd.zul", 1546 | zmm = "application/vnd.HandHeld-Entertainment+xml", 1547 | zmt = "chemical/x-mopac-input", 1548 | zone = "text/dns", 1549 | zst = "application/zstd" 1550 | ) 1551 | -------------------------------------------------------------------------------- /R/parse.R: -------------------------------------------------------------------------------- 1 | ## Rook::Utils$parse() has a few problems: 1. it adds an extra \r\n to the file 2 | ## uploaded; 2. if there are multiple files uploaded, only the info about the 3 | ## last file is recorded. Besides, I did not escape non-file data, nor did I 4 | ## unescape the filenames. The former is not important to me at the moment, 5 | ## since the primary purpose of this function is for shiny IE8/9 file uploading; 6 | ## the latter is probably not important, either, since the users normally only 7 | ## want the content of the file(s) instead of the name(s). 8 | 9 | #' Parse multipart form data 10 | #' 11 | #' This function parses the HTML form data from a Rook environment (an HTTP POST 12 | #' request). 13 | #' @param env the HTTP request environment 14 | #' @return A named list containing the values of the form data, and the files 15 | #' uploaded are saved to temporary files (the temporary filenames are 16 | #' returned). It may also be `NULL` if there is anything unexpected in the 17 | #' form data, or the form is empty. 18 | #' @references This function was borrowed from 19 | #' with slight modifications. 20 | #' @export 21 | #' @useDynLib mime, .registration = TRUE 22 | parse_multipart = function(env) { 23 | ctype = env$CONTENT_TYPE 24 | if (length(grep('^multipart', ctype)) == 0L) return() 25 | 26 | EOL = '\r\n' 27 | params = list() 28 | input = env$rook.input; input$rewind() 29 | content_length = as.integer(env$CONTENT_LENGTH) 30 | # some constants regarding boundaries 31 | boundary = gsub('^multipart/.*boundary="?([^";,]+)"?', '--\\1', ctype) 32 | 33 | bytesize = function(x) nchar(x, type = 'bytes') 34 | EOL_size = bytesize(EOL) 35 | EOL_raw = charToRaw(EOL) 36 | boundary_size = bytesize(boundary) 37 | boundaryEOL = paste(boundary, EOL, sep = '') 38 | boundaryEOL_size = boundary_size + bytesize(EOL) 39 | boundaryEOL_raw = charToRaw(boundaryEOL) 40 | EOLEOL = paste(EOL, EOL, sep = '') 41 | EOLEOL_size = bytesize(EOLEOL) 42 | EOLEOL_raw = charToRaw(EOLEOL) 43 | 44 | buf = new.env(parent = emptyenv()) 45 | buf$bufsize = 16384L # never read more than bufsize bytes (16K) 46 | buf$read_buffer = input$read(boundaryEOL_size) 47 | buf$read_buffer_len = length(buf$read_buffer) 48 | buf$unread = content_length - boundary_size 49 | if (!identical(boundaryEOL_raw, buf$read_buffer)) { 50 | warning('bad content body') 51 | input$rewind() 52 | return() 53 | } 54 | 55 | # read the smaller one of the unread content and the next chunk 56 | fill_buffer = function() { 57 | x = input$read(min(buf$bufsize, buf$unread)) 58 | n = length(x) 59 | if (n == 0L) return() 60 | buf$read_buffer = c(buf$read_buffer, x) 61 | buf$read_buffer_len = length(buf$read_buffer) 62 | buf$unread = buf$unread - n 63 | } 64 | # slices off the beginning part of read_buffer, e.g. i is the position of 65 | # EOLEOL, and size is EOLEOL_size, and read_buffer is [......EOLEOL+++], then 66 | # slice_buffer returns the the beginning [......], and turns read_buffer to 67 | # the remaining [+++] 68 | slice_buffer = function(i, size) { 69 | slice = buf$read_buffer[if (i > 1) 1:(i - 1) else 1] 70 | buf$read_buffer = if ((i+size) <= buf$read_buffer_len) 71 | buf$read_buffer[(i + size):buf$read_buffer_len] else raw() 72 | buf$read_buffer_len = length(buf$read_buffer) 73 | slice 74 | } 75 | 76 | # prime the read_buffer 77 | buf$read_buffer = raw() 78 | fill_buffer() 79 | 80 | # find the position of the raw vector x1 in x2 81 | raw_match = function(x1, x2) { 82 | if (is.character(x1)) x1 = charToRaw(x1) 83 | .Call('rawmatch', x1, x2, PACKAGE = 'mime') 84 | } 85 | unescape = function(x) { 86 | unlist(lapply(x, function(s) utils::URLdecode(chartr('+', ' ', s)))) 87 | } 88 | 89 | while (TRUE) { 90 | head = value = NULL 91 | filename = content_type = name = NULL 92 | while (is.null(head)) { 93 | i = raw_match(EOLEOL_raw, buf$read_buffer) 94 | if (length(i)) { 95 | head = slice_buffer(i, EOLEOL_size) 96 | break 97 | } else if (buf$unread) { 98 | fill_buffer() 99 | } else { 100 | break # we've read everything and still haven't seen a valid head 101 | } 102 | } 103 | if (is.null(head)) { 104 | warning('Bad post payload: searching for a header') 105 | input$rewind() 106 | return() 107 | } 108 | # cat('Head:',rawToChar(head),'\n') they're 8bit clean 109 | head = rawToChar(head) 110 | token = '[^\\s()<>,;:\\"\\/\\[\\]?=]+' 111 | condisp = sprintf('Content-Disposition:\\s*%s\\s*', token) 112 | dispparm = sprintf(';\\s*(%s)=("(?:\\"|[^"])*"|%s)*', token, token) 113 | rfc2183 = sprintf('(?m)^%s(%s)+$', condisp, dispparm) 114 | broken_quoted = sprintf( 115 | '(?m)^%s.*;\\sfilename="(.*?)"(?:\\s*$|\\s*;\\s*%s=)', condisp, token 116 | ) 117 | broken_unquoted = sprintf('(?m)^%s.*;\\sfilename=(%s)', condisp, token) 118 | if (length(grep(rfc2183, head, perl = TRUE))) { 119 | first_line = sub(condisp, '', strsplit(head, EOL)[[1L]][1], perl = TRUE) 120 | pairs = strsplit(first_line, ';', fixed = TRUE)[[1L]] 121 | fnmatch = '\\s*filename=(.*)\\s*' 122 | if (any(grepl(fnmatch, pairs, perl = TRUE))) { 123 | filename = pairs[grepl(fnmatch, pairs, perl = TRUE)][1] 124 | filename = gsub('"', '', sub(fnmatch, '\\1', filename, perl = TRUE)) 125 | } 126 | } else if (length(grep(broken_quoted, head, perl = TRUE))) { 127 | filename = sub( 128 | broken_quoted, '\\1', strsplit(head, '\r\n')[[1L]][1], perl = TRUE 129 | ) 130 | } else if (length(grep(broken_unquoted, head, perl = TRUE))) { 131 | filename = sub( 132 | broken_unquoted, '\\1', strsplit(head, '\r\n')[[1L]][1], perl = TRUE 133 | ) 134 | } 135 | # TODO: decoding filenames seems to be a mess here; skip it for now 136 | # if (!is.null(filename) && filename != '') { 137 | # filename = unescape(filename) 138 | # } 139 | headlines = strsplit(head, EOL, fixed = TRUE)[[1L]] 140 | content_type_re = '(?mi)Content-Type: (.*)' 141 | content_types = grep(content_type_re, headlines, perl = TRUE, value = TRUE) 142 | if (length(content_types)) { 143 | content_type = sub(content_type_re, '\\1', content_types[1], perl = TRUE) 144 | } 145 | name = sub( 146 | '(?si)Content-Disposition:.*\\s+name="?([^\";]*).*"?', '\\1', head, 147 | perl = TRUE 148 | ) 149 | while (TRUE) { 150 | i = raw_match(boundary, buf$read_buffer) 151 | if (length(i)) { 152 | value = slice_buffer(i, boundary_size) 153 | # strip off the extra EOL before the boundary 154 | if (identical(tail(value, EOL_size), EOL_raw)) 155 | value = head(value, -EOL_size) 156 | if (length(value)) { 157 | # drop EOL only values 158 | if (identical(value, EOL_raw)) break 159 | if (!is.null(filename) || !is.null(content_type)) { 160 | data = list() 161 | data$name = if (is.null(filename)) NA_character_ else filename 162 | data$size = length(value) 163 | data$type = if (is.null(content_type)) NA_character_ else content_type 164 | data$datapath = tempfile() 165 | con = file(data$datapath, open = 'wb') 166 | tryCatch(writeBin(value, con), finally = close(con)) 167 | params[[name]] = rbind(params[[name]], as.data.frame(data, stringsAsFactors = FALSE)) 168 | } else { 169 | len = length(value) 170 | # trim trailing EOL 171 | if (len > 2 && length(raw_match(EOL, value[(len - 1):len]))) 172 | len = len - 2 173 | # handle array parameters (TODO: why Utils$escape?) 174 | paramValue = rawToChar(value[1:len]) 175 | paramSet = FALSE 176 | if (grepl('\\[\\]$', name)) { 177 | name = sub('\\[\\]$', '', name) 178 | if (name %in% names(params)) { 179 | params[[name]] = c(params[[name]], paramValue) 180 | paramSet = TRUE 181 | } 182 | } 183 | if (!paramSet) params[[name]] = paramValue 184 | } 185 | } 186 | break 187 | } else if (buf$unread) { 188 | fill_buffer() 189 | } else { 190 | break # we've read everything and still haven't seen a valid value 191 | } 192 | } 193 | if (is.null(value)) { 194 | # bad post payload 195 | input$rewind() 196 | warning('Bad post payload: searching for a body part') 197 | return(NULL) 198 | } 199 | # now search for ending markers or the beginning of another part 200 | while (buf$read_buffer_len < 2 && buf$unread) fill_buffer() 201 | if (buf$read_buffer_len < 2 && buf$unread == 0) { 202 | # bad stuff at the end; just return what we've got and presume everything 203 | # is okay 204 | input$rewind() 205 | return(params) 206 | } 207 | # valid ending 208 | if (length(raw_match('--', buf$read_buffer[1:2]))) { 209 | input$rewind() 210 | return(params) 211 | } 212 | # skip past the EOL. 213 | if (length(raw_match(EOL, buf$read_buffer[1:EOL_size]))) { 214 | slice_buffer(1, EOL_size) 215 | } else { 216 | warning('Bad post body: EOL not present') 217 | input$rewind() 218 | return(params) 219 | } 220 | # another sanity check before we try to parse another part 221 | if ((buf$read_buffer_len + buf$unread) < boundary_size) { 222 | warning('Bad post body: unknown trailing bytes') 223 | input$rewind() 224 | return(params) 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## mime 2 | 3 | 4 | 5 | [![R-CMD-check](https://github.com/yihui/mime/workflows/R-CMD-check/badge.svg)](https://github.com/yihui/mime/actions) 6 | [![CRAN 7 | release](https://www.r-pkg.org/badges/version/mime)](https://cran.r-project.org/package=mime) 8 | 9 | 10 | 11 | This is an R package for mapping filename extensions to [MIME 12 | types](https://en.wikipedia.org/wiki/Internet_media_type), based on the data 13 | [derived](https://github.com/yihui/mime/blob/main/tools/update.R) from 14 | `/etc/mime.types`. 15 | 16 | ``` r 17 | # installation 18 | install.packages('mime') 19 | 20 | library(mime) 21 | guess_type(c('a/b/c.html', 'd.pdf', 'e.odt', 'foo.docx', 'tex')) 22 | # [1] "text/html" 23 | # [2] "application/pdf" 24 | # [3] "application/vnd.oasis.opendocument.text" 25 | # [4] "application/vnd.openxmlformats-officedocument.wordprocessingml.document" 26 | # [5] "text/x-tex" 27 | ``` 28 | -------------------------------------------------------------------------------- /inst/NEWS.Rd: -------------------------------------------------------------------------------- 1 | \name{NEWS} 2 | \title{News for Package 'mime'} 3 | 4 | \section{CHANGES IN mime VERSION 999.999}{ 5 | \itemize{ 6 | \item This NEWS file is only a placeholder. The version 999.999 does not really 7 | exist. Please read the NEWS on Github: \url{https://github.com/yihui/mime/releases} 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /man/guess_type.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mime.R 3 | \name{guess_type} 4 | \alias{guess_type} 5 | \title{Guess the MIME types from filenames} 6 | \usage{ 7 | guess_type( 8 | file, 9 | unknown = "application/octet-stream", 10 | empty = "text/plain", 11 | mime_extra = mimeextra, 12 | subtype = "" 13 | ) 14 | } 15 | \arguments{ 16 | \item{file}{a character vector of filenames, or filename extensions} 17 | 18 | \item{unknown}{the MIME type to return when the file extension was not found 19 | in the table} 20 | 21 | \item{empty}{the MIME type for files that do not have extensions} 22 | 23 | \item{mime_extra}{a named character vector of the form \code{c(extension = type)} 24 | providing extra MIME types (by default, \code{mime:::mimeextra}); note this MIME 25 | table takes precedence over the standard table \code{\link{mimemap}}} 26 | 27 | \item{subtype}{a character vector of MIME subtypes, which should be of the 28 | same length as \code{file} if provided (use an empty character string for a file 29 | if we do not want a subtype for it)} 30 | } 31 | \description{ 32 | Look up in the \code{\link{mimemap}} table for the MIME types based on the extensions of 33 | the given filenames. 34 | } 35 | \examples{ 36 | library(mime) 37 | # well-known file types 38 | guess_type(c("a/b/c.html", "d.pdf", "e.odt", "foo.docx", "tex")) 39 | # not in the standard table, but in mimeextra 40 | guess_type(c("a.md", "b.R"), mime_extra = NULL) 41 | guess_type(c("a.md", "b.R")) 42 | 43 | # override the standard MIME table (tex is text/x-tex by default) 44 | guess_type("tex", mime_extra = c(tex = "text/plain")) 45 | # unknown extension 'zzz' 46 | guess_type("foo.zzz") 47 | # force unknown types to be plain text 48 | guess_type("foo.zzz", unknown = "text/plain") 49 | 50 | # empty file extension 51 | guess_type("Makefile") 52 | # we know it is a plain text file 53 | guess_type("Makefile", empty = "text/plain") 54 | 55 | # subtypes 56 | guess_type(c("abc.html", "def.htm"), subtype = c("charset=UTF-8", "")) 57 | } 58 | -------------------------------------------------------------------------------- /man/mimemap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mime.R 3 | \docType{data} 4 | \name{mimemap} 5 | \alias{mimemap} 6 | \title{Tables for mapping filename extensions to MIME types} 7 | \source{ 8 | The file \verb{/etc/mime.types} on Debian. 9 | } 10 | \description{ 11 | The data \code{mimemap} is a named character vector that stores the filename 12 | extensions and the corresponding MIME types, e.g. \code{c(html = 'text/html', pdf = 'application/pdf', ...)}. The character vector \code{mime:::mimeextra} stores 13 | some additional types that we know, such as Markdown files (\code{.md}), or R 14 | scripts (\code{.R}). 15 | } 16 | \examples{ 17 | str(as.list(mimemap)) 18 | mimemap["pdf"] 19 | mimemap[c("html", "js", "css")] 20 | # additional MIME types (not exported) 21 | mime:::mimeextra 22 | } 23 | \keyword{datasets} 24 | -------------------------------------------------------------------------------- /man/parse_multipart.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/parse.R 3 | \name{parse_multipart} 4 | \alias{parse_multipart} 5 | \title{Parse multipart form data} 6 | \usage{ 7 | parse_multipart(env) 8 | } 9 | \arguments{ 10 | \item{env}{the HTTP request environment} 11 | } 12 | \value{ 13 | A named list containing the values of the form data, and the files 14 | uploaded are saved to temporary files (the temporary filenames are 15 | returned). It may also be \code{NULL} if there is anything unexpected in the 16 | form data, or the form is empty. 17 | } 18 | \description{ 19 | This function parses the HTML form data from a Rook environment (an HTTP POST 20 | request). 21 | } 22 | \references{ 23 | This function was borrowed from 24 | \url{https://github.com/jeffreyhorner/Rook/} with slight modifications. 25 | } 26 | -------------------------------------------------------------------------------- /mime.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageInstallArgs: -v && Rscript -e "Rd2roxygen::rab(install=T)" 20 | PackageBuildArgs: -v && Rscript -e "Rd2roxygen::rab(build=T,install=F)" 21 | PackageCheckArgs: --as-cran 22 | -------------------------------------------------------------------------------- /src/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | extern SEXP rawmatch (SEXP needle, SEXP haystack); 7 | static const R_CallMethodDef callMethods[] = { 8 | {"rawmatch", (DL_FUNC) &rawmatch, 2}, 9 | {NULL, NULL, 0} 10 | }; 11 | 12 | void R_init_mime(DllInfo *dll) 13 | { 14 | R_registerRoutines(dll, NULL, callMethods, NULL, NULL); 15 | R_useDynamicSymbols(dll, FALSE); 16 | } 17 | -------------------------------------------------------------------------------- /src/rawmatch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | SEXP rawmatch(SEXP needle, SEXP haystack) { 5 | int i, j, n1, n2; 6 | Rbyte *x1, *x2; 7 | SEXP ans; 8 | 9 | n1 = LENGTH(needle); 10 | x1 = RAW(needle); 11 | n2 = LENGTH(haystack); 12 | x2 = RAW(haystack); 13 | if (n1 * n2 == 0 || n1 > n2) return allocVector(INTSXP, 0); 14 | 15 | ans = allocVector(INTSXP, 1); 16 | 17 | for (i = 0; i <= (n2 - n1); i++) { 18 | if (x2[i] == x1[0]) { 19 | for (j = 0; j < n1; j++) { 20 | if (x2[i + j] != x1[j]) break; 21 | } 22 | if (j == n1) { 23 | INTEGER(ans)[0] = i + 1; 24 | return ans; 25 | } 26 | } 27 | } 28 | return allocVector(INTSXP, 0); 29 | } 30 | -------------------------------------------------------------------------------- /tests/mime.R: -------------------------------------------------------------------------------- 1 | stopifnot( 2 | mime::guess_type('Makefile', empty = 'text/x-makefile') == 'text/x-makefile' 3 | ) 4 | -------------------------------------------------------------------------------- /tools/update.R: -------------------------------------------------------------------------------- 1 | sys.source('R/mimeextra.R', environment()) 2 | 3 | lines = readLines(mimefile <- '/etc/mime.types', warn = FALSE) 4 | # remove comments and blank lines 5 | lines = grep('^[a-z]', lines, value = TRUE) 6 | lines = unlist(lapply(strsplit(lines, '\\s+'), function(x) { 7 | # each line is of the form: type ext [ext2 ext3 ...] 8 | if (length(x) <= 1) return() 9 | # convert to c(html = 'text/html', js = 'application/javascript', ...) 10 | setNames(rep(x[1], length(x) - 1), x[-1]) 11 | }), recursive = FALSE) 12 | 13 | # remove duplicated file extensions 14 | lines = lines[!duplicated(names(lines))] 15 | # write R source code to the data directory; "hand-writing" instead dump(), to 16 | # make sure we can easily catch possible future differences in version control 17 | dump_vec = function(name, x) { 18 | nm = sort(names(x)) 19 | # TODO: remove special treatment for jpeg https://github.com/posit-dev/connectapi/issues/382 20 | j = names(which(x == 'image/jpeg')) 21 | i = nm %in% j 22 | nm[i] = c(intersect(j, 'jpeg'), setdiff(j, 'jpeg')) 23 | writeLines(c( 24 | sprintf('%s = c(', name), 25 | paste(sprintf( 26 | '%s = "%s"', 27 | # invalid names should be quoted using `` 28 | ifelse(make.names(nm) == nm, nm, sprintf('`%s`', nm)), 29 | x[nm] 30 | ), collapse = ',\n'), 31 | ')' 32 | ), sprintf('R/%s.R', name)) 33 | } 34 | 35 | dump_vec('mimemap', lines) 36 | extra = mimeextra[setdiff(names(mimeextra), names(lines))] 37 | extra['rd'] = 'text/plain' # override the rd entry (chemical/x-mdl-rdfile -> text/plain, i.e. R documentation) 38 | dump_vec('mimeextra', extra) 39 | --------------------------------------------------------------------------------