From 2458318101707e9e5136d1ff65ce936a512aa8db Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Mon, 24 Jun 2013 11:55:49 +0000 Subject: [PATCH 001/118] Add a new MIME-type package 'mime', with implementation for handling mime-type lookup by path (finename extension) and magic-number matching. BUG= R=sgjesse@google.com Review URL: https://codereview.chromium.org//17582009 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@24324 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/mime.dart | 9 + pkgs/mime/lib/src/extension_map.dart | 993 +++++++++++++++++++++++++++ pkgs/mime/lib/src/magic_number.dart | 49 ++ pkgs/mime/lib/src/mime_type.dart | 129 ++++ pkgs/mime/pubspec.yaml | 5 + pkgs/mime/test/mime_type_test.dart | 103 +++ 6 files changed, 1288 insertions(+) create mode 100644 pkgs/mime/lib/mime.dart create mode 100644 pkgs/mime/lib/src/extension_map.dart create mode 100644 pkgs/mime/lib/src/magic_number.dart create mode 100644 pkgs/mime/lib/src/mime_type.dart create mode 100644 pkgs/mime/pubspec.yaml create mode 100644 pkgs/mime/test/mime_type_test.dart diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart new file mode 100644 index 000000000..0943de875 --- /dev/null +++ b/pkgs/mime/lib/mime.dart @@ -0,0 +1,9 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library mime; + +part 'src/mime_type.dart'; +part 'src/extension_map.dart'; +part 'src/magic_number.dart'; diff --git a/pkgs/mime/lib/src/extension_map.dart b/pkgs/mime/lib/src/extension_map.dart new file mode 100644 index 000000000..19286bbd2 --- /dev/null +++ b/pkgs/mime/lib/src/extension_map.dart @@ -0,0 +1,993 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of mime; + + +// TODO(ajohnsen): Use sorted list and binary search? +Map _defaultExtensionMap = const { +'123':'application/vnd.lotus-1-2-3', +'3dml':'text/vnd.in3d.3dml', +'3ds':'image/x-3ds', +'3g2':'video/3gpp2', +'3gp':'video/3gpp', +'7z':'application/x-7z-compressed', +'aab':'application/x-authorware-bin', +'aac':'audio/x-aac', +'aam':'application/x-authorware-map', +'aas':'application/x-authorware-seg', +'abw':'application/x-abiword', +'ac':'application/pkix-attr-cert', +'acc':'application/vnd.americandynamics.acc', +'ace':'application/x-ace-compressed', +'acu':'application/vnd.acucobol', +'acutc':'application/vnd.acucorp', +'adp':'audio/adpcm', +'aep':'application/vnd.audiograph', +'afm':'application/x-font-type1', +'afp':'application/vnd.ibm.modcap', +'ahead':'application/vnd.ahead.space', +'ai':'application/postscript', +'aif':'audio/x-aiff', +'aifc':'audio/x-aiff', +'aiff':'audio/x-aiff', +'air':'application/vnd.adobe.air-application-installer-package+zip', +'ait':'application/vnd.dvb.ait', +'ami':'application/vnd.amiga.ami', +'apk':'application/vnd.android.package-archive', +'appcache':'text/cache-manifest', +'application':'application/x-ms-application', +'apr':'application/vnd.lotus-approach', +'arc':'application/x-freearc', +'asc':'application/pgp-signature', +'asf':'video/x-ms-asf', +'asm':'text/x-asm', +'aso':'application/vnd.accpac.simply.aso', +'asx':'video/x-ms-asf', +'atc':'application/vnd.acucorp', +'atom':'application/atom+xml', +'atomcat':'application/atomcat+xml', +'atomsvc':'application/atomsvc+xml', +'atx':'application/vnd.antix.game-component', +'au':'audio/basic', +'avi':'video/x-msvideo', +'aw':'application/applixware', +'azf':'application/vnd.airzip.filesecure.azf', +'azs':'application/vnd.airzip.filesecure.azs', +'azw':'application/vnd.amazon.ebook', +'bat':'application/x-msdownload', +'bcpio':'application/x-bcpio', +'bdf':'application/x-font-bdf', +'bdm':'application/vnd.syncml.dm+wbxml', +'bed':'application/vnd.realvnc.bed', +'bh2':'application/vnd.fujitsu.oasysprs', +'bin':'application/octet-stream', +'blb':'application/x-blorb', +'blorb':'application/x-blorb', +'bmi':'application/vnd.bmi', +'bmp':'image/bmp', +'book':'application/vnd.framemaker', +'box':'application/vnd.previewsystems.box', +'boz':'application/x-bzip2', +'bpk':'application/octet-stream', +'btif':'image/prs.btif', +'bz':'application/x-bzip', +'bz2':'application/x-bzip2', +'c':'text/x-c', +'c11amc':'application/vnd.cluetrust.cartomobile-config', +'c11amz':'application/vnd.cluetrust.cartomobile-config-pkg', +'c4d':'application/vnd.clonk.c4group', +'c4f':'application/vnd.clonk.c4group', +'c4g':'application/vnd.clonk.c4group', +'c4p':'application/vnd.clonk.c4group', +'c4u':'application/vnd.clonk.c4group', +'cab':'application/vnd.ms-cab-compressed', +'caf':'audio/x-caf', +'cap':'application/vnd.tcpdump.pcap', +'car':'application/vnd.curl.car', +'cat':'application/vnd.ms-pki.seccat', +'cb7':'application/x-cbr', +'cba':'application/x-cbr', +'cbr':'application/x-cbr', +'cbt':'application/x-cbr', +'cbz':'application/x-cbr', +'cc':'text/x-c', +'cct':'application/x-director', +'ccxml':'application/ccxml+xml', +'cdbcmsg':'application/vnd.contact.cmsg', +'cdf':'application/x-netcdf', +'cdkey':'application/vnd.mediastation.cdkey', +'cdmia':'application/cdmi-capability', +'cdmic':'application/cdmi-container', +'cdmid':'application/cdmi-domain', +'cdmio':'application/cdmi-object', +'cdmiq':'application/cdmi-queue', +'cdx':'chemical/x-cdx', +'cdxml':'application/vnd.chemdraw+xml', +'cdy':'application/vnd.cinderella', +'cer':'application/pkix-cert', +'cfs':'application/x-cfs-compressed', +'cgm':'image/cgm', +'chat':'application/x-chat', +'chm':'application/vnd.ms-htmlhelp', +'chrt':'application/vnd.kde.kchart', +'cif':'chemical/x-cif', +'cii':'application/vnd.anser-web-certificate-issue-initiation', +'cil':'application/vnd.ms-artgalry', +'cla':'application/vnd.claymore', +'class':'application/java-vm', +'clkk':'application/vnd.crick.clicker.keyboard', +'clkp':'application/vnd.crick.clicker.palette', +'clkt':'application/vnd.crick.clicker.template', +'clkw':'application/vnd.crick.clicker.wordbank', +'clkx':'application/vnd.crick.clicker', +'clp':'application/x-msclip', +'cmc':'application/vnd.cosmocaller', +'cmdf':'chemical/x-cmdf', +'cml':'chemical/x-cml', +'cmp':'application/vnd.yellowriver-custom-menu', +'cmx':'image/x-cmx', +'cod':'application/vnd.rim.cod', +'com':'application/x-msdownload', +'conf':'text/plain', +'cpio':'application/x-cpio', +'cpp':'text/x-c', +'cpt':'application/mac-compactpro', +'crd':'application/x-mscardfile', +'crl':'application/pkix-crl', +'crt':'application/x-x509-ca-cert', +'cryptonote':'application/vnd.rig.cryptonote', +'csh':'application/x-csh', +'csml':'chemical/x-csml', +'csp':'application/vnd.commonspace', +'css':'text/css', +'cst':'application/x-director', +'csv':'text/csv', +'cu':'application/cu-seeme', +'curl':'text/vnd.curl', +'cww':'application/prs.cww', +'cxt':'application/x-director', +'cxx':'text/x-c', +'dae':'model/vnd.collada+xml', +'daf':'application/vnd.mobius.daf', +'dart':'application/dart', +'dataless':'application/vnd.fdsn.seed', +'davmount':'application/davmount+xml', +'dbk':'application/docbook+xml', +'dcr':'application/x-director', +'dcurl':'text/vnd.curl.dcurl', +'dd2':'application/vnd.oma.dd2+xml', +'ddd':'application/vnd.fujixerox.ddd', +'deb':'application/x-debian-package', +'def':'text/plain', +'deploy':'application/octet-stream', +'der':'application/x-x509-ca-cert', +'dfac':'application/vnd.dreamfactory', +'dgc':'application/x-dgc-compressed', +'dic':'text/x-c', +'dir':'application/x-director', +'dis':'application/vnd.mobius.dis', +'dist':'application/octet-stream', +'distz':'application/octet-stream', +'djv':'image/vnd.djvu', +'djvu':'image/vnd.djvu', +'dll':'application/x-msdownload', +'dmg':'application/x-apple-diskimage', +'dmp':'application/vnd.tcpdump.pcap', +'dms':'application/octet-stream', +'dna':'application/vnd.dna', +'doc':'application/msword', +'docm':'application/vnd.ms-word.document.macroenabled.12', +'docx':'application/vnd.openxmlformats-officedocument.wordprocessingml.document', +'dot':'application/msword', +'dotm':'application/vnd.ms-word.template.macroenabled.12', +'dotx':'application/vnd.openxmlformats-officedocument.wordprocessingml.template', +'dp':'application/vnd.osgi.dp', +'dpg':'application/vnd.dpgraph', +'dra':'audio/vnd.dra', +'dsc':'text/prs.lines.tag', +'dssc':'application/dssc+der', +'dtb':'application/x-dtbook+xml', +'dtd':'application/xml-dtd', +'dts':'audio/vnd.dts', +'dtshd':'audio/vnd.dts.hd', +'dump':'application/octet-stream', +'dvb':'video/vnd.dvb.file', +'dvi':'application/x-dvi', +'dwf':'model/vnd.dwf', +'dwg':'image/vnd.dwg', +'dxf':'image/vnd.dxf', +'dxp':'application/vnd.spotfire.dxp', +'dxr':'application/x-director', +'ecelp4800':'audio/vnd.nuera.ecelp4800', +'ecelp7470':'audio/vnd.nuera.ecelp7470', +'ecelp9600':'audio/vnd.nuera.ecelp9600', +'ecma':'application/ecmascript', +'edm':'application/vnd.novadigm.edm', +'edx':'application/vnd.novadigm.edx', +'efif':'application/vnd.picsel', +'ei6':'application/vnd.pg.osasli', +'elc':'application/octet-stream', +'emf':'application/x-msmetafile', +'eml':'message/rfc822', +'emma':'application/emma+xml', +'emz':'application/x-msmetafile', +'eol':'audio/vnd.digital-winds', +'eot':'application/vnd.ms-fontobject', +'eps':'application/postscript', +'epub':'application/epub+zip', +'es3':'application/vnd.eszigno3+xml', +'esa':'application/vnd.osgi.subsystem', +'esf':'application/vnd.epson.esf', +'et3':'application/vnd.eszigno3+xml', +'etx':'text/x-setext', +'eva':'application/x-eva', +'evy':'application/x-envoy', +'exe':'application/x-msdownload', +'exi':'application/exi', +'ext':'application/vnd.novadigm.ext', +'ez':'application/andrew-inset', +'ez2':'application/vnd.ezpix-album', +'ez3':'application/vnd.ezpix-package', +'f':'text/x-fortran', +'f4v':'video/x-f4v', +'f77':'text/x-fortran', +'f90':'text/x-fortran', +'fbs':'image/vnd.fastbidsheet', +'fcdt':'application/vnd.adobe.formscentral.fcdt', +'fcs':'application/vnd.isac.fcs', +'fdf':'application/vnd.fdf', +'fe_launch':'application/vnd.denovo.fcselayout-link', +'fg5':'application/vnd.fujitsu.oasysgp', +'fgd':'application/x-director', +'fh':'image/x-freehand', +'fh4':'image/x-freehand', +'fh5':'image/x-freehand', +'fh7':'image/x-freehand', +'fhc':'image/x-freehand', +'fig':'application/x-xfig', +'flac':'audio/x-flac', +'fli':'video/x-fli', +'flo':'application/vnd.micrografx.flo', +'flv':'video/x-flv', +'flw':'application/vnd.kde.kivio', +'flx':'text/vnd.fmi.flexstor', +'fly':'text/vnd.fly', +'fm':'application/vnd.framemaker', +'fnc':'application/vnd.frogans.fnc', +'for':'text/x-fortran', +'fpx':'image/vnd.fpx', +'frame':'application/vnd.framemaker', +'fsc':'application/vnd.fsc.weblaunch', +'fst':'image/vnd.fst', +'ftc':'application/vnd.fluxtime.clip', +'fti':'application/vnd.anser-web-funds-transfer-initiation', +'fvt':'video/vnd.fvt', +'fxp':'application/vnd.adobe.fxp', +'fxpl':'application/vnd.adobe.fxp', +'fzs':'application/vnd.fuzzysheet', +'g2w':'application/vnd.geoplan', +'g3':'image/g3fax', +'g3w':'application/vnd.geospace', +'gac':'application/vnd.groove-account', +'gam':'application/x-tads', +'gbr':'application/rpki-ghostbusters', +'gca':'application/x-gca-compressed', +'gdl':'model/vnd.gdl', +'geo':'application/vnd.dynageo', +'gex':'application/vnd.geometry-explorer', +'ggb':'application/vnd.geogebra.file', +'ggt':'application/vnd.geogebra.tool', +'ghf':'application/vnd.groove-help', +'gif':'image/gif', +'gim':'application/vnd.groove-identity-message', +'gml':'application/gml+xml', +'gmx':'application/vnd.gmx', +'gnumeric':'application/x-gnumeric', +'gph':'application/vnd.flographit', +'gpx':'application/gpx+xml', +'gqf':'application/vnd.grafeq', +'gqs':'application/vnd.grafeq', +'gram':'application/srgs', +'gramps':'application/x-gramps-xml', +'gre':'application/vnd.geometry-explorer', +'grv':'application/vnd.groove-injector', +'grxml':'application/srgs+xml', +'gsf':'application/x-font-ghostscript', +'gtar':'application/x-gtar', +'gtm':'application/vnd.groove-tool-message', +'gtw':'model/vnd.gtw', +'gv':'text/vnd.graphviz', +'gxf':'application/gxf', +'gxt':'application/vnd.geonext', +'h':'text/x-c', +'h261':'video/h261', +'h263':'video/h263', +'h264':'video/h264', +'hal':'application/vnd.hal+xml', +'hbci':'application/vnd.hbci', +'hdf':'application/x-hdf', +'hh':'text/x-c', +'hlp':'application/winhlp', +'hpgl':'application/vnd.hp-hpgl', +'hpid':'application/vnd.hp-hpid', +'hps':'application/vnd.hp-hps', +'hqx':'application/mac-binhex40', +'htke':'application/vnd.kenameaapp', +'htm':'text/html', +'html':'text/html', +'hvd':'application/vnd.yamaha.hv-dic', +'hvp':'application/vnd.yamaha.hv-voice', +'hvs':'application/vnd.yamaha.hv-script', +'i2g':'application/vnd.intergeo', +'icc':'application/vnd.iccprofile', +'ice':'x-conference/x-cooltalk', +'icm':'application/vnd.iccprofile', +'ico':'image/x-icon', +'ics':'text/calendar', +'ief':'image/ief', +'ifb':'text/calendar', +'ifm':'application/vnd.shana.informed.formdata', +'iges':'model/iges', +'igl':'application/vnd.igloader', +'igm':'application/vnd.insors.igm', +'igs':'model/iges', +'igx':'application/vnd.micrografx.igx', +'iif':'application/vnd.shana.informed.interchange', +'imp':'application/vnd.accpac.simply.imp', +'ims':'application/vnd.ms-ims', +'in':'text/plain', +'ink':'application/inkml+xml', +'inkml':'application/inkml+xml', +'install':'application/x-install-instructions', +'iota':'application/vnd.astraea-software.iota', +'ipfix':'application/ipfix', +'ipk':'application/vnd.shana.informed.package', +'irm':'application/vnd.ibm.rights-management', +'irp':'application/vnd.irepository.package+xml', +'iso':'application/x-iso9660-image', +'itp':'application/vnd.shana.informed.formtemplate', +'ivp':'application/vnd.immervision-ivp', +'ivu':'application/vnd.immervision-ivu', +'jad':'text/vnd.sun.j2me.app-descriptor', +'jam':'application/vnd.jam', +'jar':'application/java-archive', +'java':'text/x-java-source', +'jisp':'application/vnd.jisp', +'jlt':'application/vnd.hp-jlyt', +'jnlp':'application/x-java-jnlp-file', +'joda':'application/vnd.joost.joda-archive', +'jpe':'image/jpeg', +'jpeg':'image/jpeg', +'jpg':'image/jpeg', +'jpgm':'video/jpm', +'jpgv':'video/jpeg', +'jpm':'video/jpm', +'js':'application/javascript', +'json':'application/json', +'jsonml':'application/jsonml+json', +'kar':'audio/midi', +'karbon':'application/vnd.kde.karbon', +'kfo':'application/vnd.kde.kformula', +'kia':'application/vnd.kidspiration', +'kml':'application/vnd.google-earth.kml+xml', +'kmz':'application/vnd.google-earth.kmz', +'kne':'application/vnd.kinar', +'knp':'application/vnd.kinar', +'kon':'application/vnd.kde.kontour', +'kpr':'application/vnd.kde.kpresenter', +'kpt':'application/vnd.kde.kpresenter', +'kpxx':'application/vnd.ds-keypoint', +'ksp':'application/vnd.kde.kspread', +'ktr':'application/vnd.kahootz', +'ktx':'image/ktx', +'ktz':'application/vnd.kahootz', +'kwd':'application/vnd.kde.kword', +'kwt':'application/vnd.kde.kword', +'lasxml':'application/vnd.las.las+xml', +'latex':'application/x-latex', +'lbd':'application/vnd.llamagraphics.life-balance.desktop', +'lbe':'application/vnd.llamagraphics.life-balance.exchange+xml', +'les':'application/vnd.hhe.lesson-player', +'lha':'application/x-lzh-compressed', +'link66':'application/vnd.route66.link66+xml', +'list':'text/plain', +'list3820':'application/vnd.ibm.modcap', +'listafp':'application/vnd.ibm.modcap', +'lnk':'application/x-ms-shortcut', +'log':'text/plain', +'lostxml':'application/lost+xml', +'lrf':'application/octet-stream', +'lrm':'application/vnd.ms-lrm', +'ltf':'application/vnd.frogans.ltf', +'lvp':'audio/vnd.lucent.voice', +'lwp':'application/vnd.lotus-wordpro', +'lzh':'application/x-lzh-compressed', +'m13':'application/x-msmediaview', +'m14':'application/x-msmediaview', +'m1v':'video/mpeg', +'m21':'application/mp21', +'m2a':'audio/mpeg', +'m2v':'video/mpeg', +'m3a':'audio/mpeg', +'m3u':'audio/x-mpegurl', +'m3u8':'application/vnd.apple.mpegurl', +'m4u':'video/vnd.mpegurl', +'m4v':'video/x-m4v', +'ma':'application/mathematica', +'mads':'application/mads+xml', +'mag':'application/vnd.ecowin.chart', +'maker':'application/vnd.framemaker', +'man':'text/troff', +'mar':'application/octet-stream', +'mathml':'application/mathml+xml', +'mb':'application/mathematica', +'mbk':'application/vnd.mobius.mbk', +'mbox':'application/mbox', +'mc1':'application/vnd.medcalcdata', +'mcd':'application/vnd.mcd', +'mcurl':'text/vnd.curl.mcurl', +'mdb':'application/x-msaccess', +'mdi':'image/vnd.ms-modi', +'me':'text/troff', +'mesh':'model/mesh', +'meta4':'application/metalink4+xml', +'metalink':'application/metalink+xml', +'mets':'application/mets+xml', +'mfm':'application/vnd.mfmp', +'mft':'application/rpki-manifest', +'mgp':'application/vnd.osgeo.mapguide.package', +'mgz':'application/vnd.proteus.magazine', +'mid':'audio/midi', +'midi':'audio/midi', +'mie':'application/x-mie', +'mif':'application/vnd.mif', +'mime':'message/rfc822', +'mj2':'video/mj2', +'mjp2':'video/mj2', +'mk3d':'video/x-matroska', +'mka':'audio/x-matroska', +'mks':'video/x-matroska', +'mkv':'video/x-matroska', +'mlp':'application/vnd.dolby.mlp', +'mmd':'application/vnd.chipnuts.karaoke-mmd', +'mmf':'application/vnd.smaf', +'mmr':'image/vnd.fujixerox.edmics-mmr', +'mng':'video/x-mng', +'mny':'application/x-msmoney', +'mobi':'application/x-mobipocket-ebook', +'mods':'application/mods+xml', +'mov':'video/quicktime', +'movie':'video/x-sgi-movie', +'mp2':'audio/mpeg', +'mp21':'application/mp21', +'mp2a':'audio/mpeg', +'mp3':'audio/mpeg', +'mp4':'video/mp4', +'mp4a':'audio/mp4', +'mp4s':'application/mp4', +'mp4v':'video/mp4', +'mpc':'application/vnd.mophun.certificate', +'mpe':'video/mpeg', +'mpeg':'video/mpeg', +'mpg':'video/mpeg', +'mpg4':'video/mp4', +'mpga':'audio/mpeg', +'mpkg':'application/vnd.apple.installer+xml', +'mpm':'application/vnd.blueice.multipass', +'mpn':'application/vnd.mophun.application', +'mpp':'application/vnd.ms-project', +'mpt':'application/vnd.ms-project', +'mpy':'application/vnd.ibm.minipay', +'mqy':'application/vnd.mobius.mqy', +'mrc':'application/marc', +'mrcx':'application/marcxml+xml', +'ms':'text/troff', +'mscml':'application/mediaservercontrol+xml', +'mseed':'application/vnd.fdsn.mseed', +'mseq':'application/vnd.mseq', +'msf':'application/vnd.epson.msf', +'msh':'model/mesh', +'msi':'application/x-msdownload', +'msl':'application/vnd.mobius.msl', +'msty':'application/vnd.muvee.style', +'mts':'model/vnd.mts', +'mus':'application/vnd.musician', +'musicxml':'application/vnd.recordare.musicxml+xml', +'mvb':'application/x-msmediaview', +'mwf':'application/vnd.mfer', +'mxf':'application/mxf', +'mxl':'application/vnd.recordare.musicxml', +'mxml':'application/xv+xml', +'mxs':'application/vnd.triscape.mxs', +'mxu':'video/vnd.mpegurl', +'n-gage':'application/vnd.nokia.n-gage.symbian.install', +'n3':'text/n3', +'nb':'application/mathematica', +'nbp':'application/vnd.wolfram.player', +'nc':'application/x-netcdf', +'ncx':'application/x-dtbncx+xml', +'nfo':'text/x-nfo', +'ngdat':'application/vnd.nokia.n-gage.data', +'nitf':'application/vnd.nitf', +'nlu':'application/vnd.neurolanguage.nlu', +'nml':'application/vnd.enliven', +'nnd':'application/vnd.noblenet-directory', +'nns':'application/vnd.noblenet-sealer', +'nnw':'application/vnd.noblenet-web', +'npx':'image/vnd.net-fpx', +'nsc':'application/x-conference', +'nsf':'application/vnd.lotus-notes', +'ntf':'application/vnd.nitf', +'nzb':'application/x-nzb', +'oa2':'application/vnd.fujitsu.oasys2', +'oa3':'application/vnd.fujitsu.oasys3', +'oas':'application/vnd.fujitsu.oasys', +'obd':'application/x-msbinder', +'obj':'application/x-tgif', +'oda':'application/oda', +'odb':'application/vnd.oasis.opendocument.database', +'odc':'application/vnd.oasis.opendocument.chart', +'odf':'application/vnd.oasis.opendocument.formula', +'odft':'application/vnd.oasis.opendocument.formula-template', +'odg':'application/vnd.oasis.opendocument.graphics', +'odi':'application/vnd.oasis.opendocument.image', +'odm':'application/vnd.oasis.opendocument.text-master', +'odp':'application/vnd.oasis.opendocument.presentation', +'ods':'application/vnd.oasis.opendocument.spreadsheet', +'odt':'application/vnd.oasis.opendocument.text', +'oga':'audio/ogg', +'ogg':'audio/ogg', +'ogv':'video/ogg', +'ogx':'application/ogg', +'omdoc':'application/omdoc+xml', +'onepkg':'application/onenote', +'onetmp':'application/onenote', +'onetoc':'application/onenote', +'onetoc2':'application/onenote', +'opf':'application/oebps-package+xml', +'opml':'text/x-opml', +'oprc':'application/vnd.palm', +'org':'application/vnd.lotus-organizer', +'osf':'application/vnd.yamaha.openscoreformat', +'osfpvg':'application/vnd.yamaha.openscoreformat.osfpvg+xml', +'otc':'application/vnd.oasis.opendocument.chart-template', +'otf':'application/x-font-otf', +'otg':'application/vnd.oasis.opendocument.graphics-template', +'oth':'application/vnd.oasis.opendocument.text-web', +'oti':'application/vnd.oasis.opendocument.image-template', +'otp':'application/vnd.oasis.opendocument.presentation-template', +'ots':'application/vnd.oasis.opendocument.spreadsheet-template', +'ott':'application/vnd.oasis.opendocument.text-template', +'oxps':'application/oxps', +'oxt':'application/vnd.openofficeorg.extension', +'p':'text/x-pascal', +'p10':'application/pkcs10', +'p12':'application/x-pkcs12', +'p7b':'application/x-pkcs7-certificates', +'p7c':'application/pkcs7-mime', +'p7m':'application/pkcs7-mime', +'p7r':'application/x-pkcs7-certreqresp', +'p7s':'application/pkcs7-signature', +'p8':'application/pkcs8', +'pas':'text/x-pascal', +'paw':'application/vnd.pawaafile', +'pbd':'application/vnd.powerbuilder6', +'pbm':'image/x-portable-bitmap', +'pcap':'application/vnd.tcpdump.pcap', +'pcf':'application/x-font-pcf', +'pcl':'application/vnd.hp-pcl', +'pclxl':'application/vnd.hp-pclxl', +'pct':'image/x-pict', +'pcurl':'application/vnd.curl.pcurl', +'pcx':'image/x-pcx', +'pdb':'application/vnd.palm', +'pdf':'application/pdf', +'pfa':'application/x-font-type1', +'pfb':'application/x-font-type1', +'pfm':'application/x-font-type1', +'pfr':'application/font-tdpfr', +'pfx':'application/x-pkcs12', +'pgm':'image/x-portable-graymap', +'pgn':'application/x-chess-pgn', +'pgp':'application/pgp-encrypted', +'pic':'image/x-pict', +'pkg':'application/octet-stream', +'pki':'application/pkixcmp', +'pkipath':'application/pkix-pkipath', +'plb':'application/vnd.3gpp.pic-bw-large', +'plc':'application/vnd.mobius.plc', +'plf':'application/vnd.pocketlearn', +'pls':'application/pls+xml', +'pml':'application/vnd.ctc-posml', +'png':'image/png', +'pnm':'image/x-portable-anymap', +'portpkg':'application/vnd.macports.portpkg', +'pot':'application/vnd.ms-powerpoint', +'potm':'application/vnd.ms-powerpoint.template.macroenabled.12', +'potx':'application/vnd.openxmlformats-officedocument.presentationml.template', +'ppam':'application/vnd.ms-powerpoint.addin.macroenabled.12', +'ppd':'application/vnd.cups-ppd', +'ppm':'image/x-portable-pixmap', +'pps':'application/vnd.ms-powerpoint', +'ppsm':'application/vnd.ms-powerpoint.slideshow.macroenabled.12', +'ppsx':'application/vnd.openxmlformats-officedocument.presentationml.slideshow', +'ppt':'application/vnd.ms-powerpoint', +'pptm':'application/vnd.ms-powerpoint.presentation.macroenabled.12', +'pptx':'application/vnd.openxmlformats-officedocument.presentationml.presentation', +'pqa':'application/vnd.palm', +'prc':'application/x-mobipocket-ebook', +'pre':'application/vnd.lotus-freelance', +'prf':'application/pics-rules', +'ps':'application/postscript', +'psb':'application/vnd.3gpp.pic-bw-small', +'psd':'image/vnd.adobe.photoshop', +'psf':'application/x-font-linux-psf', +'pskcxml':'application/pskc+xml', +'ptid':'application/vnd.pvi.ptid1', +'pub':'application/x-mspublisher', +'pvb':'application/vnd.3gpp.pic-bw-var', +'pwn':'application/vnd.3m.post-it-notes', +'pya':'audio/vnd.ms-playready.media.pya', +'pyv':'video/vnd.ms-playready.media.pyv', +'qam':'application/vnd.epson.quickanime', +'qbo':'application/vnd.intu.qbo', +'qfx':'application/vnd.intu.qfx', +'qps':'application/vnd.publishare-delta-tree', +'qt':'video/quicktime', +'qwd':'application/vnd.quark.quarkxpress', +'qwt':'application/vnd.quark.quarkxpress', +'qxb':'application/vnd.quark.quarkxpress', +'qxd':'application/vnd.quark.quarkxpress', +'qxl':'application/vnd.quark.quarkxpress', +'qxt':'application/vnd.quark.quarkxpress', +'ra':'audio/x-pn-realaudio', +'ram':'audio/x-pn-realaudio', +'rar':'application/x-rar-compressed', +'ras':'image/x-cmu-raster', +'rcprofile':'application/vnd.ipunplugged.rcprofile', +'rdf':'application/rdf+xml', +'rdz':'application/vnd.data-vision.rdz', +'rep':'application/vnd.businessobjects', +'res':'application/x-dtbresource+xml', +'rgb':'image/x-rgb', +'rif':'application/reginfo+xml', +'rip':'audio/vnd.rip', +'ris':'application/x-research-info-systems', +'rl':'application/resource-lists+xml', +'rlc':'image/vnd.fujixerox.edmics-rlc', +'rld':'application/resource-lists-diff+xml', +'rm':'application/vnd.rn-realmedia', +'rmi':'audio/midi', +'rmp':'audio/x-pn-realaudio-plugin', +'rms':'application/vnd.jcp.javame.midlet-rms', +'rmvb':'application/vnd.rn-realmedia-vbr', +'rnc':'application/relax-ng-compact-syntax', +'roa':'application/rpki-roa', +'roff':'text/troff', +'rp9':'application/vnd.cloanto.rp9', +'rpss':'application/vnd.nokia.radio-presets', +'rpst':'application/vnd.nokia.radio-preset', +'rq':'application/sparql-query', +'rs':'application/rls-services+xml', +'rsd':'application/rsd+xml', +'rss':'application/rss+xml', +'rtf':'application/rtf', +'rtx':'text/richtext', +'s':'text/x-asm', +'s3m':'audio/s3m', +'saf':'application/vnd.yamaha.smaf-audio', +'sbml':'application/sbml+xml', +'sc':'application/vnd.ibm.secure-container', +'scd':'application/x-msschedule', +'scm':'application/vnd.lotus-screencam', +'scq':'application/scvp-cv-request', +'scs':'application/scvp-cv-response', +'scurl':'text/vnd.curl.scurl', +'sda':'application/vnd.stardivision.draw', +'sdc':'application/vnd.stardivision.calc', +'sdd':'application/vnd.stardivision.impress', +'sdkd':'application/vnd.solent.sdkm+xml', +'sdkm':'application/vnd.solent.sdkm+xml', +'sdp':'application/sdp', +'sdw':'application/vnd.stardivision.writer', +'see':'application/vnd.seemail', +'seed':'application/vnd.fdsn.seed', +'sema':'application/vnd.sema', +'semd':'application/vnd.semd', +'semf':'application/vnd.semf', +'ser':'application/java-serialized-object', +'setpay':'application/set-payment-initiation', +'setreg':'application/set-registration-initiation', +'sfd-hdstx':'application/vnd.hydrostatix.sof-data', +'sfs':'application/vnd.spotfire.sfs', +'sfv':'text/x-sfv', +'sgi':'image/sgi', +'sgl':'application/vnd.stardivision.writer-global', +'sgm':'text/sgml', +'sgml':'text/sgml', +'sh':'application/x-sh', +'shar':'application/x-shar', +'shf':'application/shf+xml', +'sid':'image/x-mrsid-image', +'sig':'application/pgp-signature', +'sil':'audio/silk', +'silo':'model/mesh', +'sis':'application/vnd.symbian.install', +'sisx':'application/vnd.symbian.install', +'sit':'application/x-stuffit', +'sitx':'application/x-stuffitx', +'skd':'application/vnd.koan', +'skm':'application/vnd.koan', +'skp':'application/vnd.koan', +'skt':'application/vnd.koan', +'sldm':'application/vnd.ms-powerpoint.slide.macroenabled.12', +'sldx':'application/vnd.openxmlformats-officedocument.presentationml.slide', +'slt':'application/vnd.epson.salt', +'sm':'application/vnd.stepmania.stepchart', +'smf':'application/vnd.stardivision.math', +'smi':'application/smil+xml', +'smil':'application/smil+xml', +'smv':'video/x-smv', +'smzip':'application/vnd.stepmania.package', +'snd':'audio/basic', +'snf':'application/x-font-snf', +'so':'application/octet-stream', +'spc':'application/x-pkcs7-certificates', +'spf':'application/vnd.yamaha.smaf-phrase', +'spl':'application/x-futuresplash', +'spot':'text/vnd.in3d.spot', +'spp':'application/scvp-vp-response', +'spq':'application/scvp-vp-request', +'spx':'audio/ogg', +'sql':'application/x-sql', +'src':'application/x-wais-source', +'srt':'application/x-subrip', +'sru':'application/sru+xml', +'srx':'application/sparql-results+xml', +'ssdl':'application/ssdl+xml', +'sse':'application/vnd.kodak-descriptor', +'ssf':'application/vnd.epson.ssf', +'ssml':'application/ssml+xml', +'st':'application/vnd.sailingtracker.track', +'stc':'application/vnd.sun.xml.calc.template', +'std':'application/vnd.sun.xml.draw.template', +'stf':'application/vnd.wt.stf', +'sti':'application/vnd.sun.xml.impress.template', +'stk':'application/hyperstudio', +'stl':'application/vnd.ms-pki.stl', +'str':'application/vnd.pg.format', +'stw':'application/vnd.sun.xml.writer.template', +'sub':'image/vnd.dvb.subtitle', +'sub':'text/vnd.dvb.subtitle', +'sus':'application/vnd.sus-calendar', +'susp':'application/vnd.sus-calendar', +'sv4cpio':'application/x-sv4cpio', +'sv4crc':'application/x-sv4crc', +'svc':'application/vnd.dvb.service', +'svd':'application/vnd.svd', +'svg':'image/svg+xml', +'svgz':'image/svg+xml', +'swa':'application/x-director', +'swf':'application/x-shockwave-flash', +'swi':'application/vnd.aristanetworks.swi', +'sxc':'application/vnd.sun.xml.calc', +'sxd':'application/vnd.sun.xml.draw', +'sxg':'application/vnd.sun.xml.writer.global', +'sxi':'application/vnd.sun.xml.impress', +'sxm':'application/vnd.sun.xml.math', +'sxw':'application/vnd.sun.xml.writer', +'t':'text/troff', +'t3':'application/x-t3vm-image', +'taglet':'application/vnd.mynfc', +'tao':'application/vnd.tao.intent-module-archive', +'tar':'application/x-tar', +'tcap':'application/vnd.3gpp2.tcap', +'tcl':'application/x-tcl', +'teacher':'application/vnd.smart.teacher', +'tei':'application/tei+xml', +'teicorpus':'application/tei+xml', +'tex':'application/x-tex', +'texi':'application/x-texinfo', +'texinfo':'application/x-texinfo', +'text':'text/plain', +'tfi':'application/thraud+xml', +'tfm':'application/x-tex-tfm', +'tga':'image/x-tga', +'thmx':'application/vnd.ms-officetheme', +'tif':'image/tiff', +'tiff':'image/tiff', +'tmo':'application/vnd.tmobile-livetv', +'torrent':'application/x-bittorrent', +'tpl':'application/vnd.groove-tool-template', +'tpt':'application/vnd.trid.tpt', +'tr':'text/troff', +'tra':'application/vnd.trueapp', +'trm':'application/x-msterminal', +'tsd':'application/timestamped-data', +'tsv':'text/tab-separated-values', +'ttc':'application/x-font-ttf', +'ttf':'application/x-font-ttf', +'ttl':'text/turtle', +'twd':'application/vnd.simtech-mindmapper', +'twds':'application/vnd.simtech-mindmapper', +'txd':'application/vnd.genomatix.tuxedo', +'txf':'application/vnd.mobius.txf', +'txt':'text/plain', +'u32':'application/x-authorware-bin', +'udeb':'application/x-debian-package', +'ufd':'application/vnd.ufdl', +'ufdl':'application/vnd.ufdl', +'ulx':'application/x-glulx', +'umj':'application/vnd.umajin', +'unityweb':'application/vnd.unity', +'uoml':'application/vnd.uoml+xml', +'uri':'text/uri-list', +'uris':'text/uri-list', +'urls':'text/uri-list', +'ustar':'application/x-ustar', +'utz':'application/vnd.uiq.theme', +'uu':'text/x-uuencode', +'uva':'audio/vnd.dece.audio', +'uvd':'application/vnd.dece.data', +'uvf':'application/vnd.dece.data', +'uvg':'image/vnd.dece.graphic', +'uvh':'video/vnd.dece.hd', +'uvi':'image/vnd.dece.graphic', +'uvm':'video/vnd.dece.mobile', +'uvp':'video/vnd.dece.pd', +'uvs':'video/vnd.dece.sd', +'uvt':'application/vnd.dece.ttml+xml', +'uvu':'video/vnd.uvvu.mp4', +'uvv':'video/vnd.dece.video', +'uvva':'audio/vnd.dece.audio', +'uvvd':'application/vnd.dece.data', +'uvvf':'application/vnd.dece.data', +'uvvg':'image/vnd.dece.graphic', +'uvvh':'video/vnd.dece.hd', +'uvvi':'image/vnd.dece.graphic', +'uvvm':'video/vnd.dece.mobile', +'uvvp':'video/vnd.dece.pd', +'uvvs':'video/vnd.dece.sd', +'uvvt':'application/vnd.dece.ttml+xml', +'uvvu':'video/vnd.uvvu.mp4', +'uvvv':'video/vnd.dece.video', +'uvvx':'application/vnd.dece.unspecified', +'uvvz':'application/vnd.dece.zip', +'uvx':'application/vnd.dece.unspecified', +'uvz':'application/vnd.dece.zip', +'vcard':'text/vcard', +'vcd':'application/x-cdlink', +'vcf':'text/x-vcard', +'vcg':'application/vnd.groove-vcard', +'vcs':'text/x-vcalendar', +'vcx':'application/vnd.vcx', +'vis':'application/vnd.visionary', +'viv':'video/vnd.vivo', +'vob':'video/x-ms-vob', +'vor':'application/vnd.stardivision.writer', +'vox':'application/x-authorware-bin', +'vrml':'model/vrml', +'vsd':'application/vnd.visio', +'vsf':'application/vnd.vsf', +'vss':'application/vnd.visio', +'vst':'application/vnd.visio', +'vsw':'application/vnd.visio', +'vtu':'model/vnd.vtu', +'vxml':'application/voicexml+xml', +'w3d':'application/x-director', +'wad':'application/x-doom', +'wav':'audio/x-wav', +'wax':'audio/x-ms-wax', +'wbmp':'image/vnd.wap.wbmp', +'wbs':'application/vnd.criticaltools.wbs+xml', +'wbxml':'application/vnd.wap.wbxml', +'wcm':'application/vnd.ms-works', +'wdb':'application/vnd.ms-works', +'wdp':'image/vnd.ms-photo', +'weba':'audio/webm', +'webm':'video/webm', +'webp':'image/webp', +'wg':'application/vnd.pmi.widget', +'wgt':'application/widget', +'wks':'application/vnd.ms-works', +'wm':'video/x-ms-wm', +'wma':'audio/x-ms-wma', +'wmd':'application/x-ms-wmd', +'wmf':'application/x-msmetafile', +'wml':'text/vnd.wap.wml', +'wmlc':'application/vnd.wap.wmlc', +'wmls':'text/vnd.wap.wmlscript', +'wmlsc':'application/vnd.wap.wmlscriptc', +'wmv':'video/x-ms-wmv', +'wmx':'video/x-ms-wmx', +'wmz':'application/x-ms-wmz', +'wmz':'application/x-msmetafile', +'woff':'application/x-font-woff', +'wpd':'application/vnd.wordperfect', +'wpl':'application/vnd.ms-wpl', +'wps':'application/vnd.ms-works', +'wqd':'application/vnd.wqd', +'wri':'application/x-mswrite', +'wrl':'model/vrml', +'wsdl':'application/wsdl+xml', +'wspolicy':'application/wspolicy+xml', +'wtb':'application/vnd.webturbo', +'wvx':'video/x-ms-wvx', +'x32':'application/x-authorware-bin', +'x3d':'model/x3d+xml', +'x3db':'model/x3d+binary', +'x3dbz':'model/x3d+binary', +'x3dv':'model/x3d+vrml', +'x3dvz':'model/x3d+vrml', +'x3dz':'model/x3d+xml', +'xaml':'application/xaml+xml', +'xap':'application/x-silverlight-app', +'xar':'application/vnd.xara', +'xbap':'application/x-ms-xbap', +'xbd':'application/vnd.fujixerox.docuworks.binder', +'xbm':'image/x-xbitmap', +'xdf':'application/xcap-diff+xml', +'xdm':'application/vnd.syncml.dm+xml', +'xdp':'application/vnd.adobe.xdp+xml', +'xdssc':'application/dssc+xml', +'xdw':'application/vnd.fujixerox.docuworks', +'xenc':'application/xenc+xml', +'xer':'application/patch-ops-error+xml', +'xfdf':'application/vnd.adobe.xfdf', +'xfdl':'application/vnd.xfdl', +'xht':'application/xhtml+xml', +'xhtml':'application/xhtml+xml', +'xhvml':'application/xv+xml', +'xif':'image/vnd.xiff', +'xla':'application/vnd.ms-excel', +'xlam':'application/vnd.ms-excel.addin.macroenabled.12', +'xlc':'application/vnd.ms-excel', +'xlf':'application/x-xliff+xml', +'xlm':'application/vnd.ms-excel', +'xls':'application/vnd.ms-excel', +'xlsb':'application/vnd.ms-excel.sheet.binary.macroenabled.12', +'xlsm':'application/vnd.ms-excel.sheet.macroenabled.12', +'xlsx':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', +'xlt':'application/vnd.ms-excel', +'xltm':'application/vnd.ms-excel.template.macroenabled.12', +'xltx':'application/vnd.openxmlformats-officedocument.spreadsheetml.template', +'xlw':'application/vnd.ms-excel', +'xm':'audio/xm', +'xml':'application/xml', +'xo':'application/vnd.olpc-sugar', +'xop':'application/xop+xml', +'xpi':'application/x-xpinstall', +'xpl':'application/xproc+xml', +'xpm':'image/x-xpixmap', +'xpr':'application/vnd.is-xpr', +'xps':'application/vnd.ms-xpsdocument', +'xpw':'application/vnd.intercon.formnet', +'xpx':'application/vnd.intercon.formnet', +'xsl':'application/xml', +'xslt':'application/xslt+xml', +'xsm':'application/vnd.syncml+xml', +'xspf':'application/xspf+xml', +'xul':'application/vnd.mozilla.xul+xml', +'xvm':'application/xv+xml', +'xvml':'application/xv+xml', +'xwd':'image/x-xwindowdump', +'xyz':'chemical/x-xyz', +'xz':'application/x-xz', +'yang':'application/yang', +'yin':'application/yin+xml', +'z1':'application/x-zmachine', +'z2':'application/x-zmachine', +'z3':'application/x-zmachine', +'z4':'application/x-zmachine', +'z5':'application/x-zmachine', +'z6':'application/x-zmachine', +'z7':'application/x-zmachine', +'z8':'application/x-zmachine', +'zaz':'application/vnd.zzazz.deck+xml', +'zip':'application/zip', +'zir':'application/vnd.zul', +'zirz':'application/vnd.zul', +'zmm':'application/vnd.handheld-entertainment+xml', +}; diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart new file mode 100644 index 000000000..451a09344 --- /dev/null +++ b/pkgs/mime/lib/src/magic_number.dart @@ -0,0 +1,49 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of mime; + + +class _MagicNumber { + final String mimeType; + final List numbers; + final List mask; + + const _MagicNumber(this.mimeType, this.numbers, {this.mask}); + + bool matches(List header) { + if (header.length < numbers.length) return false; + + for (int i = 0; i < numbers.length; i++) { + if (mask != null) { + if ((mask[i] & numbers[i]) != (mask[i] & header[i])) return false; + } else { + if (numbers[i] != header[i]) return false; + } + } + + return true; + } + +} + +int _defaultMagicNumbersMaxLength = 16; + +List<_MagicNumber> _defaultMagicNumbers = const [ +const _MagicNumber('application/pdf', const [0x25, 0x50, 0x44, 0x46]), +const _MagicNumber('application/postscript', const [0x25, 0x51]), +const _MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), +const _MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), +const _MagicNumber('image/jpeg', const [0xFF, 0xD8]), +const _MagicNumber('image/png', + const [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), +const _MagicNumber('image/tiff', const [0x49, 0x49, 0x2A, 0x00]), +const _MagicNumber('image/tiff', const [0x4D, 0x4D, 0x00, 0x2A]), +const _MagicNumber('video/mp4', + const [0x00, 0x00, 0x00, 0x00, 0x66, 0x74, + 0x79, 0x70, 0x33, 0x67, 0x70, 0x35], + mask: const [0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]) +]; + diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart new file mode 100644 index 000000000..4b73ce010 --- /dev/null +++ b/pkgs/mime/lib/src/mime_type.dart @@ -0,0 +1,129 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of mime_type; + + +MimeTypeResolver _globalResolver = new MimeTypeResolver(); + +/** + * The maximum number of bytes needed, to match all default magic-numbers. + */ +int get defaultMagicNumbersMaxLength => _defaultMagicNumbersMaxLength; + +/** + * Extract the extension from [path] and use that for MIME-type lookup, using + * the default extension map. + * + * If no matching MIME-type was found, `null` is returned. + * + * If [headerBytes] is present, a match for known magic-numbers will be + * performed first. This allows the correct mime-type to be found, even though + * a file have been saved using the wrong file-name extension. If less than + * [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't + * be matched against. + */ +String lookupMimeType(String path, + {List headerBytes}) + => _globalResolver.lookup(path, headerBytes: headerBytes); + + +/** + * MIME-type resolver class, used to customize the lookup of mime-types. + */ +class MimeTypeResolver { + final Map _extensionMap = {}; + final List<_MagicNumber> _magicNumbers = []; + bool _useDefault; + int _magicNumbersMaxLength; + + /** + * Create a new empty [MimeTypeResolver]. + */ + MimeTypeResolver.empty() : _useDefault = false, _magicNumbersMaxLength = 0; + + /** + * Create a new [MimeTypeResolver] containing the default scope. + */ + MimeTypeResolver() : + _useDefault = true, + _magicNumbersMaxLength = _defaultMagicNumbersMaxLength; + + /** + * Get the maximum number of bytes required to match all magic numbers, when + * performing [lookup] with headerBytes present. + */ + int get magicNumbersMaxLength => _magicNumbersMaxLength; + + /** + * Extract the extension from [path] and use that for MIME-type lookup. + * + * If no matching MIME-type was found, `null` is returned. + * + * If [headerBytes] is present, a match for known magic-numbers will be + * performed first. This allows the correct mime-type to be found, even though + * a file have been saved using the wrong file-name extension. If less than + * [magicNumbersMaxLength] bytes was provided, some magic-numbers won't + * be matched against. + */ + String lookup(String path, + {List headerBytes}) { + String result; + if (headerBytes != null) { + result =_matchMagic(headerBytes, _magicNumbers); + if (result != null) return result; + if (_useDefault) { + result =_matchMagic(headerBytes, _defaultMagicNumbers); + if (result != null) return result; + } + } + var ext = _ext(path); + result = _extensionMap[ext]; + if (result != null) return result; + if (_useDefault) { + result = _defaultExtensionMap[ext]; + if (result != null) return result; + } + return null; + } + + /** + * Add a new MIME-type mapping to the [MimeTypeResolver]. If the [extension] + * is already present in the [MimeTypeResolver], it'll be overwritten. + */ + void addExtension(String extension, String mimeType) { + _extensionMap[extension] = mimeType; + } + + /** + * Add a new magic-number mapping to the [MimeTypeResolver]. + * + * If [mask] is present,the [mask] is used to only perform matching on + * selective bits. The [mask] must have the same length as [bytes]. + */ + void addMagicNumber(List bytes, String mimeType, {List mask}) { + if (mask != null && bytes.length != mask.length) { + throw new ArgumentError('Bytes and mask are of different lengths'); + } + if (bytes.length > _magicNumbersMaxLength) { + _magicNumbersMaxLength = bytes.length; + } + _magicNumbers.add(new _MagicNumber(mimeType, bytes, mask: mask)); + } + + static String _matchMagic(List headerBytes, + List<_MagicNumber> magicNumbers) { + for (var mn in magicNumbers) { + if (mn.matches(headerBytes)) return mn.mimeType; + } + return null; + } + + static String _ext(String path) { + int index = path.lastIndexOf('.'); + if (index < 0 || index + 1 >= path.length) return path; + return path.substring(index + 1).toLowerCase(); + } +} + diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml new file mode 100644 index 000000000..82493f81f --- /dev/null +++ b/pkgs/mime/pubspec.yaml @@ -0,0 +1,5 @@ +name: mime +author: "Dart Team " +homepage: http://www.dartlang.org +description: > + Helper-package for working with MIME. diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart new file mode 100644 index 000000000..36c728d80 --- /dev/null +++ b/pkgs/mime/test/mime_type_test.dart @@ -0,0 +1,103 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "package:unittest/unittest.dart"; +import 'package:mime/mime.dart'; + +void expectMimeType(String path, + String expectedMimeType, + {List headerBytes, + MimeTypeResolver resolver}) { + String mimeType; + if (resolver == null) { + mimeType = lookupMimeType(path, headerBytes: headerBytes); + } else { + mimeType = resolver.lookup(path, headerBytes: headerBytes); + } + + if (mimeType != expectedMimeType) { + throw "Expect '$expectedMimeType' but got '$mimeType'"; + } +} + +void main() { + group('global-lookup', () { + test('by-path', () { + expectMimeType('file.dart', 'application/dart'); + // Test mixed-case + expectMimeType('file.DaRT', 'application/dart'); + expectMimeType('file.html', 'text/html'); + expectMimeType('file.xhtml', 'application/xhtml+xml'); + expectMimeType('file.jpeg', 'image/jpeg'); + expectMimeType('file.jpg', 'image/jpeg'); + expectMimeType('file.png', 'image/png'); + expectMimeType('file.gif', 'image/gif'); + expectMimeType('file.cc', 'text/x-c'); + expectMimeType('file.c', 'text/x-c'); + expectMimeType('file.css', 'text/css'); + expectMimeType('file.js', 'application/javascript'); + expectMimeType('file.ps', 'application/postscript'); + expectMimeType('file.pdf', 'application/pdf'); + expectMimeType('file.tiff', 'image/tiff'); + expectMimeType('file.tif', 'image/tiff'); + }); + + test('unknown-mime-type', () { + expectMimeType('file.unsupported-extension', null); + }); + + test('by-header-bytes', () { + expectMimeType('file.jpg', + 'image/png', + headerBytes: [0x89, 0x50, 0x4E, 0x47, + 0x0D, 0x0A, 0x1A, 0x0A]); + expectMimeType('file.jpg', + 'image/gif', + headerBytes: [0x47, 0x49, 0x46, 0x38, 0x39, + 0x61, 0x0D, 0x0A, 0x1A, 0x0A]); + expectMimeType('file.gif', + 'image/jpeg', + headerBytes: [0xFF, 0xD8, 0x46, 0x38, 0x39, + 0x61, 0x0D, 0x0A, 0x1A, 0x0A]); + expectMimeType('file.mp4', + 'video/mp4', + headerBytes: [0x00, 0x00, 0x00, 0x04, 0x66, 0x74, + 0x79, 0x70, 0x33, 0x67, 0x70, 0x35]); + }); + }); + + group('custom-resolver', () { + test('override-extension', () { + var resolver = new MimeTypeResolver(); + resolver.addExtension('jpg', 'my-mime-type'); + expectMimeType('file.jpg', 'my-mime-type', resolver: resolver); + }); + + test('fallthrough-extension', () { + var resolver = new MimeTypeResolver(); + resolver.addExtension('jpg2', 'my-mime-type'); + expectMimeType('file.jpg', 'image/jpeg', resolver: resolver); + }); + + test('with-mask', () { + var resolver = new MimeTypeResolver.empty(); + resolver.addMagicNumber([0x01, 0x02, 0x03], + 'my-mime-type', + mask: [0x01, 0xFF, 0xFE]); + expectMimeType('file', + 'my-mime-type', + headerBytes: [0x01, 0x02, 0x03], + resolver: resolver); + expectMimeType('file', + null, + headerBytes: [0x01, 0x03, 0x03], + resolver: resolver); + expectMimeType('file', + 'my-mime-type', + headerBytes: [0xFF, 0x02, 0x02], + resolver: resolver); + }); + }); +} + From 2a0d4413542359b532f3a8e9dff3678cdfeeae0b Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Mon, 24 Jun 2013 13:14:00 +0000 Subject: [PATCH 002/118] Fix 'part of' for mime package. BUG= R=kasperl@google.com Review URL: https://codereview.chromium.org//17583010 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@24331 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/src/mime_type.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index 4b73ce010..cd08cdfd8 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -2,7 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -part of mime_type; +part of mime; MimeTypeResolver _globalResolver = new MimeTypeResolver(); From ca949d59532914febe56000edf6d2a1c083d5b3a Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Mon, 15 Jul 2013 08:40:36 +0000 Subject: [PATCH 003/118] Move MimeMultipartTransformer and HttpBodyHandler to mime and http_server packages. BUG= R=whesse@google.com Review URL: https://codereview.chromium.org//18438005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@24991 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/mime.dart | 4 + .../lib/src/mime_multipart_transformer.dart | 420 ++++++++++++++++++ .../test/mime_multipart_transformer_test.dart | 321 +++++++++++++ 3 files changed, 745 insertions(+) create mode 100644 pkgs/mime/lib/src/mime_multipart_transformer.dart create mode 100644 pkgs/mime/test/mime_multipart_transformer_test.dart diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart index 0943de875..44c6cadd9 100644 --- a/pkgs/mime/lib/mime.dart +++ b/pkgs/mime/lib/mime.dart @@ -4,6 +4,10 @@ library mime; +import 'dart:async'; +import 'dart:typed_data'; + part 'src/mime_type.dart'; part 'src/extension_map.dart'; part 'src/magic_number.dart'; +part 'src/mime_multipart_transformer.dart'; diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart new file mode 100644 index 000000000..581308752 --- /dev/null +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -0,0 +1,420 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of mime; + + +/** + * A Mime Multipart class representing each part parsed by + * [MimeMultipartTransformer]. The data is streamed in as it become available. + */ +abstract class MimeMultipart extends Stream> { + Map get headers; +} + +class _MimeMultipart extends MimeMultipart { + final Map headers; + final Stream> _stream; + + _MimeMultipart(this.headers, this._stream); + + StreamSubscription> listen(void onData(List data), + {void onDone(), + void onError(error), + bool cancelOnError}) { + return _stream.listen(onData, + onDone: onDone, + onError: onError, + cancelOnError: cancelOnError); + } +} + +class _Const { + // Bytes for '()<>@,;:\\"/[]?={} \t'. + static const SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, + 91, 93, 63, 61, 123, 125, 32, 9]; +} + +class _CharCode { + static const int HT = 9; + static const int LF = 10; + static const int CR = 13; + static const int SP = 32; + static const int DASH = 45; + static const int COLON = 58; +} + +/** + * Parser for MIME multipart types of data as described in RFC 2046 + * section 5.1.1. The data is transformed into [MimeMultipart] objects, each + * of them streaming the multipart data. + */ +class MimeMultipartTransformer + implements StreamTransformer, MimeMultipart> { + static const int _START = 0; + static const int _FIRST_BOUNDARY_ENDING = 111; + static const int _FIRST_BOUNDARY_END = 112; + static const int _BOUNDARY_ENDING = 1; + static const int _BOUNDARY_END = 2; + static const int _HEADER_START = 3; + static const int _HEADER_FIELD = 4; + static const int _HEADER_VALUE_START = 5; + static const int _HEADER_VALUE = 6; + static const int _HEADER_VALUE_FOLDING_OR_ENDING = 7; + static const int _HEADER_VALUE_FOLD_OR_END = 8; + static const int _HEADER_ENDING = 9; + static const int _CONTENT = 10; + static const int _LAST_BOUNDARY_DASH2 = 11; + static const int _LAST_BOUNDARY_ENDING = 12; + static const int _LAST_BOUNDARY_END = 13; + static const int _DONE = 14; + static const int _FAILURE = 15; + + StreamController _controller; + StreamSubscription _subscription; + + StreamController _multipartController; + Map _headers; + + List _boundary; + int _state = _START; + int _boundaryIndex = 2; + + // Current index in the data buffer. If index is negative then it + // is the index into the artificial prefix of the boundary string. + int _index; + List _buffer; + + StringBuffer _headerField = new StringBuffer(); + StringBuffer _headerValue = new StringBuffer(); + + /** + * Construct a new MIME multipart parser with the boundary + * [boundary]. The boundary should be as specified in the content + * type parameter, that is without the -- prefix. + */ + MimeMultipartTransformer(String boundary) { + List charCodes = boundary.codeUnits; + _boundary = new Uint8List(4 + charCodes.length); + // Set-up the matching boundary preceding it with CRLF and two + // dashes. + _boundary[0] = _CharCode.CR; + _boundary[1] = _CharCode.LF; + _boundary[2] = _CharCode.DASH; + _boundary[3] = _CharCode.DASH; + _boundary.setRange(4, 4 + charCodes.length, charCodes); + } + + void _resumeStream() { + _subscription.resume(); + } + + void _pauseStream() { + _subscription.pause(); + } + + Stream bind(Stream> stream) { + _controller = new StreamController( + sync: true, + onPause: _pauseStream, + onResume:_resumeStream, + onCancel: () { + _subscription.cancel(); + }, + onListen: () { + _subscription = stream.listen( + (data) { + assert(_buffer == null); + _pauseStream(); + _buffer = data; + _index = 0; + _parse(); + }, + onDone: () { + if (_state != _DONE) { + _controller.addError( + new MimeMultipartException("Bad multipart ending")); + } + _controller.close(); + }, + onError: (error) { + _controller.addError(error); + }); + }); + return _controller.stream; + } + + void _parse() { + // Number of boundary bytes to artificially place before the supplied data. + int boundaryPrefix = 0; + // Position where content starts. Will be null if no known content + // start exists. Will be negative of the content starts in the + // boundary prefix. Will be zero or position if the content starts + // in the current buffer. + int contentStartIndex; + + // Function to report content data for the current part. The data + // reported is from the current content start index up til the + // current index. As the data can be artificially prefixed with a + // prefix of the boundary both the content start index and index + // can be negative. + void reportData() { + if (contentStartIndex < 0) { + var contentLength = boundaryPrefix + _index - _boundaryIndex; + if (contentLength <= boundaryPrefix) { + _multipartController.add( + _boundary.sublist(0, contentLength)); + } else { + _multipartController.add( + _boundary.sublist(0, boundaryPrefix)); + _multipartController.add( + _buffer.sublist(0, contentLength - boundaryPrefix)); + } + } else { + var contentEndIndex = _index - _boundaryIndex; + _multipartController.add( + _buffer.sublist(contentStartIndex, contentEndIndex)); + } + } + + if (_state == _CONTENT && _boundaryIndex == 0) { + contentStartIndex = 0; + } else { + contentStartIndex = null; + } + // The data to parse might be "artificially" prefixed with a + // partial match of the boundary. + boundaryPrefix = _boundaryIndex; + + while ((_index < _buffer.length) && _state != _FAILURE && _state != _DONE) { + if (_multipartController != null && _multipartController.isPaused) { + return; + } + int byte; + if (_index < 0) { + byte = _boundary[boundaryPrefix + _index]; + } else { + byte = _buffer[_index]; + } + switch (_state) { + case _START: + if (byte == _boundary[_boundaryIndex]) { + _boundaryIndex++; + if (_boundaryIndex == _boundary.length) { + _state = _FIRST_BOUNDARY_ENDING; + _boundaryIndex = 0; + } + } else { + // Restart matching of the boundary. + _index = _index - _boundaryIndex; + _boundaryIndex = 0; + } + break; + + case _FIRST_BOUNDARY_ENDING: + if (byte == _CharCode.CR) { + _state = _FIRST_BOUNDARY_END; + } else { + _expectWS(byte); + } + break; + + case _FIRST_BOUNDARY_END: + _expect(byte, _CharCode.LF); + _state = _HEADER_START; + break; + + case _BOUNDARY_ENDING: + if (byte == _CharCode.CR) { + _state = _BOUNDARY_END; + } else if (byte == _CharCode.DASH) { + _state = _LAST_BOUNDARY_DASH2; + } else { + _expectWS(byte); + } + break; + + case _BOUNDARY_END: + _expect(byte, _CharCode.LF); + _multipartController.close(); + _multipartController = null; + _state = _HEADER_START; + break; + + case _HEADER_START: + _headers = new Map(); + if (byte == _CharCode.CR) { + _state = _HEADER_ENDING; + } else { + // Start of new header field. + _headerField.writeCharCode(_toLowerCase(byte)); + _state = _HEADER_FIELD; + } + break; + + case _HEADER_FIELD: + if (byte == _CharCode.COLON) { + _state = _HEADER_VALUE_START; + } else { + if (!_isTokenChar(byte)) { + throw new MimeMultipartException("Invalid header field name"); + } + _headerField.writeCharCode(_toLowerCase(byte)); + } + break; + + case _HEADER_VALUE_START: + if (byte == _CharCode.CR) { + _state = _HEADER_VALUE_FOLDING_OR_ENDING; + } else if (byte != _CharCode.SP && byte != _CharCode.HT) { + // Start of new header value. + _headerValue.writeCharCode(byte); + _state = _HEADER_VALUE; + } + break; + + case _HEADER_VALUE: + if (byte == _CharCode.CR) { + _state = _HEADER_VALUE_FOLDING_OR_ENDING; + } else { + _headerValue.writeCharCode(byte); + } + break; + + case _HEADER_VALUE_FOLDING_OR_ENDING: + _expect(byte, _CharCode.LF); + _state = _HEADER_VALUE_FOLD_OR_END; + break; + + case _HEADER_VALUE_FOLD_OR_END: + if (byte == _CharCode.SP || byte == _CharCode.HT) { + _state = _HEADER_VALUE_START; + } else { + String headerField = _headerField.toString(); + String headerValue =_headerValue.toString(); + _headers[headerField.toLowerCase()] = headerValue; + _headerField = new StringBuffer(); + _headerValue = new StringBuffer(); + if (byte == _CharCode.CR) { + _state = _HEADER_ENDING; + } else { + // Start of new header field. + _headerField.writeCharCode(_toLowerCase(byte)); + _state = _HEADER_FIELD; + } + } + break; + + case _HEADER_ENDING: + _expect(byte, _CharCode.LF); + _multipartController = new StreamController( + sync: true, + onPause: () { + _pauseStream(); + }, + onResume: () { + _resumeStream(); + _parse(); + }); + _controller.add( + new _MimeMultipart(_headers, _multipartController.stream)); + _headers = null; + _state = _CONTENT; + contentStartIndex = _index + 1; + break; + + case _CONTENT: + if (byte == _boundary[_boundaryIndex]) { + _boundaryIndex++; + if (_boundaryIndex == _boundary.length) { + if (contentStartIndex != null) { + _index++; + reportData(); + _index--; + } + _multipartController.close(); + _boundaryIndex = 0; + _state = _BOUNDARY_ENDING; + } + } else { + // Restart matching of the boundary. + _index = _index - _boundaryIndex; + if (contentStartIndex == null) contentStartIndex = _index; + _boundaryIndex = 0; + } + break; + + case _LAST_BOUNDARY_DASH2: + _expect(byte, _CharCode.DASH); + _state = _LAST_BOUNDARY_ENDING; + break; + + case _LAST_BOUNDARY_ENDING: + if (byte == _CharCode.CR) { + _state = _LAST_BOUNDARY_END; + } else { + _expectWS(byte); + } + break; + + case _LAST_BOUNDARY_END: + _expect(byte, _CharCode.LF); + _multipartController.close(); + _multipartController = null; + _state = _DONE; + break; + + default: + // Should be unreachable. + assert(false); + break; + } + + // Move to the next byte. + _index++; + } + + // Report any known content. + if (_state == _CONTENT && contentStartIndex != null) { + reportData(); + } + + // Resume if at end. + if (_index == _buffer.length) { + _buffer = null; + _index = null; + _resumeStream(); + } + } + + bool _isTokenChar(int byte) { + return byte > 31 && byte < 128 && _Const.SEPARATORS.indexOf(byte) == -1; + } + + int _toLowerCase(int byte) { + final int aCode = "A".codeUnitAt(0); + final int zCode = "Z".codeUnitAt(0); + final int delta = "a".codeUnitAt(0) - aCode; + return (aCode <= byte && byte <= zCode) ? byte + delta : byte; + } + + void _expect(int val1, int val2) { + if (val1 != val2) { + throw new MimeMultipartException("Failed to parse multipart mime 1"); + } + } + + void _expectWS(int byte) { + if (byte != _CharCode.SP && byte != _CharCode.HT) { + throw new MimeMultipartException("Failed to parse multipart mime 2"); + } + } +} + + +class MimeMultipartException implements Exception { + const MimeMultipartException([String this.message = ""]); + String toString() => "MimeMultipartException: $message"; + final String message; +} diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart new file mode 100644 index 000000000..f0dd91e66 --- /dev/null +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -0,0 +1,321 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "package:unittest/unittest.dart"; +import "package:mime/mime.dart"; +import 'dart:async'; +import 'dart:math'; +import 'dart:isolate'; + +void testParse(String message, + String boundary, + [List expectedHeaders, + List expectedParts, + bool expectError = false]) { + Future testWrite(List data, [int chunkSize = -1]) { + StreamController controller = new StreamController(sync: true); + + var stream = controller.stream.transform( + new MimeMultipartTransformer(boundary)); + int i = 0; + var completer = new Completer(); + var futures = []; + stream.listen((multipart) { + int part = i++; + if (expectedHeaders != null) { + expect(multipart.headers, equals(expectedHeaders[part])); + } + futures.add(multipart.fold([], (buffer, data) => buffer..addAll(data)) + .then((data) { + if (expectedParts[part] != null) { + expect(data, equals(expectedParts[part].codeUnits)); + } + })); + }, onError: (error) { + if (!expectError) throw error; + }, onDone: () { + if (expectedParts != null) { + expect(i, equals(expectedParts.length)); + } + Future.wait(futures).then(completer.complete); + }); + + if (chunkSize == -1) chunkSize = data.length; + + int written = 0; + for (int pos = 0; pos < data.length; pos += chunkSize) { + int remaining = data.length - pos; + int writeLength = min(chunkSize, remaining); + controller.add(data.sublist(pos, pos + writeLength)); + written += writeLength; + } + controller.close(); + + return completer.future; + } + + // Test parsing the data three times delivering the data in + // different chunks. + List data = message.codeUnits; + expect(Future.wait([ + testWrite(data), + testWrite(data, 10), + testWrite(data, 2), + testWrite(data, 1)]), + completes); +} + +void testParseValid() { + String message; + Map headers; + Map headers1; + Map headers2; + Map headers3; + Map headers4; + String body1; + String body2; + String body3; + String body4; + + // Sample from Wikipedia. + message = """ +This is a message with multiple parts in MIME format.\r +--frontier\r +Content-Type: text/plain\r +\r +This is the body of the message.\r +--frontier\r +Content-Type: application/octet-stream\r +Content-Transfer-Encoding: base64\r +\r +PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg +Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\r +--frontier--\r\n"""; + headers1 = {"content-type": "text/plain"}; + headers2 = {"content-type": "application/octet-stream", + "content-transfer-encoding": "base64"}; + body1 = "This is the body of the message."; + body2 = """ +PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg +Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg="""; + testParse(message, "frontier", [headers1, headers2], [body1, body2]); + + // Sample from HTML 4.01 Specification. + message = """ +\r\n--AaB03x\r +Content-Disposition: form-data; name=\"submit-name\"\r +\r +Larry\r +--AaB03x\r +Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"\r +Content-Type: text/plain\r +\r +... contents of file1.txt ...\r +--AaB03x--\r\n"""; + headers1 = { + "content-disposition": "form-data; name=\"submit-name\""}; + headers2 = { + "content-type": "text/plain", + "content-disposition": "form-data; name=\"files\"; filename=\"file1.txt\"" + }; + body1 = "Larry"; + body2 = "... contents of file1.txt ..."; + testParse(message, "AaB03x", [headers1, headers2], [body1, body2]); + + // Longer form from submitting the following from Chrome. + // + // + // + //
+ //

+ // Text: + // Password: + // Checkbox: + // Radio: + // Send + //

+ //
+ // + // + + message = """ +\r\n------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r +Content-Disposition: form-data; name=\"text_input\"\r +\r +text\r +------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r +Content-Disposition: form-data; name=\"password_input\"\r +\r +password\r +------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r +Content-Disposition: form-data; name=\"checkbox_input\"\r +\r +on\r +------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r +Content-Disposition: form-data; name=\"radio_input\"\r +\r +on\r +------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n"""; + headers1 = { + "content-disposition": "form-data; name=\"text_input\""}; + headers2 = { + "content-disposition": "form-data; name=\"password_input\""}; + headers3 = { + "content-disposition": "form-data; name=\"checkbox_input\""}; + headers4 = { + "content-disposition": "form-data; name=\"radio_input\""}; + body1 = "text"; + body2 = "password"; + body3 = "on"; + body4 = "on"; + testParse(message, + "----WebKitFormBoundaryQ3cgYAmGRF8yOeYB", + [headers1, headers2, headers3, headers4], + [body1, body2, body3, body4]); + + // Same form from Firefox. + message = """ +\r\n-----------------------------52284550912143824192005403738\r +Content-Disposition: form-data; name=\"text_input\"\r +\r +text\r +-----------------------------52284550912143824192005403738\r +Content-Disposition: form-data; name=\"password_input\"\r +\r +password\r +-----------------------------52284550912143824192005403738\r +Content-Disposition: form-data; name=\"checkbox_input\"\r +\r +on\r +-----------------------------52284550912143824192005403738\r +Content-Disposition: form-data; name=\"radio_input\"\r +\r +on\r +-----------------------------52284550912143824192005403738--\r\n"""; + testParse(message, + "---------------------------52284550912143824192005403738", + [headers1, headers2, headers3, headers4], + [body1, body2, body3, body4]); + + // And Internet Explorer + message = """ +\r\n-----------------------------7dc8f38c60326\r +Content-Disposition: form-data; name=\"text_input\"\r +\r +text\r +-----------------------------7dc8f38c60326\r +Content-Disposition: form-data; name=\"password_input\"\r +\r +password\r +-----------------------------7dc8f38c60326\r +Content-Disposition: form-data; name=\"checkbox_input\"\r +\r +on\r +-----------------------------7dc8f38c60326\r +Content-Disposition: form-data; name=\"radio_input\"\r +\r +on\r +-----------------------------7dc8f38c60326--\r\n"""; + testParse(message, + "---------------------------7dc8f38c60326", + [headers1, headers2, headers3, headers4], + [body1, body2, body3, body4]); + + // Test boundary prefix inside prefix and content. + message = """ +-\r +--\r +--b\r +--bo\r +--bou\r +--boun\r +--bound\r +--bounda\r +--boundar\r +--boundary\r +Content-Type: text/plain\r +\r +-\r +--\r +--b\r +--bo\r +--bou\r +--boun\r +--bound\r\r +--bounda\r\r\r +--boundar\r\r\r\r +--boundary\r +Content-Type: text/plain\r +\r +--boundar\r +--bounda\r +--bound\r +--boun\r +--bou\r +--bo\r +--b\r\r\r\r +--\r\r\r +-\r\r +--boundary--\r\n"""; + headers = {"content-type": "text/plain"}; + body1 = """ +-\r +--\r +--b\r +--bo\r +--bou\r +--boun\r +--bound\r\r +--bounda\r\r\r +--boundar\r\r\r"""; + body2 = """ +--boundar\r +--bounda\r +--bound\r +--boun\r +--bou\r +--bo\r +--b\r\r\r\r +--\r\r\r +-\r"""; + testParse(message, "boundary", [headers, headers], [body1, body2]); + + // Without initial CRLF. + message = """ +--xxx\r +\r +\r +Body 1\r +--xxx\r +\r +\r +Body2\r +--xxx--\r\n"""; + testParse(message, "xxx", null, ["\r\nBody 1", "\r\nBody2"]); +} + +void testParseInvalid() { + String message; + + // Missing end boundary. + message = """ +\r +--xxx\r +\r +\r +Body 1\r +--xxx\r +\r +\r +Body2\r +--xxx\r\n"""; + testParse(message, "xxx", null, [null, null], true); +} + +void main() { + testParseValid(); + testParseInvalid(); +} From 2ea7b3ab567d80935c06a6bddc1bf35c4db341e0 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Mon, 15 Jul 2013 09:11:06 +0000 Subject: [PATCH 004/118] Fix editor warnings in http_server and mime. BUG= Review URL: https://codereview.chromium.org//19158002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@24992 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/src/extension_map.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/mime/lib/src/extension_map.dart b/pkgs/mime/lib/src/extension_map.dart index 19286bbd2..ac534aea5 100644 --- a/pkgs/mime/lib/src/extension_map.dart +++ b/pkgs/mime/lib/src/extension_map.dart @@ -759,7 +759,6 @@ Map _defaultExtensionMap = const { 'stl':'application/vnd.ms-pki.stl', 'str':'application/vnd.pg.format', 'stw':'application/vnd.sun.xml.writer.template', -'sub':'image/vnd.dvb.subtitle', 'sub':'text/vnd.dvb.subtitle', 'sus':'application/vnd.sus-calendar', 'susp':'application/vnd.sus-calendar', @@ -903,7 +902,6 @@ Map _defaultExtensionMap = const { 'wmv':'video/x-ms-wmv', 'wmx':'video/x-ms-wmx', 'wmz':'application/x-ms-wmz', -'wmz':'application/x-msmetafile', 'woff':'application/x-font-woff', 'wpd':'application/vnd.wordperfect', 'wpl':'application/vnd.ms-wpl', From ed04ff22192a4332e0fb6ffa210b6c0ebe9260a1 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Mon, 15 Jul 2013 09:15:18 +0000 Subject: [PATCH 005/118] Run mime-multipart test in 'test' callback. BUG= Review URL: https://codereview.chromium.org//19158004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@24993 260f80e4-7a28-3924-810f-c04153c831b5 --- .../mime/test/mime_multipart_transformer_test.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index f0dd91e66..43b542fa2 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -58,12 +58,14 @@ void testParse(String message, // Test parsing the data three times delivering the data in // different chunks. List data = message.codeUnits; - expect(Future.wait([ - testWrite(data), - testWrite(data, 10), - testWrite(data, 2), - testWrite(data, 1)]), - completes); + test('test', () { + expect(Future.wait([ + testWrite(data), + testWrite(data, 10), + testWrite(data, 2), + testWrite(data, 1)]), + completes); + }); } void testParseValid() { From 9e20bcff230460c63a5bd00b4634ae0d2413397e Mon Sep 17 00:00:00 2001 From: "kevmoo@j832.com" Date: Tue, 6 Aug 2013 20:42:04 +0000 Subject: [PATCH 006/118] pkg: analysis aided cleanup Removed a lot of warnings and hints when opening many pkg projects in the editor R=gram@google.com Review URL: https://codereview.chromium.org//22284003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@25831 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/pubspec.yaml | 7 ++++--- pkgs/mime/test/mime_multipart_transformer_test.dart | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 82493f81f..174820c03 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,6 @@ name: mime -author: "Dart Team " +author: Dart Team +description: Helper-package for working with MIME. homepage: http://www.dartlang.org -description: > - Helper-package for working with MIME. +dev_dependencies: + unittest: any diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 43b542fa2..7d7bacaae 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -6,7 +6,6 @@ import "package:unittest/unittest.dart"; import "package:mime/mime.dart"; import 'dart:async'; import 'dart:math'; -import 'dart:isolate'; void testParse(String message, String boundary, From 8d8de0d5b0160bfb234b5b312206c129a3e00e5c Mon Sep 17 00:00:00 2001 From: "kathyw@google.com" Date: Tue, 27 Aug 2013 14:27:46 +0000 Subject: [PATCH 007/118] mime library description R=mcampione@google.com Review URL: https://codereview.chromium.org//23419003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@26713 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/mime.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart index 44c6cadd9..652aa850e 100644 --- a/pkgs/mime/lib/mime.dart +++ b/pkgs/mime/lib/mime.dart @@ -2,6 +2,16 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +/** + * Help for working with file format identifiers + * such as `text/html` and `image/png`. + * + * More details, including a list of types, are in the Wikipedia article + * [Internet media type](http://en.wikipedia.org/wiki/Internet_media_type). + * For information on installing and importing this library, see the + * [mime package on pub.dartlang.org] + * (http://pub.dartlang.org/packages/mime). + */ library mime; import 'dart:async'; From acb98eed2be501bf631279630c4359b81f82bad0 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Fri, 11 Oct 2013 12:02:20 +0000 Subject: [PATCH 008/118] Adapt streams for additional stackTrace argument. R=lrn@google.com Review URL: https://codereview.chromium.org//25094002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@28511 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/src/mime_multipart_transformer.dart | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart index 581308752..024cd714c 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -21,7 +21,7 @@ class _MimeMultipart extends MimeMultipart { StreamSubscription> listen(void onData(List data), {void onDone(), - void onError(error), + Function onError, bool cancelOnError}) { return _stream.listen(onData, onDone: onDone, @@ -138,9 +138,7 @@ class MimeMultipartTransformer } _controller.close(); }, - onError: (error) { - _controller.addError(error); - }); + onError: _controller.addError); }); return _controller.stream; } From b752bfb39af2e56004c1796e901c99d75cbae7b3 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Wed, 30 Oct 2013 10:34:12 +0000 Subject: [PATCH 009/118] Use UTF8-decoding for headers in mime multipart parser. BUG=http://code.google.com/p/dart/issues/detail?id=14303 R=sgjesse@google.com Review URL: https://codereview.chromium.org//48403004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@29526 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/mime.dart | 1 + .../lib/src/mime_multipart_transformer.dart | 22 +++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart index 652aa850e..d1372d44c 100644 --- a/pkgs/mime/lib/mime.dart +++ b/pkgs/mime/lib/mime.dart @@ -15,6 +15,7 @@ library mime; import 'dart:async'; +import 'dart:convert'; import 'dart:typed_data'; part 'src/mime_type.dart'; diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart index 024cd714c..a35b49136 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -86,8 +86,8 @@ class MimeMultipartTransformer int _index; List _buffer; - StringBuffer _headerField = new StringBuffer(); - StringBuffer _headerValue = new StringBuffer(); + List _headerField = []; + List _headerValue = []; /** * Construct a new MIME multipart parser with the boundary @@ -246,7 +246,7 @@ class MimeMultipartTransformer _state = _HEADER_ENDING; } else { // Start of new header field. - _headerField.writeCharCode(_toLowerCase(byte)); + _headerField.add(_toLowerCase(byte)); _state = _HEADER_FIELD; } break; @@ -258,7 +258,7 @@ class MimeMultipartTransformer if (!_isTokenChar(byte)) { throw new MimeMultipartException("Invalid header field name"); } - _headerField.writeCharCode(_toLowerCase(byte)); + _headerField.add(_toLowerCase(byte)); } break; @@ -267,7 +267,7 @@ class MimeMultipartTransformer _state = _HEADER_VALUE_FOLDING_OR_ENDING; } else if (byte != _CharCode.SP && byte != _CharCode.HT) { // Start of new header value. - _headerValue.writeCharCode(byte); + _headerValue.add(byte); _state = _HEADER_VALUE; } break; @@ -276,7 +276,7 @@ class MimeMultipartTransformer if (byte == _CharCode.CR) { _state = _HEADER_VALUE_FOLDING_OR_ENDING; } else { - _headerValue.writeCharCode(byte); + _headerValue.add(byte); } break; @@ -289,16 +289,16 @@ class MimeMultipartTransformer if (byte == _CharCode.SP || byte == _CharCode.HT) { _state = _HEADER_VALUE_START; } else { - String headerField = _headerField.toString(); - String headerValue =_headerValue.toString(); + String headerField = UTF8.decode(_headerField); + String headerValue = UTF8.decode(_headerValue); _headers[headerField.toLowerCase()] = headerValue; - _headerField = new StringBuffer(); - _headerValue = new StringBuffer(); + _headerField = []; + _headerValue = []; if (byte == _CharCode.CR) { _state = _HEADER_ENDING; } else { // Start of new header field. - _headerField.writeCharCode(_toLowerCase(byte)); + _headerField.add(_toLowerCase(byte)); _state = _HEADER_FIELD; } } From a09e4370eeae25b7ba420ca69038de420224ab86 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" Date: Wed, 6 Nov 2013 03:27:58 +0000 Subject: [PATCH 010/118] add versions and constraints for packages and samples - all packages at 0.9.0, except "analyzer" which had a version already - dependencies at ">=0.9.0 <0.10.0" except analyzer is ">=0.10.0 <0.11.0" - sdk constraint ">=1.0.0 <2.0.0" R=sigmund@google.com Review URL: https://codereview.chromium.org//59763006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@29957 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/pubspec.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 174820c03..d3891a651 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,6 +1,9 @@ name: mime +version: 0.9.0 author: Dart Team description: Helper-package for working with MIME. homepage: http://www.dartlang.org dev_dependencies: - unittest: any + unittest: ">=0.9.0 <0.10.0" +environment: + sdk: ">=1.0.0 <2.0.0" From bdec88694f6d13a04973cb663955d6e7215a7c26 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Wed, 6 Nov 2013 09:09:18 +0000 Subject: [PATCH 011/118] Revert "add versions and constraints for packages and samples" This is currently blocking us from testing samples. BUG= R=kasperl@google.com Review URL: https://codereview.chromium.org//59513007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@29960 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/pubspec.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index d3891a651..174820c03 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,9 +1,6 @@ name: mime -version: 0.9.0 author: Dart Team description: Helper-package for working with MIME. homepage: http://www.dartlang.org dev_dependencies: - unittest: ">=0.9.0 <0.10.0" -environment: - sdk: ">=1.0.0 <2.0.0" + unittest: any From ee8ef9d7ce8cf99784449fb606a2649c2729d3d5 Mon Sep 17 00:00:00 2001 From: "dgrove@google.com" Date: Wed, 6 Nov 2013 18:28:22 +0000 Subject: [PATCH 012/118] Re-land r29957 (add versions and constraints for packages and samples), with SDK constraints bumped from 1.0.0 to 0.8.10+6 . R=ricow@google.com, sigmund@google.com Review URL: https://codereview.chromium.org//62473002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@29986 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/pubspec.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 174820c03..0ce9b2ac8 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,6 +1,9 @@ name: mime +version: 0.9.0 author: Dart Team description: Helper-package for working with MIME. homepage: http://www.dartlang.org dev_dependencies: - unittest: any + unittest: ">=0.9.0 <0.10.0" +environment: + sdk: ">=0.8.10+6 <2.0.0" From f6f6d0cafe67609c2156f491c838b247bcaae2f3 Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" Date: Mon, 13 Jan 2014 18:07:45 +0000 Subject: [PATCH 013/118] pkg/unittest: added LICENSE R=rnystrom@google.com Review URL: https://codereview.chromium.org//135343002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@31750 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/LICENSE | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 pkgs/mime/LICENSE diff --git a/pkgs/mime/LICENSE b/pkgs/mime/LICENSE new file mode 100644 index 000000000..5c60afea3 --- /dev/null +++ b/pkgs/mime/LICENSE @@ -0,0 +1,26 @@ +Copyright 2014, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 083c31b5901c6ec1606fd984425b8caadae60f9a Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" Date: Tue, 28 Jan 2014 17:24:08 +0000 Subject: [PATCH 014/118] pkg/mime: formatting, finals, consts, etc R=ajohnsen@google.com Review URL: https://codereview.chromium.org//141433024 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@32072 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/src/extension_map.dart | 2 +- pkgs/mime/lib/src/magic_number.dart | 36 ++++++++++++++-------------- pkgs/mime/lib/src/mime_type.dart | 23 ++++++++---------- 3 files changed, 29 insertions(+), 32 deletions(-) diff --git a/pkgs/mime/lib/src/extension_map.dart b/pkgs/mime/lib/src/extension_map.dart index ac534aea5..745556b54 100644 --- a/pkgs/mime/lib/src/extension_map.dart +++ b/pkgs/mime/lib/src/extension_map.dart @@ -6,7 +6,7 @@ part of mime; // TODO(ajohnsen): Use sorted list and binary search? -Map _defaultExtensionMap = const { +const Map _DEFAULT_EXTENSION_MAP = const { '123':'application/vnd.lotus-1-2-3', '3dml':'text/vnd.in3d.3dml', '3ds':'image/x-3ds', diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 451a09344..1229b6dab 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -28,22 +28,22 @@ class _MagicNumber { } -int _defaultMagicNumbersMaxLength = 16; - -List<_MagicNumber> _defaultMagicNumbers = const [ -const _MagicNumber('application/pdf', const [0x25, 0x50, 0x44, 0x46]), -const _MagicNumber('application/postscript', const [0x25, 0x51]), -const _MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), -const _MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), -const _MagicNumber('image/jpeg', const [0xFF, 0xD8]), -const _MagicNumber('image/png', - const [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), -const _MagicNumber('image/tiff', const [0x49, 0x49, 0x2A, 0x00]), -const _MagicNumber('image/tiff', const [0x4D, 0x4D, 0x00, 0x2A]), -const _MagicNumber('video/mp4', - const [0x00, 0x00, 0x00, 0x00, 0x66, 0x74, - 0x79, 0x70, 0x33, 0x67, 0x70, 0x35], - mask: const [0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]) +const int _DEFAULT_MAGIC_NUMBERS_MAX_LENGTH = 16; + +const List<_MagicNumber> _DEFAULT_MAGIC_NUMBERS = const [ + const _MagicNumber('application/pdf', const [0x25, 0x50, 0x44, 0x46]), + const _MagicNumber('application/postscript', const [0x25, 0x51]), + const _MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), + const _MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), + const _MagicNumber('image/jpeg', const [0xFF, 0xD8]), + const _MagicNumber('image/png', + const [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), + const _MagicNumber('image/tiff', const [0x49, 0x49, 0x2A, 0x00]), + const _MagicNumber('image/tiff', const [0x4D, 0x4D, 0x00, 0x2A]), + const _MagicNumber( + 'video/mp4', + const [0x00, 0x00, 0x00, 0x00, 0x66, 0x74, + 0x79, 0x70, 0x33, 0x67, 0x70, 0x35], + mask: const [0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]) ]; - diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index cd08cdfd8..c9daa2bd3 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -5,12 +5,12 @@ part of mime; -MimeTypeResolver _globalResolver = new MimeTypeResolver(); +final MimeTypeResolver _globalResolver = new MimeTypeResolver(); /** * The maximum number of bytes needed, to match all default magic-numbers. */ -int get defaultMagicNumbersMaxLength => _defaultMagicNumbersMaxLength; +int get defaultMagicNumbersMaxLength => _DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; /** * Extract the extension from [path] and use that for MIME-type lookup, using @@ -24,10 +24,8 @@ int get defaultMagicNumbersMaxLength => _defaultMagicNumbersMaxLength; * [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't * be matched against. */ -String lookupMimeType(String path, - {List headerBytes}) - => _globalResolver.lookup(path, headerBytes: headerBytes); - +String lookupMimeType(String path, {List headerBytes}) => + _globalResolver.lookup(path, headerBytes: headerBytes); /** * MIME-type resolver class, used to customize the lookup of mime-types. @@ -35,7 +33,7 @@ String lookupMimeType(String path, class MimeTypeResolver { final Map _extensionMap = {}; final List<_MagicNumber> _magicNumbers = []; - bool _useDefault; + final bool _useDefault; int _magicNumbersMaxLength; /** @@ -48,7 +46,7 @@ class MimeTypeResolver { */ MimeTypeResolver() : _useDefault = true, - _magicNumbersMaxLength = _defaultMagicNumbersMaxLength; + _magicNumbersMaxLength = _DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; /** * Get the maximum number of bytes required to match all magic numbers, when @@ -67,14 +65,13 @@ class MimeTypeResolver { * [magicNumbersMaxLength] bytes was provided, some magic-numbers won't * be matched against. */ - String lookup(String path, - {List headerBytes}) { + String lookup(String path, {List headerBytes}) { String result; if (headerBytes != null) { - result =_matchMagic(headerBytes, _magicNumbers); + result = _matchMagic(headerBytes, _magicNumbers); if (result != null) return result; if (_useDefault) { - result =_matchMagic(headerBytes, _defaultMagicNumbers); + result = _matchMagic(headerBytes, _DEFAULT_MAGIC_NUMBERS); if (result != null) return result; } } @@ -82,7 +79,7 @@ class MimeTypeResolver { result = _extensionMap[ext]; if (result != null) return result; if (_useDefault) { - result = _defaultExtensionMap[ext]; + result = _DEFAULT_EXTENSION_MAP[ext]; if (result != null) return result; } return null; From 69a3038e63b3edf643d0dcdc515c327ddc5a70ff Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" Date: Tue, 13 May 2014 17:49:01 +0000 Subject: [PATCH 015/118] pkg/mime: layout as mini-libraries Update version for publishing Updated max unittest dependency version R=ajohnsen@google.com Review URL: https://codereview.chromium.org//272353002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@36115 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/mime.dart | 10 +-- ...on_map.dart => default_extension_map.dart} | 5 +- pkgs/mime/lib/src/magic_number.dart | 29 ++++---- .../lib/src/mime_multipart_transformer.dart | 21 +++--- pkgs/mime/lib/src/mime_type.dart | 19 ++--- pkgs/mime/pubspec.yaml | 8 +-- .../test/mime_multipart_transformer_test.dart | 66 +++++++---------- pkgs/mime/test/mime_type_test.dart | 72 ++++++++++--------- 8 files changed, 111 insertions(+), 119 deletions(-) rename pkgs/mime/lib/src/{extension_map.dart => default_extension_map.dart} (99%) diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart index d1372d44c..11b2ca94f 100644 --- a/pkgs/mime/lib/mime.dart +++ b/pkgs/mime/lib/mime.dart @@ -14,11 +14,5 @@ */ library mime; -import 'dart:async'; -import 'dart:convert'; -import 'dart:typed_data'; - -part 'src/mime_type.dart'; -part 'src/extension_map.dart'; -part 'src/magic_number.dart'; -part 'src/mime_multipart_transformer.dart'; +export 'src/mime_multipart_transformer.dart'; +export 'src/mime_type.dart'; diff --git a/pkgs/mime/lib/src/extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart similarity index 99% rename from pkgs/mime/lib/src/extension_map.dart rename to pkgs/mime/lib/src/default_extension_map.dart index 745556b54..7e74648d3 100644 --- a/pkgs/mime/lib/src/extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -2,11 +2,10 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -part of mime; - +library mime.extension_map; // TODO(ajohnsen): Use sorted list and binary search? -const Map _DEFAULT_EXTENSION_MAP = const { +const Map DEFAULT_EXTENSION_MAP = const { '123':'application/vnd.lotus-1-2-3', '3dml':'text/vnd.in3d.3dml', '3ds':'image/x-3ds', diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 1229b6dab..6c554aaa4 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -2,15 +2,14 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -part of mime; +library mime.magic_number; - -class _MagicNumber { +class MagicNumber { final String mimeType; final List numbers; final List mask; - const _MagicNumber(this.mimeType, this.numbers, {this.mask}); + const MagicNumber(this.mimeType, this.numbers, {this.mask}); bool matches(List header) { if (header.length < numbers.length) return false; @@ -28,19 +27,17 @@ class _MagicNumber { } -const int _DEFAULT_MAGIC_NUMBERS_MAX_LENGTH = 16; - -const List<_MagicNumber> _DEFAULT_MAGIC_NUMBERS = const [ - const _MagicNumber('application/pdf', const [0x25, 0x50, 0x44, 0x46]), - const _MagicNumber('application/postscript', const [0x25, 0x51]), - const _MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), - const _MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), - const _MagicNumber('image/jpeg', const [0xFF, 0xD8]), - const _MagicNumber('image/png', +const List DEFAULT_MAGIC_NUMBERS = const [ + const MagicNumber('application/pdf', const [0x25, 0x50, 0x44, 0x46]), + const MagicNumber('application/postscript', const [0x25, 0x51]), + const MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), + const MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), + const MagicNumber('image/jpeg', const [0xFF, 0xD8]), + const MagicNumber('image/png', const [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), - const _MagicNumber('image/tiff', const [0x49, 0x49, 0x2A, 0x00]), - const _MagicNumber('image/tiff', const [0x4D, 0x4D, 0x00, 0x2A]), - const _MagicNumber( + const MagicNumber('image/tiff', const [0x49, 0x49, 0x2A, 0x00]), + const MagicNumber('image/tiff', const [0x4D, 0x4D, 0x00, 0x2A]), + const MagicNumber( 'video/mp4', const [0x00, 0x00, 0x00, 0x00, 0x66, 0x74, 0x79, 0x70, 0x33, 0x67, 0x70, 0x35], diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart index a35b49136..75d10ff71 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -2,8 +2,11 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -part of mime; +library mime.multipart_transformer; +import 'dart:async'; +import 'dart:convert'; +import 'dart:typed_data'; /** * A Mime Multipart class representing each part parsed by @@ -30,12 +33,6 @@ class _MimeMultipart extends MimeMultipart { } } -class _Const { - // Bytes for '()<>@,;:\\"/[]?={} \t'. - static const SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, - 91, 93, 63, 61, 123, 125, 32, 9]; -} - class _CharCode { static const int HT = 9; static const int LF = 10; @@ -71,6 +68,10 @@ class MimeMultipartTransformer static const int _DONE = 14; static const int _FAILURE = 15; + // Bytes for '()<>@,;:\\"/[]?={} \t'. + static const _SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, + 91, 93, 63, 61, 123, 125, 32, 9]; + StreamController _controller; StreamSubscription _subscription; @@ -387,7 +388,7 @@ class MimeMultipartTransformer } bool _isTokenChar(int byte) { - return byte > 31 && byte < 128 && _Const.SEPARATORS.indexOf(byte) == -1; + return byte > 31 && byte < 128 && _SEPARATORS.indexOf(byte) == -1; } int _toLowerCase(int byte) { @@ -412,7 +413,9 @@ class MimeMultipartTransformer class MimeMultipartException implements Exception { + final String message; + const MimeMultipartException([String this.message = ""]); + String toString() => "MimeMultipartException: $message"; - final String message; } diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index c9daa2bd3..ca4d6c51a 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -2,15 +2,18 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -part of mime; +library mime.mime_type; +import 'default_extension_map.dart'; +import 'magic_number.dart'; final MimeTypeResolver _globalResolver = new MimeTypeResolver(); /** * The maximum number of bytes needed, to match all default magic-numbers. */ -int get defaultMagicNumbersMaxLength => _DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; +// NOTE: this is not formatted AS_A_CONST to avoid a breaking change +const int defaultMagicNumbersMaxLength = 12; /** * Extract the extension from [path] and use that for MIME-type lookup, using @@ -32,7 +35,7 @@ String lookupMimeType(String path, {List headerBytes}) => */ class MimeTypeResolver { final Map _extensionMap = {}; - final List<_MagicNumber> _magicNumbers = []; + final List _magicNumbers = []; final bool _useDefault; int _magicNumbersMaxLength; @@ -46,7 +49,7 @@ class MimeTypeResolver { */ MimeTypeResolver() : _useDefault = true, - _magicNumbersMaxLength = _DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; + _magicNumbersMaxLength = defaultMagicNumbersMaxLength; /** * Get the maximum number of bytes required to match all magic numbers, when @@ -71,7 +74,7 @@ class MimeTypeResolver { result = _matchMagic(headerBytes, _magicNumbers); if (result != null) return result; if (_useDefault) { - result = _matchMagic(headerBytes, _DEFAULT_MAGIC_NUMBERS); + result = _matchMagic(headerBytes, DEFAULT_MAGIC_NUMBERS); if (result != null) return result; } } @@ -79,7 +82,7 @@ class MimeTypeResolver { result = _extensionMap[ext]; if (result != null) return result; if (_useDefault) { - result = _DEFAULT_EXTENSION_MAP[ext]; + result = DEFAULT_EXTENSION_MAP[ext]; if (result != null) return result; } return null; @@ -106,11 +109,11 @@ class MimeTypeResolver { if (bytes.length > _magicNumbersMaxLength) { _magicNumbersMaxLength = bytes.length; } - _magicNumbers.add(new _MagicNumber(mimeType, bytes, mask: mask)); + _magicNumbers.add(new MagicNumber(mimeType, bytes, mask: mask)); } static String _matchMagic(List headerBytes, - List<_MagicNumber> magicNumbers) { + List magicNumbers) { for (var mn in magicNumbers) { if (mn.matches(headerBytes)) return mn.mimeType; } diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 0ce9b2ac8..b44361b52 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,9 +1,9 @@ name: mime -version: 0.9.0 +version: 0.9.0+1 author: Dart Team description: Helper-package for working with MIME. homepage: http://www.dartlang.org -dev_dependencies: - unittest: ">=0.9.0 <0.10.0" environment: - sdk: ">=0.8.10+6 <2.0.0" + sdk: '>=1.0.0 <2.0.0' +dev_dependencies: + unittest: '>=0.9.0 <0.11.0' diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 7d7bacaae..7bc2d7d92 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -2,12 +2,13 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import "package:unittest/unittest.dart"; -import "package:mime/mime.dart"; import 'dart:async'; import 'dart:math'; -void testParse(String message, +import "package:unittest/unittest.dart"; +import "package:mime/mime.dart"; + +void _testParse(String message, String boundary, [List expectedHeaders, List expectedParts, @@ -67,20 +68,9 @@ void testParse(String message, }); } -void testParseValid() { - String message; - Map headers; - Map headers1; - Map headers2; - Map headers3; - Map headers4; - String body1; - String body2; - String body3; - String body4; - +void _testParseValid() { // Sample from Wikipedia. - message = """ + var message = """ This is a message with multiple parts in MIME format.\r --frontier\r Content-Type: text/plain\r @@ -93,14 +83,14 @@ Content-Transfer-Encoding: base64\r PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\r --frontier--\r\n"""; - headers1 = {"content-type": "text/plain"}; - headers2 = {"content-type": "application/octet-stream", + var headers1 = {"content-type": "text/plain"}; + var headers2 = {"content-type": "application/octet-stream", "content-transfer-encoding": "base64"}; - body1 = "This is the body of the message."; - body2 = """ + var body1 = "This is the body of the message."; + var body2 = """ PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg="""; - testParse(message, "frontier", [headers1, headers2], [body1, body2]); + _testParse(message, "frontier", [headers1, headers2], [body1, body2]); // Sample from HTML 4.01 Specification. message = """ @@ -122,7 +112,7 @@ Content-Type: text/plain\r }; body1 = "Larry"; body2 = "... contents of file1.txt ..."; - testParse(message, "AaB03x", [headers1, headers2], [body1, body2]); + _testParse(message, "AaB03x", [headers1, headers2], [body1, body2]); // Longer form from submitting the following from Chrome. // @@ -164,15 +154,15 @@ on\r "content-disposition": "form-data; name=\"text_input\""}; headers2 = { "content-disposition": "form-data; name=\"password_input\""}; - headers3 = { + var headers3 = { "content-disposition": "form-data; name=\"checkbox_input\""}; - headers4 = { + var headers4 = { "content-disposition": "form-data; name=\"radio_input\""}; body1 = "text"; body2 = "password"; - body3 = "on"; - body4 = "on"; - testParse(message, + var body3 = "on"; + var body4 = "on"; + _testParse(message, "----WebKitFormBoundaryQ3cgYAmGRF8yOeYB", [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); @@ -196,7 +186,7 @@ Content-Disposition: form-data; name=\"radio_input\"\r \r on\r -----------------------------52284550912143824192005403738--\r\n"""; - testParse(message, + _testParse(message, "---------------------------52284550912143824192005403738", [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); @@ -220,7 +210,7 @@ Content-Disposition: form-data; name=\"radio_input\"\r \r on\r -----------------------------7dc8f38c60326--\r\n"""; - testParse(message, + _testParse(message, "---------------------------7dc8f38c60326", [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); @@ -261,7 +251,7 @@ Content-Type: text/plain\r --\r\r\r -\r\r --boundary--\r\n"""; - headers = {"content-type": "text/plain"}; + var headers = {"content-type": "text/plain"}; body1 = """ -\r --\r @@ -282,7 +272,7 @@ Content-Type: text/plain\r --b\r\r\r\r --\r\r\r -\r"""; - testParse(message, "boundary", [headers, headers], [body1, body2]); + _testParse(message, "boundary", [headers, headers], [body1, body2]); // Without initial CRLF. message = """ @@ -295,14 +285,12 @@ Body 1\r \r Body2\r --xxx--\r\n"""; - testParse(message, "xxx", null, ["\r\nBody 1", "\r\nBody2"]); + _testParse(message, "xxx", null, ["\r\nBody 1", "\r\nBody2"]); } -void testParseInvalid() { - String message; - +void _testParseInvalid() { // Missing end boundary. - message = """ + var message = """ \r --xxx\r \r @@ -313,10 +301,10 @@ Body 1\r \r Body2\r --xxx\r\n"""; - testParse(message, "xxx", null, [null, null], true); + _testParse(message, "xxx", null, [null, null], true); } void main() { - testParseValid(); - testParseInvalid(); + _testParseValid(); + _testParseInvalid(); } diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 36c728d80..23cc10e3c 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -2,10 +2,13 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import "package:unittest/unittest.dart"; +import 'dart:math' as math; + +import 'package:unittest/unittest.dart'; import 'package:mime/mime.dart'; +import 'package:mime/src/magic_number.dart'; -void expectMimeType(String path, +void _expectMimeType(String path, String expectedMimeType, {List headerBytes, MimeTypeResolver resolver}) { @@ -16,51 +19,49 @@ void expectMimeType(String path, mimeType = resolver.lookup(path, headerBytes: headerBytes); } - if (mimeType != expectedMimeType) { - throw "Expect '$expectedMimeType' but got '$mimeType'"; - } + expect(mimeType, expectedMimeType); } void main() { group('global-lookup', () { test('by-path', () { - expectMimeType('file.dart', 'application/dart'); + _expectMimeType('file.dart', 'application/dart'); // Test mixed-case - expectMimeType('file.DaRT', 'application/dart'); - expectMimeType('file.html', 'text/html'); - expectMimeType('file.xhtml', 'application/xhtml+xml'); - expectMimeType('file.jpeg', 'image/jpeg'); - expectMimeType('file.jpg', 'image/jpeg'); - expectMimeType('file.png', 'image/png'); - expectMimeType('file.gif', 'image/gif'); - expectMimeType('file.cc', 'text/x-c'); - expectMimeType('file.c', 'text/x-c'); - expectMimeType('file.css', 'text/css'); - expectMimeType('file.js', 'application/javascript'); - expectMimeType('file.ps', 'application/postscript'); - expectMimeType('file.pdf', 'application/pdf'); - expectMimeType('file.tiff', 'image/tiff'); - expectMimeType('file.tif', 'image/tiff'); + _expectMimeType('file.DaRT', 'application/dart'); + _expectMimeType('file.html', 'text/html'); + _expectMimeType('file.xhtml', 'application/xhtml+xml'); + _expectMimeType('file.jpeg', 'image/jpeg'); + _expectMimeType('file.jpg', 'image/jpeg'); + _expectMimeType('file.png', 'image/png'); + _expectMimeType('file.gif', 'image/gif'); + _expectMimeType('file.cc', 'text/x-c'); + _expectMimeType('file.c', 'text/x-c'); + _expectMimeType('file.css', 'text/css'); + _expectMimeType('file.js', 'application/javascript'); + _expectMimeType('file.ps', 'application/postscript'); + _expectMimeType('file.pdf', 'application/pdf'); + _expectMimeType('file.tiff', 'image/tiff'); + _expectMimeType('file.tif', 'image/tiff'); }); test('unknown-mime-type', () { - expectMimeType('file.unsupported-extension', null); + _expectMimeType('file.unsupported-extension', null); }); test('by-header-bytes', () { - expectMimeType('file.jpg', + _expectMimeType('file.jpg', 'image/png', headerBytes: [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]); - expectMimeType('file.jpg', + _expectMimeType('file.jpg', 'image/gif', headerBytes: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x0D, 0x0A, 0x1A, 0x0A]); - expectMimeType('file.gif', + _expectMimeType('file.gif', 'image/jpeg', headerBytes: [0xFF, 0xD8, 0x46, 0x38, 0x39, 0x61, 0x0D, 0x0A, 0x1A, 0x0A]); - expectMimeType('file.mp4', + _expectMimeType('file.mp4', 'video/mp4', headerBytes: [0x00, 0x00, 0x00, 0x04, 0x66, 0x74, 0x79, 0x70, 0x33, 0x67, 0x70, 0x35]); @@ -71,13 +72,13 @@ void main() { test('override-extension', () { var resolver = new MimeTypeResolver(); resolver.addExtension('jpg', 'my-mime-type'); - expectMimeType('file.jpg', 'my-mime-type', resolver: resolver); + _expectMimeType('file.jpg', 'my-mime-type', resolver: resolver); }); test('fallthrough-extension', () { var resolver = new MimeTypeResolver(); resolver.addExtension('jpg2', 'my-mime-type'); - expectMimeType('file.jpg', 'image/jpeg', resolver: resolver); + _expectMimeType('file.jpg', 'image/jpeg', resolver: resolver); }); test('with-mask', () { @@ -85,19 +86,26 @@ void main() { resolver.addMagicNumber([0x01, 0x02, 0x03], 'my-mime-type', mask: [0x01, 0xFF, 0xFE]); - expectMimeType('file', + _expectMimeType('file', 'my-mime-type', headerBytes: [0x01, 0x02, 0x03], resolver: resolver); - expectMimeType('file', + _expectMimeType('file', null, headerBytes: [0x01, 0x03, 0x03], resolver: resolver); - expectMimeType('file', + _expectMimeType('file', 'my-mime-type', headerBytes: [0xFF, 0x02, 0x02], resolver: resolver); }); }); -} + test('default magic number', () { + var actualMaxBytes = DEFAULT_MAGIC_NUMBERS.fold(0, (previous, magic) { + return math.max(previous, magic.numbers.length); + }); + + expect(defaultMagicNumbersMaxLength, actualMaxBytes); + }); +} From 586e7e3d102844741eb33474619ca68868c2f4d3 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Fri, 23 May 2014 07:07:15 +0000 Subject: [PATCH 016/118] Clean up mime package. Also speed up default mime-type map, by not using a const map. BUG= R=kevmoo@google.com Review URL: https://codereview.chromium.org//292983002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@36543 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/src/default_extension_map.dart | 4 ++-- pkgs/mime/lib/src/magic_number.dart | 2 ++ pkgs/mime/lib/src/mime_type.dart | 7 +++---- pkgs/mime/pubspec.yaml | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index 7e74648d3..ae0d7df5d 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -4,8 +4,8 @@ library mime.extension_map; -// TODO(ajohnsen): Use sorted list and binary search? -const Map DEFAULT_EXTENSION_MAP = const { +// TODO(ajohnsen): Use const map once Issue 7559 is fixed. +final Map defaultExtensionMap = { '123':'application/vnd.lotus-1-2-3', '3dml':'text/vnd.in3d.3dml', '3ds':'image/x-3ds', diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 6c554aaa4..3efb2ee73 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -27,6 +27,8 @@ class MagicNumber { } +const int DEFAULT_MAGIC_NUMBERS_MAX_LENGTH = 12; + const List DEFAULT_MAGIC_NUMBERS = const [ const MagicNumber('application/pdf', const [0x25, 0x50, 0x44, 0x46]), const MagicNumber('application/postscript', const [0x25, 0x51]), diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index ca4d6c51a..744eead87 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -12,8 +12,7 @@ final MimeTypeResolver _globalResolver = new MimeTypeResolver(); /** * The maximum number of bytes needed, to match all default magic-numbers. */ -// NOTE: this is not formatted AS_A_CONST to avoid a breaking change -const int defaultMagicNumbersMaxLength = 12; +int get defaultMagicNumbersMaxLength => _globalResolver.magicNumbersMaxLength; /** * Extract the extension from [path] and use that for MIME-type lookup, using @@ -49,7 +48,7 @@ class MimeTypeResolver { */ MimeTypeResolver() : _useDefault = true, - _magicNumbersMaxLength = defaultMagicNumbersMaxLength; + _magicNumbersMaxLength = DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; /** * Get the maximum number of bytes required to match all magic numbers, when @@ -82,7 +81,7 @@ class MimeTypeResolver { result = _extensionMap[ext]; if (result != null) return result; if (_useDefault) { - result = DEFAULT_EXTENSION_MAP[ext]; + result = defaultExtensionMap[ext]; if (result != null) return result; } return null; diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index b44361b52..54dc5a830 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.0+1 +version: 0.9.0+2 author: Dart Team description: Helper-package for working with MIME. homepage: http://www.dartlang.org From 17b4eeb6f386dd2f0f7596e64d2541f15ef7bd6b Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" Date: Fri, 30 May 2014 17:38:57 +0000 Subject: [PATCH 017/118] pkg/mime: Removed mutable state from MimeMultipartTransformer R=ajohnsen@google.com Review URL: https://codereview.chromium.org//307963004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@36825 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/mime.dart | 1 + pkgs/mime/lib/src/bound_multipart_stream.dart | 375 ++++++++++++++++ pkgs/mime/lib/src/char_code.dart | 16 + .../lib/src/mime_multipart_transformer.dart | 408 +----------------- pkgs/mime/lib/src/mime_shared.dart | 22 + pkgs/mime/pubspec.yaml | 4 +- 6 files changed, 434 insertions(+), 392 deletions(-) create mode 100644 pkgs/mime/lib/src/bound_multipart_stream.dart create mode 100644 pkgs/mime/lib/src/char_code.dart create mode 100644 pkgs/mime/lib/src/mime_shared.dart diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart index 11b2ca94f..dce677488 100644 --- a/pkgs/mime/lib/mime.dart +++ b/pkgs/mime/lib/mime.dart @@ -15,4 +15,5 @@ library mime; export 'src/mime_multipart_transformer.dart'; +export 'src/mime_shared.dart'; export 'src/mime_type.dart'; diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart new file mode 100644 index 000000000..d470034f1 --- /dev/null +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -0,0 +1,375 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +library mime.bound_multipart_stream; + +import 'dart:async'; +import 'dart:convert'; + +import 'mime_shared.dart'; +import 'char_code.dart'; + +// Bytes for '()<>@,;:\\"/[]?={} \t'. +const _SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, 91, 93, + 63, 61, 123, 125, 32, 9]; + +bool _isTokenChar(int byte) { + return byte > 31 && byte < 128 && _SEPARATORS.indexOf(byte) == -1; +} + +int _toLowerCase(int byte) { + const delta = CharCode.LOWER_A - CharCode.UPPER_A; + return (CharCode.UPPER_A <= byte && byte <= CharCode.UPPER_Z) ? + byte + delta : byte; +} + +void _expectByteValue(int val1, int val2) { + if (val1 != val2) { + throw new MimeMultipartException("Failed to parse multipart mime 1"); + } +} + +void _expectWhitespace(int byte) { + if (byte != CharCode.SP && byte != CharCode.HT) { + throw new MimeMultipartException("Failed to parse multipart mime 2"); + } +} + +class _MimeMultipart extends MimeMultipart { + final Map headers; + final Stream> _stream; + + _MimeMultipart(this.headers, this._stream); + + StreamSubscription> listen(void onData(List data), + {void onDone(), + Function onError, + bool cancelOnError}) { + return _stream.listen(onData, + onDone: onDone, + onError: onError, + cancelOnError: cancelOnError); + } +} + +class BoundMultipartStream { + static const int _START = 0; + static const int _FIRST_BOUNDARY_ENDING = 111; + static const int _FIRST_BOUNDARY_END = 112; + static const int _BOUNDARY_ENDING = 1; + static const int _BOUNDARY_END = 2; + static const int _HEADER_START = 3; + static const int _HEADER_FIELD = 4; + static const int _HEADER_VALUE_START = 5; + static const int _HEADER_VALUE = 6; + static const int _HEADER_VALUE_FOLDING_OR_ENDING = 7; + static const int _HEADER_VALUE_FOLD_OR_END = 8; + static const int _HEADER_ENDING = 9; + static const int _CONTENT = 10; + static const int _LAST_BOUNDARY_DASH2 = 11; + static const int _LAST_BOUNDARY_ENDING = 12; + static const int _LAST_BOUNDARY_END = 13; + static const int _DONE = 14; + static const int _FAIL = 15; + + final List _boundary; + final List _headerField = []; + final List _headerValue = []; + + StreamController _controller; + + Stream get stream => _controller.stream; + + StreamSubscription _subscription; + + StreamController _multipartController; + Map _headers; + + int _state = _START; + int _boundaryIndex = 2; + + // Current index in the data buffer. If index is negative then it + // is the index into the artificial prefix of the boundary string. + int _index; + List _buffer; + + BoundMultipartStream(this._boundary, Stream> stream) { + _controller = new StreamController( + sync: true, + onPause: _pauseStream, + onResume:_resumeStream, + onCancel: () { + _subscription.cancel(); + }, + onListen: () { + _subscription = stream.listen( + (data) { + assert(_buffer == null); + _pauseStream(); + _buffer = data; + _index = 0; + _parse(); + }, + onDone: () { + if (_state != _DONE) { + _controller.addError( + new MimeMultipartException("Bad multipart ending")); + } + _controller.close(); + }, + onError: _controller.addError); + }); + } + + void _resumeStream() { + _subscription.resume(); + } + + void _pauseStream() { + _subscription.pause(); + } + + + void _parse() { + // Number of boundary bytes to artificially place before the supplied data. + int boundaryPrefix = 0; + // Position where content starts. Will be null if no known content + // start exists. Will be negative of the content starts in the + // boundary prefix. Will be zero or position if the content starts + // in the current buffer. + int contentStartIndex; + + // Function to report content data for the current part. The data + // reported is from the current content start index up til the + // current index. As the data can be artificially prefixed with a + // prefix of the boundary both the content start index and index + // can be negative. + void reportData() { + if (contentStartIndex < 0) { + var contentLength = boundaryPrefix + _index - _boundaryIndex; + if (contentLength <= boundaryPrefix) { + _multipartController.add( + _boundary.sublist(0, contentLength)); + } else { + _multipartController.add( + _boundary.sublist(0, boundaryPrefix)); + _multipartController.add( + _buffer.sublist(0, contentLength - boundaryPrefix)); + } + } else { + var contentEndIndex = _index - _boundaryIndex; + _multipartController.add( + _buffer.sublist(contentStartIndex, contentEndIndex)); + } + } + + if (_state == _CONTENT && _boundaryIndex == 0) { + contentStartIndex = 0; + } else { + contentStartIndex = null; + } + // The data to parse might be "artificially" prefixed with a + // partial match of the boundary. + boundaryPrefix = _boundaryIndex; + + while ((_index < _buffer.length) && _state != _FAIL && _state != _DONE) { + if (_multipartController != null && _multipartController.isPaused) { + return; + } + int byte; + if (_index < 0) { + byte = _boundary[boundaryPrefix + _index]; + } else { + byte = _buffer[_index]; + } + switch (_state) { + case _START: + if (byte == _boundary[_boundaryIndex]) { + _boundaryIndex++; + if (_boundaryIndex == _boundary.length) { + _state = _FIRST_BOUNDARY_ENDING; + _boundaryIndex = 0; + } + } else { + // Restart matching of the boundary. + _index = _index - _boundaryIndex; + _boundaryIndex = 0; + } + break; + + case _FIRST_BOUNDARY_ENDING: + if (byte == CharCode.CR) { + _state = _FIRST_BOUNDARY_END; + } else { + _expectWhitespace(byte); + } + break; + + case _FIRST_BOUNDARY_END: + _expectByteValue(byte, CharCode.LF); + _state = _HEADER_START; + break; + + case _BOUNDARY_ENDING: + if (byte == CharCode.CR) { + _state = _BOUNDARY_END; + } else if (byte == CharCode.DASH) { + _state = _LAST_BOUNDARY_DASH2; + } else { + _expectWhitespace(byte); + } + break; + + case _BOUNDARY_END: + _expectByteValue(byte, CharCode.LF); + _multipartController.close(); + _multipartController = null; + _state = _HEADER_START; + break; + + case _HEADER_START: + _headers = new Map(); + if (byte == CharCode.CR) { + _state = _HEADER_ENDING; + } else { + // Start of new header field. + _headerField.add(_toLowerCase(byte)); + _state = _HEADER_FIELD; + } + break; + + case _HEADER_FIELD: + if (byte == CharCode.COLON) { + _state = _HEADER_VALUE_START; + } else { + if (!_isTokenChar(byte)) { + throw new MimeMultipartException("Invalid header field name"); + } + _headerField.add(_toLowerCase(byte)); + } + break; + + case _HEADER_VALUE_START: + if (byte == CharCode.CR) { + _state = _HEADER_VALUE_FOLDING_OR_ENDING; + } else if (byte != CharCode.SP && byte != CharCode.HT) { + // Start of new header value. + _headerValue.add(byte); + _state = _HEADER_VALUE; + } + break; + + case _HEADER_VALUE: + if (byte == CharCode.CR) { + _state = _HEADER_VALUE_FOLDING_OR_ENDING; + } else { + _headerValue.add(byte); + } + break; + + case _HEADER_VALUE_FOLDING_OR_ENDING: + _expectByteValue(byte, CharCode.LF); + _state = _HEADER_VALUE_FOLD_OR_END; + break; + + case _HEADER_VALUE_FOLD_OR_END: + if (byte == CharCode.SP || byte == CharCode.HT) { + _state = _HEADER_VALUE_START; + } else { + String headerField = UTF8.decode(_headerField); + String headerValue = UTF8.decode(_headerValue); + _headers[headerField.toLowerCase()] = headerValue; + _headerField.clear(); + _headerValue.clear(); + if (byte == CharCode.CR) { + _state = _HEADER_ENDING; + } else { + // Start of new header field. + _headerField.add(_toLowerCase(byte)); + _state = _HEADER_FIELD; + } + } + break; + + case _HEADER_ENDING: + _expectByteValue(byte, CharCode.LF); + _multipartController = new StreamController( + sync: true, + onPause: () { + _pauseStream(); + }, + onResume: () { + _resumeStream(); + _parse(); + }); + _controller.add( + new _MimeMultipart(_headers, _multipartController.stream)); + _headers = null; + _state = _CONTENT; + contentStartIndex = _index + 1; + break; + + case _CONTENT: + if (byte == _boundary[_boundaryIndex]) { + _boundaryIndex++; + if (_boundaryIndex == _boundary.length) { + if (contentStartIndex != null) { + _index++; + reportData(); + _index--; + } + _multipartController.close(); + _boundaryIndex = 0; + _state = _BOUNDARY_ENDING; + } + } else { + // Restart matching of the boundary. + _index = _index - _boundaryIndex; + if (contentStartIndex == null) contentStartIndex = _index; + _boundaryIndex = 0; + } + break; + + case _LAST_BOUNDARY_DASH2: + _expectByteValue(byte, CharCode.DASH); + _state = _LAST_BOUNDARY_ENDING; + break; + + case _LAST_BOUNDARY_ENDING: + if (byte == CharCode.CR) { + _state = _LAST_BOUNDARY_END; + } else { + _expectWhitespace(byte); + } + break; + + case _LAST_BOUNDARY_END: + _expectByteValue(byte, CharCode.LF); + _multipartController.close(); + _multipartController = null; + _state = _DONE; + break; + + default: + // Should be unreachable. + assert(false); + break; + } + + // Move to the next byte. + _index++; + } + + // Report any known content. + if (_state == _CONTENT && contentStartIndex != null) { + reportData(); + } + + // Resume if at end. + if (_index == _buffer.length) { + _buffer = null; + _index = null; + _resumeStream(); + } + } +} diff --git a/pkgs/mime/lib/src/char_code.dart b/pkgs/mime/lib/src/char_code.dart new file mode 100644 index 000000000..f455e681a --- /dev/null +++ b/pkgs/mime/lib/src/char_code.dart @@ -0,0 +1,16 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +library mime.char_code; + +class CharCode { + static const int HT = 9; + static const int LF = 10; + static const int CR = 13; + static const int SP = 32; + static const int DASH = 45; + static const int COLON = 58; + static const int UPPER_A = 65; + static const int UPPER_Z = 90; + static const int LOWER_A = 97; +} diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart index 75d10ff71..3afff2dc3 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -1,45 +1,28 @@ // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. - library mime.multipart_transformer; import 'dart:async'; -import 'dart:convert'; import 'dart:typed_data'; -/** - * A Mime Multipart class representing each part parsed by - * [MimeMultipartTransformer]. The data is streamed in as it become available. - */ -abstract class MimeMultipart extends Stream> { - Map get headers; -} +import 'bound_multipart_stream.dart'; +import 'mime_shared.dart'; +import 'char_code.dart'; -class _MimeMultipart extends MimeMultipart { - final Map headers; - final Stream> _stream; - _MimeMultipart(this.headers, this._stream); - - StreamSubscription> listen(void onData(List data), - {void onDone(), - Function onError, - bool cancelOnError}) { - return _stream.listen(onData, - onDone: onDone, - onError: onError, - cancelOnError: cancelOnError); - } -} +Uint8List _getBoundary(String boundary) { + var charCodes = boundary.codeUnits; -class _CharCode { - static const int HT = 9; - static const int LF = 10; - static const int CR = 13; - static const int SP = 32; - static const int DASH = 45; - static const int COLON = 58; + var boundaryList = new Uint8List(4 + charCodes.length); + // Set-up the matching boundary preceding it with CRLF and two + // dashes. + boundaryList[0] = CharCode.CR; + boundaryList[1] = CharCode.LF; + boundaryList[2] = CharCode.DASH; + boundaryList[3] = CharCode.DASH; + boundaryList.setRange(4, 4 + charCodes.length, charCodes); + return boundaryList; } /** @@ -49,373 +32,18 @@ class _CharCode { */ class MimeMultipartTransformer implements StreamTransformer, MimeMultipart> { - static const int _START = 0; - static const int _FIRST_BOUNDARY_ENDING = 111; - static const int _FIRST_BOUNDARY_END = 112; - static const int _BOUNDARY_ENDING = 1; - static const int _BOUNDARY_END = 2; - static const int _HEADER_START = 3; - static const int _HEADER_FIELD = 4; - static const int _HEADER_VALUE_START = 5; - static const int _HEADER_VALUE = 6; - static const int _HEADER_VALUE_FOLDING_OR_ENDING = 7; - static const int _HEADER_VALUE_FOLD_OR_END = 8; - static const int _HEADER_ENDING = 9; - static const int _CONTENT = 10; - static const int _LAST_BOUNDARY_DASH2 = 11; - static const int _LAST_BOUNDARY_ENDING = 12; - static const int _LAST_BOUNDARY_END = 13; - static const int _DONE = 14; - static const int _FAILURE = 15; - // Bytes for '()<>@,;:\\"/[]?={} \t'. - static const _SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, - 91, 93, 63, 61, 123, 125, 32, 9]; - - StreamController _controller; - StreamSubscription _subscription; - - StreamController _multipartController; - Map _headers; - - List _boundary; - int _state = _START; - int _boundaryIndex = 2; - - // Current index in the data buffer. If index is negative then it - // is the index into the artificial prefix of the boundary string. - int _index; - List _buffer; - - List _headerField = []; - List _headerValue = []; + final List _boundary; /** * Construct a new MIME multipart parser with the boundary * [boundary]. The boundary should be as specified in the content * type parameter, that is without the -- prefix. */ - MimeMultipartTransformer(String boundary) { - List charCodes = boundary.codeUnits; - _boundary = new Uint8List(4 + charCodes.length); - // Set-up the matching boundary preceding it with CRLF and two - // dashes. - _boundary[0] = _CharCode.CR; - _boundary[1] = _CharCode.LF; - _boundary[2] = _CharCode.DASH; - _boundary[3] = _CharCode.DASH; - _boundary.setRange(4, 4 + charCodes.length, charCodes); - } - - void _resumeStream() { - _subscription.resume(); - } - - void _pauseStream() { - _subscription.pause(); - } + MimeMultipartTransformer(String boundary) + : _boundary = _getBoundary(boundary); Stream bind(Stream> stream) { - _controller = new StreamController( - sync: true, - onPause: _pauseStream, - onResume:_resumeStream, - onCancel: () { - _subscription.cancel(); - }, - onListen: () { - _subscription = stream.listen( - (data) { - assert(_buffer == null); - _pauseStream(); - _buffer = data; - _index = 0; - _parse(); - }, - onDone: () { - if (_state != _DONE) { - _controller.addError( - new MimeMultipartException("Bad multipart ending")); - } - _controller.close(); - }, - onError: _controller.addError); - }); - return _controller.stream; - } - - void _parse() { - // Number of boundary bytes to artificially place before the supplied data. - int boundaryPrefix = 0; - // Position where content starts. Will be null if no known content - // start exists. Will be negative of the content starts in the - // boundary prefix. Will be zero or position if the content starts - // in the current buffer. - int contentStartIndex; - - // Function to report content data for the current part. The data - // reported is from the current content start index up til the - // current index. As the data can be artificially prefixed with a - // prefix of the boundary both the content start index and index - // can be negative. - void reportData() { - if (contentStartIndex < 0) { - var contentLength = boundaryPrefix + _index - _boundaryIndex; - if (contentLength <= boundaryPrefix) { - _multipartController.add( - _boundary.sublist(0, contentLength)); - } else { - _multipartController.add( - _boundary.sublist(0, boundaryPrefix)); - _multipartController.add( - _buffer.sublist(0, contentLength - boundaryPrefix)); - } - } else { - var contentEndIndex = _index - _boundaryIndex; - _multipartController.add( - _buffer.sublist(contentStartIndex, contentEndIndex)); - } - } - - if (_state == _CONTENT && _boundaryIndex == 0) { - contentStartIndex = 0; - } else { - contentStartIndex = null; - } - // The data to parse might be "artificially" prefixed with a - // partial match of the boundary. - boundaryPrefix = _boundaryIndex; - - while ((_index < _buffer.length) && _state != _FAILURE && _state != _DONE) { - if (_multipartController != null && _multipartController.isPaused) { - return; - } - int byte; - if (_index < 0) { - byte = _boundary[boundaryPrefix + _index]; - } else { - byte = _buffer[_index]; - } - switch (_state) { - case _START: - if (byte == _boundary[_boundaryIndex]) { - _boundaryIndex++; - if (_boundaryIndex == _boundary.length) { - _state = _FIRST_BOUNDARY_ENDING; - _boundaryIndex = 0; - } - } else { - // Restart matching of the boundary. - _index = _index - _boundaryIndex; - _boundaryIndex = 0; - } - break; - - case _FIRST_BOUNDARY_ENDING: - if (byte == _CharCode.CR) { - _state = _FIRST_BOUNDARY_END; - } else { - _expectWS(byte); - } - break; - - case _FIRST_BOUNDARY_END: - _expect(byte, _CharCode.LF); - _state = _HEADER_START; - break; - - case _BOUNDARY_ENDING: - if (byte == _CharCode.CR) { - _state = _BOUNDARY_END; - } else if (byte == _CharCode.DASH) { - _state = _LAST_BOUNDARY_DASH2; - } else { - _expectWS(byte); - } - break; - - case _BOUNDARY_END: - _expect(byte, _CharCode.LF); - _multipartController.close(); - _multipartController = null; - _state = _HEADER_START; - break; - - case _HEADER_START: - _headers = new Map(); - if (byte == _CharCode.CR) { - _state = _HEADER_ENDING; - } else { - // Start of new header field. - _headerField.add(_toLowerCase(byte)); - _state = _HEADER_FIELD; - } - break; - - case _HEADER_FIELD: - if (byte == _CharCode.COLON) { - _state = _HEADER_VALUE_START; - } else { - if (!_isTokenChar(byte)) { - throw new MimeMultipartException("Invalid header field name"); - } - _headerField.add(_toLowerCase(byte)); - } - break; - - case _HEADER_VALUE_START: - if (byte == _CharCode.CR) { - _state = _HEADER_VALUE_FOLDING_OR_ENDING; - } else if (byte != _CharCode.SP && byte != _CharCode.HT) { - // Start of new header value. - _headerValue.add(byte); - _state = _HEADER_VALUE; - } - break; - - case _HEADER_VALUE: - if (byte == _CharCode.CR) { - _state = _HEADER_VALUE_FOLDING_OR_ENDING; - } else { - _headerValue.add(byte); - } - break; - - case _HEADER_VALUE_FOLDING_OR_ENDING: - _expect(byte, _CharCode.LF); - _state = _HEADER_VALUE_FOLD_OR_END; - break; - - case _HEADER_VALUE_FOLD_OR_END: - if (byte == _CharCode.SP || byte == _CharCode.HT) { - _state = _HEADER_VALUE_START; - } else { - String headerField = UTF8.decode(_headerField); - String headerValue = UTF8.decode(_headerValue); - _headers[headerField.toLowerCase()] = headerValue; - _headerField = []; - _headerValue = []; - if (byte == _CharCode.CR) { - _state = _HEADER_ENDING; - } else { - // Start of new header field. - _headerField.add(_toLowerCase(byte)); - _state = _HEADER_FIELD; - } - } - break; - - case _HEADER_ENDING: - _expect(byte, _CharCode.LF); - _multipartController = new StreamController( - sync: true, - onPause: () { - _pauseStream(); - }, - onResume: () { - _resumeStream(); - _parse(); - }); - _controller.add( - new _MimeMultipart(_headers, _multipartController.stream)); - _headers = null; - _state = _CONTENT; - contentStartIndex = _index + 1; - break; - - case _CONTENT: - if (byte == _boundary[_boundaryIndex]) { - _boundaryIndex++; - if (_boundaryIndex == _boundary.length) { - if (contentStartIndex != null) { - _index++; - reportData(); - _index--; - } - _multipartController.close(); - _boundaryIndex = 0; - _state = _BOUNDARY_ENDING; - } - } else { - // Restart matching of the boundary. - _index = _index - _boundaryIndex; - if (contentStartIndex == null) contentStartIndex = _index; - _boundaryIndex = 0; - } - break; - - case _LAST_BOUNDARY_DASH2: - _expect(byte, _CharCode.DASH); - _state = _LAST_BOUNDARY_ENDING; - break; - - case _LAST_BOUNDARY_ENDING: - if (byte == _CharCode.CR) { - _state = _LAST_BOUNDARY_END; - } else { - _expectWS(byte); - } - break; - - case _LAST_BOUNDARY_END: - _expect(byte, _CharCode.LF); - _multipartController.close(); - _multipartController = null; - _state = _DONE; - break; - - default: - // Should be unreachable. - assert(false); - break; - } - - // Move to the next byte. - _index++; - } - - // Report any known content. - if (_state == _CONTENT && contentStartIndex != null) { - reportData(); - } - - // Resume if at end. - if (_index == _buffer.length) { - _buffer = null; - _index = null; - _resumeStream(); - } + return new BoundMultipartStream(_boundary, stream).stream; } - - bool _isTokenChar(int byte) { - return byte > 31 && byte < 128 && _SEPARATORS.indexOf(byte) == -1; - } - - int _toLowerCase(int byte) { - final int aCode = "A".codeUnitAt(0); - final int zCode = "Z".codeUnitAt(0); - final int delta = "a".codeUnitAt(0) - aCode; - return (aCode <= byte && byte <= zCode) ? byte + delta : byte; - } - - void _expect(int val1, int val2) { - if (val1 != val2) { - throw new MimeMultipartException("Failed to parse multipart mime 1"); - } - } - - void _expectWS(int byte) { - if (byte != _CharCode.SP && byte != _CharCode.HT) { - throw new MimeMultipartException("Failed to parse multipart mime 2"); - } - } -} - - -class MimeMultipartException implements Exception { - final String message; - - const MimeMultipartException([String this.message = ""]); - - String toString() => "MimeMultipartException: $message"; } diff --git a/pkgs/mime/lib/src/mime_shared.dart b/pkgs/mime/lib/src/mime_shared.dart new file mode 100644 index 000000000..6d14e0a61 --- /dev/null +++ b/pkgs/mime/lib/src/mime_shared.dart @@ -0,0 +1,22 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +library mime.shared; + +import 'dart:async'; + +class MimeMultipartException implements Exception { + final String message; + + const MimeMultipartException([String this.message = ""]); + + String toString() => "MimeMultipartException: $message"; +} + +/** + * A Mime Multipart class representing each part parsed by + * [MimeMultipartTransformer]. The data is streamed in as it become available. + */ +abstract class MimeMultipart extends Stream> { + Map get headers; +} diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 54dc5a830..70515824d 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,9 +1,9 @@ name: mime -version: 0.9.0+2 +version: 0.9.0+3 author: Dart Team description: Helper-package for working with MIME. homepage: http://www.dartlang.org environment: sdk: '>=1.0.0 <2.0.0' dev_dependencies: - unittest: '>=0.9.0 <0.11.0' + unittest: '>=0.9.0 <0.12.0' From 3e6e648a501fd3ccd1f0d16cc0d1ea55da7737cb Mon Sep 17 00:00:00 2001 From: "sgjesse@google.com" Date: Tue, 18 Nov 2014 14:40:00 +0000 Subject: [PATCH 018/118] Handle multipart MIME parsing with no parts The multipart MIME parser did not correctly handle the case where there was only the final boundary. R=kustermann@google.com BUG= Review URL: https://codereview.chromium.org//739533002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@41805 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/CHANGELOG.md | 3 ++ pkgs/mime/lib/src/bound_multipart_stream.dart | 29 ++++++------------- pkgs/mime/pubspec.yaml | 2 +- .../test/mime_multipart_transformer_test.dart | 6 +++- 4 files changed, 18 insertions(+), 22 deletions(-) create mode 100644 pkgs/mime/CHANGELOG.md diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md new file mode 100644 index 000000000..eab1ae35f --- /dev/null +++ b/pkgs/mime/CHANGELOG.md @@ -0,0 +1,3 @@ +# 0.9.1 + +* Handle parsing of MIME multipart content with no parts. diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index d470034f1..a049b1d11 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -54,8 +54,6 @@ class _MimeMultipart extends MimeMultipart { class BoundMultipartStream { static const int _START = 0; - static const int _FIRST_BOUNDARY_ENDING = 111; - static const int _FIRST_BOUNDARY_END = 112; static const int _BOUNDARY_ENDING = 1; static const int _BOUNDARY_END = 2; static const int _HEADER_START = 3; @@ -187,7 +185,7 @@ class BoundMultipartStream { if (byte == _boundary[_boundaryIndex]) { _boundaryIndex++; if (_boundaryIndex == _boundary.length) { - _state = _FIRST_BOUNDARY_ENDING; + _state = _BOUNDARY_ENDING; _boundaryIndex = 0; } } else { @@ -197,19 +195,6 @@ class BoundMultipartStream { } break; - case _FIRST_BOUNDARY_ENDING: - if (byte == CharCode.CR) { - _state = _FIRST_BOUNDARY_END; - } else { - _expectWhitespace(byte); - } - break; - - case _FIRST_BOUNDARY_END: - _expectByteValue(byte, CharCode.LF); - _state = _HEADER_START; - break; - case _BOUNDARY_ENDING: if (byte == CharCode.CR) { _state = _BOUNDARY_END; @@ -222,8 +207,10 @@ class BoundMultipartStream { case _BOUNDARY_END: _expectByteValue(byte, CharCode.LF); - _multipartController.close(); - _multipartController = null; + if (_multipartController != null) { + _multipartController.close(); + _multipartController = null; + } _state = _HEADER_START; break; @@ -345,8 +332,10 @@ class BoundMultipartStream { case _LAST_BOUNDARY_END: _expectByteValue(byte, CharCode.LF); - _multipartController.close(); - _multipartController = null; + if (_multipartController != null) { + _multipartController.close(); + _multipartController = null; + } _state = _DONE; break; diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 70515824d..7ca466958 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.0+3 +version: 0.9.1 author: Dart Team description: Helper-package for working with MIME. homepage: http://www.dartlang.org diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 7bc2d7d92..0008ff011 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -69,8 +69,12 @@ void _testParse(String message, } void _testParseValid() { + // Empty message from Chrome form post. + var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; + _testParse(message, "----WebKitFormBoundaryU3FBruSkJKG0Yor1", [], []); + // Sample from Wikipedia. - var message = """ + message = """ This is a message with multiple parts in MIME format.\r --frontier\r Content-Type: text/plain\r From 57180b6015ce30f731ca9b08bc84acde98df1b8f Mon Sep 17 00:00:00 2001 From: "kustermann@google.com" Date: Thu, 12 Feb 2015 13:51:18 +0000 Subject: [PATCH 019/118] Fix multipart transformer in package:mime The error codition occures in the following scenario: A multipart transformer returns a new multipart, that part is listened on, but the subscription for more parts is cancelled. This used to cause cancellation of the byte stream into the multipart parser, which caused the first part to never be read completely. R=lrn@google.com, sgjesse@google.com Review URL: https://codereview.chromium.org//874223002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@43726 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/CHANGELOG.md | 5 + pkgs/mime/lib/src/bound_multipart_stream.dart | 52 ++++++-- pkgs/mime/pubspec.yaml | 2 +- .../test/mime_multipart_transformer_test.dart | 116 ++++++++++++++++-- 4 files changed, 154 insertions(+), 21 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index eab1ae35f..8fa7caa8f 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.9.2 + +* Fixed erroneous behavior when pausing/canceling stream of parts but already + listened to one part. + # 0.9.1 * Handle parsing of MIME multipart content with no parts. diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index a049b1d11..7d16b9651 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -74,6 +74,16 @@ class BoundMultipartStream { final List _headerField = []; final List _headerValue = []; + // The following states belong to `_controller`, state changes will not be + // immediately acted upon but rather only after the current + // `_multipartController` is done. + static const int _CONTROLLER_STATE_IDLE = 0; + static const int _CONTROLLER_STATE_ACTIVE = 1; + static const int _CONTROLLER_STATE_PAUSED = 2; + static const int _CONTROLLER_STATE_CANCELED = 3; + + int _controllerState = _CONTROLLER_STATE_IDLE; + StreamController _controller; Stream get stream => _controller.stream; @@ -97,13 +107,15 @@ class BoundMultipartStream { onPause: _pauseStream, onResume:_resumeStream, onCancel: () { - _subscription.cancel(); + _controllerState = _CONTROLLER_STATE_CANCELED; + _tryPropagateControllerState(); }, onListen: () { + _controllerState = _CONTROLLER_STATE_ACTIVE; _subscription = stream.listen( (data) { assert(_buffer == null); - _pauseStream(); + _subscription.pause(); _buffer = data; _index = 0; _parse(); @@ -120,13 +132,33 @@ class BoundMultipartStream { } void _resumeStream() { - _subscription.resume(); + assert (_controllerState == _CONTROLLER_STATE_PAUSED); + _controllerState = _CONTROLLER_STATE_ACTIVE; + _tryPropagateControllerState(); } void _pauseStream() { - _subscription.pause(); + _controllerState = _CONTROLLER_STATE_PAUSED; + _tryPropagateControllerState(); } + void _tryPropagateControllerState() { + if (_multipartController == null) { + switch (_controllerState) { + case _CONTROLLER_STATE_ACTIVE: + if (_subscription.isPaused) _subscription.resume(); + break; + case _CONTROLLER_STATE_PAUSED: + if (!_subscription.isPaused) _subscription.pause(); + break; + case _CONTROLLER_STATE_CANCELED: + _subscription.cancel(); + break; + default: + throw new StateError("This code should never be reached."); + } + } + } void _parse() { // Number of boundary bytes to artificially place before the supplied data. @@ -210,6 +242,7 @@ class BoundMultipartStream { if (_multipartController != null) { _multipartController.close(); _multipartController = null; + _tryPropagateControllerState(); } _state = _HEADER_START; break; @@ -282,11 +315,9 @@ class BoundMultipartStream { _expectByteValue(byte, CharCode.LF); _multipartController = new StreamController( sync: true, - onPause: () { - _pauseStream(); - }, + onPause: _subscription.pause, onResume: () { - _resumeStream(); + _subscription.resume(); _parse(); }); _controller.add( @@ -306,6 +337,8 @@ class BoundMultipartStream { _index--; } _multipartController.close(); + _multipartController = null; + _tryPropagateControllerState(); _boundaryIndex = 0; _state = _BOUNDARY_ENDING; } @@ -335,6 +368,7 @@ class BoundMultipartStream { if (_multipartController != null) { _multipartController.close(); _multipartController = null; + _tryPropagateControllerState(); } _state = _DONE; break; @@ -358,7 +392,7 @@ class BoundMultipartStream { if (_index == _buffer.length) { _buffer = null; _index = null; - _resumeStream(); + _subscription.resume(); } } } diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 7ca466958..e29681c5c 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.1 +version: 0.9.2 author: Dart Team description: Helper-package for working with MIME. homepage: http://www.dartlang.org diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 0008ff011..86ab551e0 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -8,6 +8,22 @@ import 'dart:math'; import "package:unittest/unittest.dart"; import "package:mime/mime.dart"; +void _writeInChunks(List data, + int chunkSize, + StreamController> controller) { + if (chunkSize == -1) chunkSize = data.length; + + int written = 0; + for (int pos = 0; pos < data.length; pos += chunkSize) { + int remaining = data.length - pos; + int writeLength = min(chunkSize, remaining); + controller.add(data.sublist(pos, pos + writeLength)); + written += writeLength; + } + controller.close(); +} + + void _testParse(String message, String boundary, [List expectedHeaders, @@ -41,16 +57,71 @@ void _testParse(String message, Future.wait(futures).then(completer.complete); }); - if (chunkSize == -1) chunkSize = data.length; + _writeInChunks(data, chunkSize, controller); - int written = 0; - for (int pos = 0; pos < data.length; pos += chunkSize) { - int remaining = data.length - pos; - int writeLength = min(chunkSize, remaining); - controller.add(data.sublist(pos, pos + writeLength)); - written += writeLength; - } - controller.close(); + return completer.future; + } + + Future testFirstPartOnly(List data, [int chunkSize = -1]) { + var completer = new Completer(); + var controller = new StreamController(sync: true); + + var stream = controller.stream.transform( + new MimeMultipartTransformer(boundary)); + + var subscription; + subscription = stream.first.then((multipart) { + if (expectedHeaders != null) { + expect(multipart.headers, equals(expectedHeaders[0])); + } + return (multipart.fold([], (b, d) => b..addAll(d)).then((data) { + if (expectedParts != null && expectedParts[0] != null) { + expect(data, equals(expectedParts[0].codeUnits)); + } + })); + }).then((_) { + completer.complete(); + }); + + _writeInChunks(data, chunkSize, controller); + + return completer.future; + } + + Future testCompletePartAfterCancel(List data, + int parts, + [int chunkSize = -1]) { + var completer = new Completer(); + var controller = new StreamController(sync: true); + var stream = controller.stream.transform( + new MimeMultipartTransformer(boundary)); + var subscription; + int i = 0; + var futures = []; + subscription = stream.listen((multipart) { + int partIndex = i; + + if (partIndex >= parts) { + throw 'Expected no more parts, but got one.'; + } + + if (expectedHeaders != null) { + expect(multipart.headers, equals(expectedHeaders[partIndex])); + } + futures.add((multipart.fold([], (b, d) => b..addAll(d)).then((data) { + if (expectedParts != null && expectedParts[partIndex] != null) { + expect(data, equals(expectedParts[partIndex].codeUnits)); + } + }))); + + if (partIndex == (parts - 1)) { + subscription.cancel(); + Future.wait(futures).then(completer.complete); + } + i++; + }); + + _writeInChunks(data, chunkSize, controller); return completer.future; } @@ -63,9 +134,32 @@ void _testParse(String message, testWrite(data), testWrite(data, 10), testWrite(data, 2), - testWrite(data, 1)]), - completes); + testWrite(data, 1), + ]), completes); }); + + if (expectedParts.length > 0) { + test('test-first-part-only', () { + expect(Future.wait([ + testFirstPartOnly(data), + testFirstPartOnly(data, 10), + testFirstPartOnly(data, 2), + testFirstPartOnly(data, 1), + ]), completes); + }); + + test('test-n-parts-only', () { + int numPartsExpected = expectedParts.length - 1; + if (numPartsExpected == 0) numPartsExpected = 1; + + expect(Future.wait([ + testCompletePartAfterCancel(data, numPartsExpected), + testCompletePartAfterCancel(data, numPartsExpected, 10), + testCompletePartAfterCancel(data, numPartsExpected, 2), + testCompletePartAfterCancel(data, numPartsExpected, 1), + ]), completes); + }); + } } void _testParseValid() { From fb24c4c4d63c68765c660668377e5a5f74c9baf7 Mon Sep 17 00:00:00 2001 From: "sgjesse@google.com" Date: Wed, 18 Feb 2015 07:27:48 +0000 Subject: [PATCH 020/118] Fix bug in subscription handling in mime package The parser now parses each received chunk to the end no matter what the paused state of the part stream is. This will add data to the part stream controller before it is even listened on, but only the data already received from the original input stream. Not trying to stop the parsing on a received chunk when the part stream is paused makes the code simpler to reason about. The two added tests modes failed without this change. Either by hanging or by hitting an exception trying to invoke the getter 'length' on null. R=kustermann@google.com BUG= Review URL: https://codereview.chromium.org//934763004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@43835 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/lib/src/bound_multipart_stream.dart | 13 ++-- pkgs/mime/pubspec.yaml | 2 +- .../test/mime_multipart_transformer_test.dart | 77 ++++++++++++++++--- 3 files changed, 73 insertions(+), 19 deletions(-) diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index 7d16b9651..ab06dabeb 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -105,7 +105,7 @@ class BoundMultipartStream { _controller = new StreamController( sync: true, onPause: _pauseStream, - onResume:_resumeStream, + onResume: _resumeStream, onCancel: () { _controllerState = _CONTROLLER_STATE_CANCELED; _tryPropagateControllerState(); @@ -203,9 +203,6 @@ class BoundMultipartStream { boundaryPrefix = _boundaryIndex; while ((_index < _buffer.length) && _state != _FAIL && _state != _DONE) { - if (_multipartController != null && _multipartController.isPaused) { - return; - } int byte; if (_index < 0) { byte = _boundary[boundaryPrefix + _index]; @@ -315,11 +312,11 @@ class BoundMultipartStream { _expectByteValue(byte, CharCode.LF); _multipartController = new StreamController( sync: true, + onListen: () { + if (_subscription.isPaused) _subscription.resume(); + }, onPause: _subscription.pause, - onResume: () { - _subscription.resume(); - _parse(); - }); + onResume: _subscription.resume); _controller.add( new _MimeMultipart(_headers, _multipartController.stream)); _headers = null; diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index e29681c5c..2de7eca53 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.2 +version: 0.9.3 author: Dart Team description: Helper-package for working with MIME. homepage: http://www.dartlang.org diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 86ab551e0..50389998f 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -24,11 +24,18 @@ void _writeInChunks(List data, } -void _testParse(String message, - String boundary, - [List expectedHeaders, - List expectedParts, - bool expectError = false]) { +enum TestMode { + IMMEDIATE_LISTEN, + DELAY_LISTEN, + PAUSE_RESUME +} + +void _runParseTest(String message, + String boundary, + TestMode mode, + [List expectedHeaders, + List expectedParts, + bool expectError = false]) { Future testWrite(List data, [int chunkSize = -1]) { StreamController controller = new StreamController(sync: true); @@ -42,12 +49,46 @@ void _testParse(String message, if (expectedHeaders != null) { expect(multipart.headers, equals(expectedHeaders[part])); } - futures.add(multipart.fold([], (buffer, data) => buffer..addAll(data)) - .then((data) { - if (expectedParts[part] != null) { - expect(data, equals(expectedParts[part].codeUnits)); - } + switch (mode) { + case TestMode.IMMEDIATE_LISTEN: + futures.add(multipart.fold([], (buffer, data) => buffer..addAll(data)) + .then((data) { + if (expectedParts[part] != null) { + expect(data, equals(expectedParts[part].codeUnits)); + } + })); + break; + + case TestMode.DELAY_LISTEN: + futures.add(new Future(() { + return multipart.fold([], (buffer, data) => buffer..addAll(data)) + .then((data) { + if (expectedParts[part] != null) { + expect(data, equals(expectedParts[part].codeUnits)); + } + }); })); + break; + + case TestMode.PAUSE_RESUME: + var completer = new Completer(); + futures.add(completer.future); + var buffer = []; + var subscription; + subscription = multipart.listen( + (data) { + buffer.addAll(data); + subscription.pause(); + new Future(() => subscription.resume()); + }, + onDone: () { + if (expectedParts[part] != null) { + expect(buffer, equals(expectedParts[part].codeUnits)); + } + completer.complete(); + }); + break; + } }, onError: (error) { if (!expectError) throw error; }, onDone: () { @@ -162,6 +203,22 @@ void _testParse(String message, } } +void _testParse(String message, + String boundary, + [List expectedHeaders, + List expectedParts, + bool expectError = false]) { + _runParseTest( + message, boundary, TestMode.IMMEDIATE_LISTEN, + expectedHeaders, expectedParts, expectError); + _runParseTest( + message, boundary, TestMode.DELAY_LISTEN, + expectedHeaders, expectedParts, expectError); + _runParseTest( + message, boundary, TestMode.PAUSE_RESUME, + expectedHeaders, expectedParts, expectError); +} + void _testParseValid() { // Empty message from Chrome form post. var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; From 3e92b980ca42dc6ac93a2ac7a5d8b00b0817fab5 Mon Sep 17 00:00:00 2001 From: "sgjesse@google.com" Date: Wed, 18 Feb 2015 14:45:30 +0000 Subject: [PATCH 021/118] Add README file to the mime package Also update CHANGELOG after last change. R=kustermann@google.com, wibling@google.com BUG=http://dartbug.com/22442 Review URL: https://codereview.chromium.org//936733004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/mime@43841 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/mime/CHANGELOG.md | 5 +++++ pkgs/mime/README.md | 48 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 pkgs/mime/README.md diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 8fa7caa8f..98abd3a15 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.9.3 + +* Fixed erroneous behavior for listening and when pausing/resuming + stream of parts. + # 0.9.2 * Fixed erroneous behavior when pausing/canceling stream of parts but already diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md new file mode 100644 index 000000000..dd69358b0 --- /dev/null +++ b/pkgs/mime/README.md @@ -0,0 +1,48 @@ +#MIME type package + +Package for working with MIME type definitions and for processing +streams of MIME multipart media types. + +##Determining the MIME type for a file + +The `MimeTypeResolver` class can be used to determine the MIME type of +a file. It supports both using the extension of the file name and +looking at magic bytes from the begining of the file. + +There is a builtin instance of `MimeTypeResolver` accessible through +the top level function `lookupMimeType`. This builtin instance has +the most common file name extensions and magic bytes registered. + + print(lookupMimeType('test.html')); // Will print text/html + print(lookupMimeType('test', [0xFF, 0xD8])); // Will print image/jpeg + print(lookupMimeType('test.html', [0xFF, 0xD8])); // Will print image/jpeg + +You can build you own resolver by creating an instance of +`MimeTypeResolver` and adding file name extensions and magic bytes +using `addExtension` and `addMagicNumber`. + +##Processing MIME multipart media types + +The class `MimeMultipartTransformer` is used to process a `Stream` of +bytes encoded using a MIME multipart media types encoding. The +transformer provides a new `Stream` of `MimeMultipart` objects each of +which have the headers and the content of each part. The content of a +part is provided as a stream of bytes. + +Below is an example showing how to process an HTTP request and print +the length of the content of each part. + + // HTTP request with content type multipart/form-data. + HttpRequest request = ...; + // Determine the boundary form the content type header + String boundary = request.headers.contentType.parameters['boundary']; + + // Process the body just calculating the length of each part. + request.transform(new MimeMultipartTransformer(boundary)) + .map((part) => part.fold(0, (p, d) => p + d)) + .listen((length) => print('Part with length $length')); + +Take a look at the `HttpBodyHandler` in the [http_server][1] package for +handling different content types in a HTTP request. + +[1]: https://pub.dartlang.org/packages/http_server From 361f26495c9c7ba6f60853c266cdd9240ed8a483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Gjesse?= Date: Tue, 24 Feb 2015 10:06:36 +0100 Subject: [PATCH 022/118] Update project to match OSS template R=ricow@google.com BUG= Review URL: https://codereview.chromium.org//955593002 --- pkgs/mime/AUTHORS | 6 ++++++ pkgs/mime/CONTRIBUTING.md | 33 +++++++++++++++++++++++++++++++++ pkgs/mime/LICENSE | 2 +- pkgs/mime/README.md | 11 ++++++++--- pkgs/mime/codereview.settings | 3 +++ pkgs/mime/pubspec.yaml | 2 +- 6 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 pkgs/mime/AUTHORS create mode 100644 pkgs/mime/CONTRIBUTING.md create mode 100644 pkgs/mime/codereview.settings diff --git a/pkgs/mime/AUTHORS b/pkgs/mime/AUTHORS new file mode 100644 index 000000000..e8063a8cd --- /dev/null +++ b/pkgs/mime/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. diff --git a/pkgs/mime/CONTRIBUTING.md b/pkgs/mime/CONTRIBUTING.md new file mode 100644 index 000000000..6f5e0ea67 --- /dev/null +++ b/pkgs/mime/CONTRIBUTING.md @@ -0,0 +1,33 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. + +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. + +### File headers +All files in the project must start with the following header. + + // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file + // for details. All rights reserved. Use of this source code is governed by a + // BSD-style license that can be found in the LICENSE file. + +### The small print +Contributions made by corporations are covered by a different agreement than the +one above, the +[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/mime/LICENSE b/pkgs/mime/LICENSE index 5c60afea3..de31e1a0a 100644 --- a/pkgs/mime/LICENSE +++ b/pkgs/mime/LICENSE @@ -1,4 +1,4 @@ -Copyright 2014, the Dart project authors. All rights reserved. +Copyright 2015, the Dart project authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index dd69358b0..d5bf11a4d 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -42,7 +42,12 @@ the length of the content of each part. .map((part) => part.fold(0, (p, d) => p + d)) .listen((length) => print('Part with length $length')); -Take a look at the `HttpBodyHandler` in the [http_server][1] package for -handling different content types in a HTTP request. +Take a look at the `HttpBodyHandler` in the [http_server][http_server] +package for handling different content types in a HTTP request. -[1]: https://pub.dartlang.org/packages/http_server +## Features and bugs + +Please file feature requests and bugs at the [issue tracker][tracker]. + +[tracker]: https://github.com/dart-lang/sample/issues +[http_server]: https://pub.dartlang.org/packages/http_server diff --git a/pkgs/mime/codereview.settings b/pkgs/mime/codereview.settings new file mode 100644 index 000000000..85f2bb59e --- /dev/null +++ b/pkgs/mime/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: http://codereview.chromium.org/ +VIEW_VC: https://github.com/dart-lang/mime/commit/ +CC_LIST: reviews@dartlang.org diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 2de7eca53..ee168a3dc 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -2,7 +2,7 @@ name: mime version: 0.9.3 author: Dart Team description: Helper-package for working with MIME. -homepage: http://www.dartlang.org +homepage: https://www.github.com/dart-lang/mime environment: sdk: '>=1.0.0 <2.0.0' dev_dependencies: From 017f46de62f7eccfdebd53d726196a1e2693b428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Gjesse?= Date: Tue, 24 Feb 2015 11:57:01 +0100 Subject: [PATCH 023/118] Add .gitignore and empty .status R=ricow@google.com Review URL: https://codereview.chromium.org//951213003 --- pkgs/mime/.gitignore | 8 ++++++++ pkgs/mime/.status | 4 ++++ 2 files changed, 12 insertions(+) create mode 100644 pkgs/mime/.gitignore create mode 100644 pkgs/mime/.status diff --git a/pkgs/mime/.gitignore b/pkgs/mime/.gitignore new file mode 100644 index 000000000..89f7747cd --- /dev/null +++ b/pkgs/mime/.gitignore @@ -0,0 +1,8 @@ +.buildlog +.DS_Store +.idea +.pub/ +.settings/ +build/ +packages +pubspec.lock diff --git a/pkgs/mime/.status b/pkgs/mime/.status new file mode 100644 index 000000000..364ca4b46 --- /dev/null +++ b/pkgs/mime/.status @@ -0,0 +1,4 @@ +# Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +# for details. All rights reserved. Use of this source code is governed by a +# BSD-style license that can be found in the LICENSE file. + From 1be80dac3a8217eeacefd0c4c0e396ca49326dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Gjesse?= Date: Tue, 24 Feb 2015 15:27:37 +0100 Subject: [PATCH 024/118] Update .status for mime package R=ricow@google.com BUG= Review URL: https://codereview.chromium.org//952893002 --- pkgs/mime/.status | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkgs/mime/.status b/pkgs/mime/.status index 364ca4b46..ebc5f8132 100644 --- a/pkgs/mime/.status +++ b/pkgs/mime/.status @@ -2,3 +2,11 @@ # for details. All rights reserved. Use of this source code is governed by a # BSD-style license that can be found in the LICENSE file. +# Skip non-test files ending with "_test". +packages/*: Skip +*/packages/*: Skip +*/*/packages/*: Skip +*/*/*/packages/*: Skip +*/*/*/*packages/*: Skip +*/*/*/*/*packages/*: Skip + From 20ebc850350f20ea0e60ae718c32578d758b5fbd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Aug 2015 08:07:44 -0700 Subject: [PATCH 025/118] ignore .packages file ...and clean up other .gitignore entries R=sgjesse@google.com Review URL: https://codereview.chromium.org//1306733004 . --- pkgs/mime/.gitignore | 6 +----- pkgs/mime/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pkgs/mime/.gitignore b/pkgs/mime/.gitignore index 89f7747cd..4232a2f22 100644 --- a/pkgs/mime/.gitignore +++ b/pkgs/mime/.gitignore @@ -1,8 +1,4 @@ -.buildlog -.DS_Store -.idea +.packages .pub/ -.settings/ -build/ packages pubspec.lock diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index ee168a3dc..892fbb0e5 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.3 +version: 0.9.4-dev author: Dart Team description: Helper-package for working with MIME. homepage: https://www.github.com/dart-lang/mime From c664d4b34f6c79d7921a1693b13ddabcae50528a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Aug 2015 08:08:21 -0700 Subject: [PATCH 026/118] Use pkg/test R=sgjesse@google.com Review URL: https://codereview.chromium.org//1317773003 . --- pkgs/mime/CHANGELOG.md | 4 ++++ pkgs/mime/pubspec.yaml | 4 ++-- pkgs/mime/test/mime_multipart_transformer_test.dart | 2 +- pkgs/mime/test/mime_type_test.dart | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 98abd3a15..a76441f07 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.4 + +* Updated Dart SDK requirement to `>= 1.8.3 <2.0.0` + # 0.9.3 * Fixed erroneous behavior for listening and when pausing/resuming diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 892fbb0e5..e90b74c52 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -4,6 +4,6 @@ author: Dart Team description: Helper-package for working with MIME. homepage: https://www.github.com/dart-lang/mime environment: - sdk: '>=1.0.0 <2.0.0' + sdk: '>=1.8.3 <2.0.0' dev_dependencies: - unittest: '>=0.9.0 <0.12.0' + test: '^0.12.0' diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 50389998f..95e90bc07 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -5,7 +5,7 @@ import 'dart:async'; import 'dart:math'; -import "package:unittest/unittest.dart"; +import "package:test/test.dart"; import "package:mime/mime.dart"; void _writeInChunks(List data, diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 23cc10e3c..c7843433d 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -4,7 +4,7 @@ import 'dart:math' as math; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'package:mime/mime.dart'; import 'package:mime/src/magic_number.dart'; From bf90449af761fb306110fc5eef65f00139f8921f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Aug 2015 08:09:55 -0700 Subject: [PATCH 027/118] dartfmt most of the code Except for a few array/map literals R=sgjesse@google.com Review URL: https://codereview.chromium.org//1315033002 . --- pkgs/mime/lib/src/bound_multipart_stream.dart | 680 +++++++++--------- pkgs/mime/lib/src/magic_number.dart | 5 +- .../lib/src/mime_multipart_transformer.dart | 2 - pkgs/mime/lib/src/mime_type.dart | 15 +- .../test/mime_multipart_transformer_test.dart | 185 +++-- pkgs/mime/test/mime_type_test.dart | 29 +- 6 files changed, 441 insertions(+), 475 deletions(-) diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index ab06dabeb..270503a73 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -19,8 +19,9 @@ bool _isTokenChar(int byte) { int _toLowerCase(int byte) { const delta = CharCode.LOWER_A - CharCode.UPPER_A; - return (CharCode.UPPER_A <= byte && byte <= CharCode.UPPER_Z) ? - byte + delta : byte; + return (CharCode.UPPER_A <= byte && byte <= CharCode.UPPER_Z) + ? byte + delta + : byte; } void _expectByteValue(int val1, int val2) { @@ -42,354 +43,339 @@ class _MimeMultipart extends MimeMultipart { _MimeMultipart(this.headers, this._stream); StreamSubscription> listen(void onData(List data), - {void onDone(), - Function onError, - bool cancelOnError}) { + {void onDone(), Function onError, bool cancelOnError}) { return _stream.listen(onData, - onDone: onDone, - onError: onError, - cancelOnError: cancelOnError); + onDone: onDone, onError: onError, cancelOnError: cancelOnError); } } class BoundMultipartStream { - static const int _START = 0; - static const int _BOUNDARY_ENDING = 1; - static const int _BOUNDARY_END = 2; - static const int _HEADER_START = 3; - static const int _HEADER_FIELD = 4; - static const int _HEADER_VALUE_START = 5; - static const int _HEADER_VALUE = 6; - static const int _HEADER_VALUE_FOLDING_OR_ENDING = 7; - static const int _HEADER_VALUE_FOLD_OR_END = 8; - static const int _HEADER_ENDING = 9; - static const int _CONTENT = 10; - static const int _LAST_BOUNDARY_DASH2 = 11; - static const int _LAST_BOUNDARY_ENDING = 12; - static const int _LAST_BOUNDARY_END = 13; - static const int _DONE = 14; - static const int _FAIL = 15; - - final List _boundary; - final List _headerField = []; - final List _headerValue = []; - - // The following states belong to `_controller`, state changes will not be - // immediately acted upon but rather only after the current - // `_multipartController` is done. - static const int _CONTROLLER_STATE_IDLE = 0; - static const int _CONTROLLER_STATE_ACTIVE = 1; - static const int _CONTROLLER_STATE_PAUSED = 2; - static const int _CONTROLLER_STATE_CANCELED = 3; - - int _controllerState = _CONTROLLER_STATE_IDLE; - - StreamController _controller; - - Stream get stream => _controller.stream; - - StreamSubscription _subscription; - - StreamController _multipartController; - Map _headers; - - int _state = _START; - int _boundaryIndex = 2; - - // Current index in the data buffer. If index is negative then it - // is the index into the artificial prefix of the boundary string. - int _index; - List _buffer; - - BoundMultipartStream(this._boundary, Stream> stream) { - _controller = new StreamController( - sync: true, - onPause: _pauseStream, - onResume: _resumeStream, - onCancel: () { - _controllerState = _CONTROLLER_STATE_CANCELED; - _tryPropagateControllerState(); - }, - onListen: () { - _controllerState = _CONTROLLER_STATE_ACTIVE; - _subscription = stream.listen( - (data) { - assert(_buffer == null); - _subscription.pause(); - _buffer = data; - _index = 0; - _parse(); - }, - onDone: () { - if (_state != _DONE) { - _controller.addError( - new MimeMultipartException("Bad multipart ending")); - } - _controller.close(); - }, - onError: _controller.addError); - }); - } - - void _resumeStream() { - assert (_controllerState == _CONTROLLER_STATE_PAUSED); - _controllerState = _CONTROLLER_STATE_ACTIVE; - _tryPropagateControllerState(); - } - - void _pauseStream() { - _controllerState = _CONTROLLER_STATE_PAUSED; - _tryPropagateControllerState(); - } - - void _tryPropagateControllerState() { - if (_multipartController == null) { - switch (_controllerState) { - case _CONTROLLER_STATE_ACTIVE: - if (_subscription.isPaused) _subscription.resume(); - break; - case _CONTROLLER_STATE_PAUSED: - if (!_subscription.isPaused) _subscription.pause(); - break; - case _CONTROLLER_STATE_CANCELED: - _subscription.cancel(); - break; - default: - throw new StateError("This code should never be reached."); - } - } - } - - void _parse() { - // Number of boundary bytes to artificially place before the supplied data. - int boundaryPrefix = 0; - // Position where content starts. Will be null if no known content - // start exists. Will be negative of the content starts in the - // boundary prefix. Will be zero or position if the content starts - // in the current buffer. - int contentStartIndex; - - // Function to report content data for the current part. The data - // reported is from the current content start index up til the - // current index. As the data can be artificially prefixed with a - // prefix of the boundary both the content start index and index - // can be negative. - void reportData() { - if (contentStartIndex < 0) { - var contentLength = boundaryPrefix + _index - _boundaryIndex; - if (contentLength <= boundaryPrefix) { - _multipartController.add( - _boundary.sublist(0, contentLength)); - } else { - _multipartController.add( - _boundary.sublist(0, boundaryPrefix)); - _multipartController.add( - _buffer.sublist(0, contentLength - boundaryPrefix)); - } - } else { - var contentEndIndex = _index - _boundaryIndex; - _multipartController.add( - _buffer.sublist(contentStartIndex, contentEndIndex)); - } - } - - if (_state == _CONTENT && _boundaryIndex == 0) { - contentStartIndex = 0; - } else { - contentStartIndex = null; - } - // The data to parse might be "artificially" prefixed with a - // partial match of the boundary. - boundaryPrefix = _boundaryIndex; - - while ((_index < _buffer.length) && _state != _FAIL && _state != _DONE) { - int byte; - if (_index < 0) { - byte = _boundary[boundaryPrefix + _index]; - } else { - byte = _buffer[_index]; - } - switch (_state) { - case _START: - if (byte == _boundary[_boundaryIndex]) { - _boundaryIndex++; - if (_boundaryIndex == _boundary.length) { - _state = _BOUNDARY_ENDING; - _boundaryIndex = 0; - } - } else { - // Restart matching of the boundary. - _index = _index - _boundaryIndex; - _boundaryIndex = 0; - } - break; - - case _BOUNDARY_ENDING: - if (byte == CharCode.CR) { - _state = _BOUNDARY_END; - } else if (byte == CharCode.DASH) { - _state = _LAST_BOUNDARY_DASH2; - } else { - _expectWhitespace(byte); - } - break; - - case _BOUNDARY_END: - _expectByteValue(byte, CharCode.LF); - if (_multipartController != null) { - _multipartController.close(); - _multipartController = null; - _tryPropagateControllerState(); - } - _state = _HEADER_START; - break; - - case _HEADER_START: - _headers = new Map(); - if (byte == CharCode.CR) { - _state = _HEADER_ENDING; - } else { - // Start of new header field. - _headerField.add(_toLowerCase(byte)); - _state = _HEADER_FIELD; - } - break; - - case _HEADER_FIELD: - if (byte == CharCode.COLON) { - _state = _HEADER_VALUE_START; - } else { - if (!_isTokenChar(byte)) { - throw new MimeMultipartException("Invalid header field name"); - } - _headerField.add(_toLowerCase(byte)); - } - break; - - case _HEADER_VALUE_START: - if (byte == CharCode.CR) { - _state = _HEADER_VALUE_FOLDING_OR_ENDING; - } else if (byte != CharCode.SP && byte != CharCode.HT) { - // Start of new header value. - _headerValue.add(byte); - _state = _HEADER_VALUE; - } - break; - - case _HEADER_VALUE: - if (byte == CharCode.CR) { - _state = _HEADER_VALUE_FOLDING_OR_ENDING; - } else { - _headerValue.add(byte); - } - break; - - case _HEADER_VALUE_FOLDING_OR_ENDING: - _expectByteValue(byte, CharCode.LF); - _state = _HEADER_VALUE_FOLD_OR_END; - break; - - case _HEADER_VALUE_FOLD_OR_END: - if (byte == CharCode.SP || byte == CharCode.HT) { - _state = _HEADER_VALUE_START; - } else { - String headerField = UTF8.decode(_headerField); - String headerValue = UTF8.decode(_headerValue); - _headers[headerField.toLowerCase()] = headerValue; - _headerField.clear(); - _headerValue.clear(); - if (byte == CharCode.CR) { - _state = _HEADER_ENDING; - } else { - // Start of new header field. - _headerField.add(_toLowerCase(byte)); - _state = _HEADER_FIELD; - } - } - break; - - case _HEADER_ENDING: - _expectByteValue(byte, CharCode.LF); - _multipartController = new StreamController( - sync: true, - onListen: () { - if (_subscription.isPaused) _subscription.resume(); - }, - onPause: _subscription.pause, - onResume: _subscription.resume); - _controller.add( - new _MimeMultipart(_headers, _multipartController.stream)); - _headers = null; - _state = _CONTENT; - contentStartIndex = _index + 1; - break; - - case _CONTENT: - if (byte == _boundary[_boundaryIndex]) { - _boundaryIndex++; - if (_boundaryIndex == _boundary.length) { - if (contentStartIndex != null) { - _index++; - reportData(); - _index--; - } - _multipartController.close(); - _multipartController = null; - _tryPropagateControllerState(); - _boundaryIndex = 0; - _state = _BOUNDARY_ENDING; - } - } else { - // Restart matching of the boundary. - _index = _index - _boundaryIndex; - if (contentStartIndex == null) contentStartIndex = _index; - _boundaryIndex = 0; - } - break; - - case _LAST_BOUNDARY_DASH2: - _expectByteValue(byte, CharCode.DASH); - _state = _LAST_BOUNDARY_ENDING; - break; - - case _LAST_BOUNDARY_ENDING: - if (byte == CharCode.CR) { - _state = _LAST_BOUNDARY_END; - } else { - _expectWhitespace(byte); - } - break; - - case _LAST_BOUNDARY_END: - _expectByteValue(byte, CharCode.LF); - if (_multipartController != null) { - _multipartController.close(); - _multipartController = null; - _tryPropagateControllerState(); - } - _state = _DONE; - break; - - default: - // Should be unreachable. - assert(false); - break; - } - - // Move to the next byte. - _index++; - } - - // Report any known content. - if (_state == _CONTENT && contentStartIndex != null) { - reportData(); - } - - // Resume if at end. - if (_index == _buffer.length) { - _buffer = null; - _index = null; - _subscription.resume(); - } - } + static const int _START = 0; + static const int _BOUNDARY_ENDING = 1; + static const int _BOUNDARY_END = 2; + static const int _HEADER_START = 3; + static const int _HEADER_FIELD = 4; + static const int _HEADER_VALUE_START = 5; + static const int _HEADER_VALUE = 6; + static const int _HEADER_VALUE_FOLDING_OR_ENDING = 7; + static const int _HEADER_VALUE_FOLD_OR_END = 8; + static const int _HEADER_ENDING = 9; + static const int _CONTENT = 10; + static const int _LAST_BOUNDARY_DASH2 = 11; + static const int _LAST_BOUNDARY_ENDING = 12; + static const int _LAST_BOUNDARY_END = 13; + static const int _DONE = 14; + static const int _FAIL = 15; + + final List _boundary; + final List _headerField = []; + final List _headerValue = []; + + // The following states belong to `_controller`, state changes will not be + // immediately acted upon but rather only after the current + // `_multipartController` is done. + static const int _CONTROLLER_STATE_IDLE = 0; + static const int _CONTROLLER_STATE_ACTIVE = 1; + static const int _CONTROLLER_STATE_PAUSED = 2; + static const int _CONTROLLER_STATE_CANCELED = 3; + + int _controllerState = _CONTROLLER_STATE_IDLE; + + StreamController _controller; + + Stream get stream => _controller.stream; + + StreamSubscription _subscription; + + StreamController _multipartController; + Map _headers; + + int _state = _START; + int _boundaryIndex = 2; + + // Current index in the data buffer. If index is negative then it + // is the index into the artificial prefix of the boundary string. + int _index; + List _buffer; + + BoundMultipartStream(this._boundary, Stream> stream) { + _controller = new StreamController( + sync: true, + onPause: _pauseStream, + onResume: _resumeStream, onCancel: () { + _controllerState = _CONTROLLER_STATE_CANCELED; + _tryPropagateControllerState(); + }, onListen: () { + _controllerState = _CONTROLLER_STATE_ACTIVE; + _subscription = stream.listen((data) { + assert(_buffer == null); + _subscription.pause(); + _buffer = data; + _index = 0; + _parse(); + }, onDone: () { + if (_state != _DONE) { + _controller + .addError(new MimeMultipartException("Bad multipart ending")); + } + _controller.close(); + }, onError: _controller.addError); + }); + } + + void _resumeStream() { + assert(_controllerState == _CONTROLLER_STATE_PAUSED); + _controllerState = _CONTROLLER_STATE_ACTIVE; + _tryPropagateControllerState(); + } + + void _pauseStream() { + _controllerState = _CONTROLLER_STATE_PAUSED; + _tryPropagateControllerState(); + } + + void _tryPropagateControllerState() { + if (_multipartController == null) { + switch (_controllerState) { + case _CONTROLLER_STATE_ACTIVE: + if (_subscription.isPaused) _subscription.resume(); + break; + case _CONTROLLER_STATE_PAUSED: + if (!_subscription.isPaused) _subscription.pause(); + break; + case _CONTROLLER_STATE_CANCELED: + _subscription.cancel(); + break; + default: + throw new StateError("This code should never be reached."); + } + } + } + + void _parse() { + // Number of boundary bytes to artificially place before the supplied data. + int boundaryPrefix = 0; + // Position where content starts. Will be null if no known content + // start exists. Will be negative of the content starts in the + // boundary prefix. Will be zero or position if the content starts + // in the current buffer. + int contentStartIndex; + + // Function to report content data for the current part. The data + // reported is from the current content start index up til the + // current index. As the data can be artificially prefixed with a + // prefix of the boundary both the content start index and index + // can be negative. + void reportData() { + if (contentStartIndex < 0) { + var contentLength = boundaryPrefix + _index - _boundaryIndex; + if (contentLength <= boundaryPrefix) { + _multipartController.add(_boundary.sublist(0, contentLength)); + } else { + _multipartController.add(_boundary.sublist(0, boundaryPrefix)); + _multipartController + .add(_buffer.sublist(0, contentLength - boundaryPrefix)); + } + } else { + var contentEndIndex = _index - _boundaryIndex; + _multipartController + .add(_buffer.sublist(contentStartIndex, contentEndIndex)); + } + } + + if (_state == _CONTENT && _boundaryIndex == 0) { + contentStartIndex = 0; + } else { + contentStartIndex = null; + } + // The data to parse might be "artificially" prefixed with a + // partial match of the boundary. + boundaryPrefix = _boundaryIndex; + + while ((_index < _buffer.length) && _state != _FAIL && _state != _DONE) { + int byte; + if (_index < 0) { + byte = _boundary[boundaryPrefix + _index]; + } else { + byte = _buffer[_index]; + } + switch (_state) { + case _START: + if (byte == _boundary[_boundaryIndex]) { + _boundaryIndex++; + if (_boundaryIndex == _boundary.length) { + _state = _BOUNDARY_ENDING; + _boundaryIndex = 0; + } + } else { + // Restart matching of the boundary. + _index = _index - _boundaryIndex; + _boundaryIndex = 0; + } + break; + + case _BOUNDARY_ENDING: + if (byte == CharCode.CR) { + _state = _BOUNDARY_END; + } else if (byte == CharCode.DASH) { + _state = _LAST_BOUNDARY_DASH2; + } else { + _expectWhitespace(byte); + } + break; + + case _BOUNDARY_END: + _expectByteValue(byte, CharCode.LF); + if (_multipartController != null) { + _multipartController.close(); + _multipartController = null; + _tryPropagateControllerState(); + } + _state = _HEADER_START; + break; + + case _HEADER_START: + _headers = new Map(); + if (byte == CharCode.CR) { + _state = _HEADER_ENDING; + } else { + // Start of new header field. + _headerField.add(_toLowerCase(byte)); + _state = _HEADER_FIELD; + } + break; + + case _HEADER_FIELD: + if (byte == CharCode.COLON) { + _state = _HEADER_VALUE_START; + } else { + if (!_isTokenChar(byte)) { + throw new MimeMultipartException("Invalid header field name"); + } + _headerField.add(_toLowerCase(byte)); + } + break; + + case _HEADER_VALUE_START: + if (byte == CharCode.CR) { + _state = _HEADER_VALUE_FOLDING_OR_ENDING; + } else if (byte != CharCode.SP && byte != CharCode.HT) { + // Start of new header value. + _headerValue.add(byte); + _state = _HEADER_VALUE; + } + break; + + case _HEADER_VALUE: + if (byte == CharCode.CR) { + _state = _HEADER_VALUE_FOLDING_OR_ENDING; + } else { + _headerValue.add(byte); + } + break; + + case _HEADER_VALUE_FOLDING_OR_ENDING: + _expectByteValue(byte, CharCode.LF); + _state = _HEADER_VALUE_FOLD_OR_END; + break; + + case _HEADER_VALUE_FOLD_OR_END: + if (byte == CharCode.SP || byte == CharCode.HT) { + _state = _HEADER_VALUE_START; + } else { + String headerField = UTF8.decode(_headerField); + String headerValue = UTF8.decode(_headerValue); + _headers[headerField.toLowerCase()] = headerValue; + _headerField.clear(); + _headerValue.clear(); + if (byte == CharCode.CR) { + _state = _HEADER_ENDING; + } else { + // Start of new header field. + _headerField.add(_toLowerCase(byte)); + _state = _HEADER_FIELD; + } + } + break; + + case _HEADER_ENDING: + _expectByteValue(byte, CharCode.LF); + _multipartController = new StreamController(sync: true, onListen: () { + if (_subscription.isPaused) _subscription.resume(); + }, onPause: _subscription.pause, onResume: _subscription.resume); + _controller + .add(new _MimeMultipart(_headers, _multipartController.stream)); + _headers = null; + _state = _CONTENT; + contentStartIndex = _index + 1; + break; + + case _CONTENT: + if (byte == _boundary[_boundaryIndex]) { + _boundaryIndex++; + if (_boundaryIndex == _boundary.length) { + if (contentStartIndex != null) { + _index++; + reportData(); + _index--; + } + _multipartController.close(); + _multipartController = null; + _tryPropagateControllerState(); + _boundaryIndex = 0; + _state = _BOUNDARY_ENDING; + } + } else { + // Restart matching of the boundary. + _index = _index - _boundaryIndex; + if (contentStartIndex == null) contentStartIndex = _index; + _boundaryIndex = 0; + } + break; + + case _LAST_BOUNDARY_DASH2: + _expectByteValue(byte, CharCode.DASH); + _state = _LAST_BOUNDARY_ENDING; + break; + + case _LAST_BOUNDARY_ENDING: + if (byte == CharCode.CR) { + _state = _LAST_BOUNDARY_END; + } else { + _expectWhitespace(byte); + } + break; + + case _LAST_BOUNDARY_END: + _expectByteValue(byte, CharCode.LF); + if (_multipartController != null) { + _multipartController.close(); + _multipartController = null; + _tryPropagateControllerState(); + } + _state = _DONE; + break; + + default: + // Should be unreachable. + assert(false); + break; + } + + // Move to the next byte. + _index++; + } + + // Report any known content. + if (_state == _CONTENT && contentStartIndex != null) { + reportData(); + } + + // Resume if at end. + if (_index == _buffer.length) { + _buffer = null; + _index = null; + _subscription.resume(); + } + } } diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 3efb2ee73..bc939f66c 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -24,7 +24,6 @@ class MagicNumber { return true; } - } const int DEFAULT_MAGIC_NUMBERS_MAX_LENGTH = 12; @@ -35,8 +34,8 @@ const List DEFAULT_MAGIC_NUMBERS = const [ const MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), const MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), const MagicNumber('image/jpeg', const [0xFF, 0xD8]), - const MagicNumber('image/png', - const [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), + const MagicNumber( + 'image/png', const [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), const MagicNumber('image/tiff', const [0x49, 0x49, 0x2A, 0x00]), const MagicNumber('image/tiff', const [0x4D, 0x4D, 0x00, 0x2A]), const MagicNumber( diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart index 3afff2dc3..781040eeb 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -10,7 +10,6 @@ import 'bound_multipart_stream.dart'; import 'mime_shared.dart'; import 'char_code.dart'; - Uint8List _getBoundary(String boundary) { var charCodes = boundary.codeUnits; @@ -32,7 +31,6 @@ Uint8List _getBoundary(String boundary) { */ class MimeMultipartTransformer implements StreamTransformer, MimeMultipart> { - final List _boundary; /** diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index 744eead87..b1fa8daa0 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -41,14 +41,16 @@ class MimeTypeResolver { /** * Create a new empty [MimeTypeResolver]. */ - MimeTypeResolver.empty() : _useDefault = false, _magicNumbersMaxLength = 0; + MimeTypeResolver.empty() + : _useDefault = false, + _magicNumbersMaxLength = 0; /** * Create a new [MimeTypeResolver] containing the default scope. */ - MimeTypeResolver() : - _useDefault = true, - _magicNumbersMaxLength = DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; + MimeTypeResolver() + : _useDefault = true, + _magicNumbersMaxLength = DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; /** * Get the maximum number of bytes required to match all magic numbers, when @@ -111,8 +113,8 @@ class MimeTypeResolver { _magicNumbers.add(new MagicNumber(mimeType, bytes, mask: mask)); } - static String _matchMagic(List headerBytes, - List magicNumbers) { + static String _matchMagic( + List headerBytes, List magicNumbers) { for (var mn in magicNumbers) { if (mn.matches(headerBytes)) return mn.mimeType; } @@ -125,4 +127,3 @@ class MimeTypeResolver { return path.substring(index + 1).toLowerCase(); } } - diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 95e90bc07..d5b642fdf 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -8,9 +8,8 @@ import 'dart:math'; import "package:test/test.dart"; import "package:mime/mime.dart"; -void _writeInChunks(List data, - int chunkSize, - StreamController> controller) { +void _writeInChunks( + List data, int chunkSize, StreamController> controller) { if (chunkSize == -1) chunkSize = data.length; int written = 0; @@ -23,24 +22,15 @@ void _writeInChunks(List data, controller.close(); } +enum TestMode { IMMEDIATE_LISTEN, DELAY_LISTEN, PAUSE_RESUME } -enum TestMode { - IMMEDIATE_LISTEN, - DELAY_LISTEN, - PAUSE_RESUME -} - -void _runParseTest(String message, - String boundary, - TestMode mode, - [List expectedHeaders, - List expectedParts, - bool expectError = false]) { +void _runParseTest(String message, String boundary, TestMode mode, + [List expectedHeaders, List expectedParts, bool expectError = false]) { Future testWrite(List data, [int chunkSize = -1]) { StreamController controller = new StreamController(sync: true); - var stream = controller.stream.transform( - new MimeMultipartTransformer(boundary)); + var stream = + controller.stream.transform(new MimeMultipartTransformer(boundary)); int i = 0; var completer = new Completer(); var futures = []; @@ -53,20 +43,20 @@ void _runParseTest(String message, case TestMode.IMMEDIATE_LISTEN: futures.add(multipart.fold([], (buffer, data) => buffer..addAll(data)) .then((data) { - if (expectedParts[part] != null) { - expect(data, equals(expectedParts[part].codeUnits)); - } - })); + if (expectedParts[part] != null) { + expect(data, equals(expectedParts[part].codeUnits)); + } + })); break; case TestMode.DELAY_LISTEN: futures.add(new Future(() { return multipart.fold([], (buffer, data) => buffer..addAll(data)) .then((data) { - if (expectedParts[part] != null) { - expect(data, equals(expectedParts[part].codeUnits)); - } - }); + if (expectedParts[part] != null) { + expect(data, equals(expectedParts[part].codeUnits)); + } + }); })); break; @@ -75,18 +65,16 @@ void _runParseTest(String message, futures.add(completer.future); var buffer = []; var subscription; - subscription = multipart.listen( - (data) { - buffer.addAll(data); - subscription.pause(); - new Future(() => subscription.resume()); - }, - onDone: () { - if (expectedParts[part] != null) { - expect(buffer, equals(expectedParts[part].codeUnits)); - } - completer.complete(); - }); + subscription = multipart.listen((data) { + buffer.addAll(data); + subscription.pause(); + new Future(() => subscription.resume()); + }, onDone: () { + if (expectedParts[part] != null) { + expect(buffer, equals(expectedParts[part].codeUnits)); + } + completer.complete(); + }); break; } }, onError: (error) { @@ -107,8 +95,8 @@ void _runParseTest(String message, var completer = new Completer(); var controller = new StreamController(sync: true); - var stream = controller.stream.transform( - new MimeMultipartTransformer(boundary)); + var stream = + controller.stream.transform(new MimeMultipartTransformer(boundary)); var subscription; subscription = stream.first.then((multipart) { @@ -129,13 +117,12 @@ void _runParseTest(String message, return completer.future; } - Future testCompletePartAfterCancel(List data, - int parts, - [int chunkSize = -1]) { + Future testCompletePartAfterCancel(List data, int parts, + [int chunkSize = -1]) { var completer = new Completer(); var controller = new StreamController(sync: true); - var stream = controller.stream.transform( - new MimeMultipartTransformer(boundary)); + var stream = + controller.stream.transform(new MimeMultipartTransformer(boundary)); var subscription; int i = 0; var futures = []; @@ -171,52 +158,52 @@ void _runParseTest(String message, // different chunks. List data = message.codeUnits; test('test', () { - expect(Future.wait([ - testWrite(data), - testWrite(data, 10), - testWrite(data, 2), - testWrite(data, 1), - ]), completes); + expect( + Future.wait([ + testWrite(data), + testWrite(data, 10), + testWrite(data, 2), + testWrite(data, 1), + ]), + completes); }); if (expectedParts.length > 0) { test('test-first-part-only', () { - expect(Future.wait([ - testFirstPartOnly(data), - testFirstPartOnly(data, 10), - testFirstPartOnly(data, 2), - testFirstPartOnly(data, 1), - ]), completes); + expect( + Future.wait([ + testFirstPartOnly(data), + testFirstPartOnly(data, 10), + testFirstPartOnly(data, 2), + testFirstPartOnly(data, 1), + ]), + completes); }); test('test-n-parts-only', () { int numPartsExpected = expectedParts.length - 1; if (numPartsExpected == 0) numPartsExpected = 1; - expect(Future.wait([ - testCompletePartAfterCancel(data, numPartsExpected), - testCompletePartAfterCancel(data, numPartsExpected, 10), - testCompletePartAfterCancel(data, numPartsExpected, 2), - testCompletePartAfterCancel(data, numPartsExpected, 1), - ]), completes); + expect( + Future.wait([ + testCompletePartAfterCancel(data, numPartsExpected), + testCompletePartAfterCancel(data, numPartsExpected, 10), + testCompletePartAfterCancel(data, numPartsExpected, 2), + testCompletePartAfterCancel(data, numPartsExpected, 1), + ]), + completes); }); } } -void _testParse(String message, - String boundary, - [List expectedHeaders, - List expectedParts, - bool expectError = false]) { - _runParseTest( - message, boundary, TestMode.IMMEDIATE_LISTEN, - expectedHeaders, expectedParts, expectError); - _runParseTest( - message, boundary, TestMode.DELAY_LISTEN, - expectedHeaders, expectedParts, expectError); - _runParseTest( - message, boundary, TestMode.PAUSE_RESUME, - expectedHeaders, expectedParts, expectError); +void _testParse(String message, String boundary, + [List expectedHeaders, List expectedParts, bool expectError = false]) { + _runParseTest(message, boundary, TestMode.IMMEDIATE_LISTEN, expectedHeaders, + expectedParts, expectError); + _runParseTest(message, boundary, TestMode.DELAY_LISTEN, expectedHeaders, + expectedParts, expectError); + _runParseTest(message, boundary, TestMode.PAUSE_RESUME, expectedHeaders, + expectedParts, expectError); } void _testParseValid() { @@ -239,8 +226,10 @@ PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\r --frontier--\r\n"""; var headers1 = {"content-type": "text/plain"}; - var headers2 = {"content-type": "application/octet-stream", - "content-transfer-encoding": "base64"}; + var headers2 = { + "content-type": "application/octet-stream", + "content-transfer-encoding": "base64" + }; var body1 = "This is the body of the message."; var body2 = """ PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg @@ -260,10 +249,11 @@ Content-Type: text/plain\r ... contents of file1.txt ...\r --AaB03x--\r\n"""; headers1 = { - "content-disposition": "form-data; name=\"submit-name\""}; + "content-disposition": "form-data; name=\"submit-name\"" + }; headers2 = { - "content-type": "text/plain", - "content-disposition": "form-data; name=\"files\"; filename=\"file1.txt\"" + "content-type": "text/plain", + "content-disposition": "form-data; name=\"files\"; filename=\"file1.txt\"" }; body1 = "Larry"; body2 = "... contents of file1.txt ..."; @@ -306,21 +296,23 @@ Content-Disposition: form-data; name=\"radio_input\"\r on\r ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n"""; headers1 = { - "content-disposition": "form-data; name=\"text_input\""}; + "content-disposition": "form-data; name=\"text_input\"" + }; headers2 = { - "content-disposition": "form-data; name=\"password_input\""}; + "content-disposition": "form-data; name=\"password_input\"" + }; var headers3 = { - "content-disposition": "form-data; name=\"checkbox_input\""}; + "content-disposition": "form-data; name=\"checkbox_input\"" + }; var headers4 = { - "content-disposition": "form-data; name=\"radio_input\""}; + "content-disposition": "form-data; name=\"radio_input\"" + }; body1 = "text"; body2 = "password"; var body3 = "on"; var body4 = "on"; - _testParse(message, - "----WebKitFormBoundaryQ3cgYAmGRF8yOeYB", - [headers1, headers2, headers3, headers4], - [body1, body2, body3, body4]); + _testParse(message, "----WebKitFormBoundaryQ3cgYAmGRF8yOeYB", + [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); // Same form from Firefox. message = """ @@ -341,10 +333,11 @@ Content-Disposition: form-data; name=\"radio_input\"\r \r on\r -----------------------------52284550912143824192005403738--\r\n"""; - _testParse(message, - "---------------------------52284550912143824192005403738", - [headers1, headers2, headers3, headers4], - [body1, body2, body3, body4]); + _testParse( + message, + "---------------------------52284550912143824192005403738", + [headers1, headers2, headers3, headers4], + [body1, body2, body3, body4]); // And Internet Explorer message = """ @@ -365,10 +358,8 @@ Content-Disposition: form-data; name=\"radio_input\"\r \r on\r -----------------------------7dc8f38c60326--\r\n"""; - _testParse(message, - "---------------------------7dc8f38c60326", - [headers1, headers2, headers3, headers4], - [body1, body2, body3, body4]); + _testParse(message, "---------------------------7dc8f38c60326", + [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); // Test boundary prefix inside prefix and content. message = """ diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index c7843433d..0ac32f586 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -8,10 +8,8 @@ import 'package:test/test.dart'; import 'package:mime/mime.dart'; import 'package:mime/src/magic_number.dart'; -void _expectMimeType(String path, - String expectedMimeType, - {List headerBytes, - MimeTypeResolver resolver}) { +void _expectMimeType(String path, String expectedMimeType, + {List headerBytes, MimeTypeResolver resolver}) { String mimeType; if (resolver == null) { mimeType = lookupMimeType(path, headerBytes: headerBytes); @@ -83,21 +81,14 @@ void main() { test('with-mask', () { var resolver = new MimeTypeResolver.empty(); - resolver.addMagicNumber([0x01, 0x02, 0x03], - 'my-mime-type', - mask: [0x01, 0xFF, 0xFE]); - _expectMimeType('file', - 'my-mime-type', - headerBytes: [0x01, 0x02, 0x03], - resolver: resolver); - _expectMimeType('file', - null, - headerBytes: [0x01, 0x03, 0x03], - resolver: resolver); - _expectMimeType('file', - 'my-mime-type', - headerBytes: [0xFF, 0x02, 0x02], - resolver: resolver); + resolver.addMagicNumber([0x01, 0x02, 0x03], 'my-mime-type', + mask: [0x01, 0xFF, 0xFE]); + _expectMimeType('file', 'my-mime-type', + headerBytes: [0x01, 0x02, 0x03], resolver: resolver); + _expectMimeType('file', null, + headerBytes: [0x01, 0x03, 0x03], resolver: resolver); + _expectMimeType('file', 'my-mime-type', + headerBytes: [0xFF, 0x02, 0x02], resolver: resolver); }); }); From cb622333341d0899c8b94db5d9f0064729620791 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 27 Aug 2015 08:54:58 -0700 Subject: [PATCH 028/118] cleanup unused members in test R=sgjesse@google.com Review URL: https://codereview.chromium.org//1318773002 . --- pkgs/mime/test/mime_multipart_transformer_test.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index d5b642fdf..de1dc6dec 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -12,12 +12,10 @@ void _writeInChunks( List data, int chunkSize, StreamController> controller) { if (chunkSize == -1) chunkSize = data.length; - int written = 0; for (int pos = 0; pos < data.length; pos += chunkSize) { int remaining = data.length - pos; int writeLength = min(chunkSize, remaining); controller.add(data.sublist(pos, pos + writeLength)); - written += writeLength; } controller.close(); } @@ -98,8 +96,7 @@ void _runParseTest(String message, String boundary, TestMode mode, var stream = controller.stream.transform(new MimeMultipartTransformer(boundary)); - var subscription; - subscription = stream.first.then((multipart) { + stream.first.then((multipart) { if (expectedHeaders != null) { expect(multipart.headers, equals(expectedHeaders[0])); } From 20972621f172bd0d54f0cf11bfbe2597a592fe8f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 27 Aug 2015 08:55:27 -0700 Subject: [PATCH 029/118] Update bot configuration to use test package R=sgjesse@google.com Review URL: https://codereview.chromium.org//1318763002 . --- pkgs/mime/.status | 12 ------------ pkgs/mime/.test_config | 3 +++ 2 files changed, 3 insertions(+), 12 deletions(-) delete mode 100644 pkgs/mime/.status create mode 100644 pkgs/mime/.test_config diff --git a/pkgs/mime/.status b/pkgs/mime/.status deleted file mode 100644 index ebc5f8132..000000000 --- a/pkgs/mime/.status +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file -# for details. All rights reserved. Use of this source code is governed by a -# BSD-style license that can be found in the LICENSE file. - -# Skip non-test files ending with "_test". -packages/*: Skip -*/packages/*: Skip -*/*/packages/*: Skip -*/*/*/packages/*: Skip -*/*/*/*packages/*: Skip -*/*/*/*/*packages/*: Skip - diff --git a/pkgs/mime/.test_config b/pkgs/mime/.test_config new file mode 100644 index 000000000..412fc5c5c --- /dev/null +++ b/pkgs/mime/.test_config @@ -0,0 +1,3 @@ +{ + "test_package": true +} \ No newline at end of file From e5b74ab7cf6ce77bc041fda41bf7cb62d585f969 Mon Sep 17 00:00:00 2001 From: keertip Date: Fri, 9 Dec 2016 11:27:03 -0800 Subject: [PATCH 030/118] Make package mime strong clean BUG=https://github.com/dart-lang/mime/issues/5 R=kevmoo@google.com Review URL: https://codereview.chromium.org//2561953002 . --- pkgs/mime/.analysis_options | 2 ++ pkgs/mime/lib/src/bound_multipart_stream.dart | 4 ++-- pkgs/mime/test/mime_multipart_transformer_test.dart | 10 +++++----- pkgs/mime/test/mime_type_test.dart | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 pkgs/mime/.analysis_options diff --git a/pkgs/mime/.analysis_options b/pkgs/mime/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/pkgs/mime/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index 270503a73..73811e7c5 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -81,13 +81,13 @@ class BoundMultipartStream { int _controllerState = _CONTROLLER_STATE_IDLE; - StreamController _controller; + StreamController _controller; Stream get stream => _controller.stream; StreamSubscription _subscription; - StreamController _multipartController; + StreamController> _multipartController; Map _headers; int _state = _START; diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index de1dc6dec..76f6514ab 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -25,13 +25,13 @@ enum TestMode { IMMEDIATE_LISTEN, DELAY_LISTEN, PAUSE_RESUME } void _runParseTest(String message, String boundary, TestMode mode, [List expectedHeaders, List expectedParts, bool expectError = false]) { Future testWrite(List data, [int chunkSize = -1]) { - StreamController controller = new StreamController(sync: true); + var controller = new StreamController>(sync: true); var stream = controller.stream.transform(new MimeMultipartTransformer(boundary)); int i = 0; var completer = new Completer(); - var futures = []; + var futures = []; stream.listen((multipart) { int part = i++; if (expectedHeaders != null) { @@ -91,7 +91,7 @@ void _runParseTest(String message, String boundary, TestMode mode, Future testFirstPartOnly(List data, [int chunkSize = -1]) { var completer = new Completer(); - var controller = new StreamController(sync: true); + var controller = new StreamController>(sync: true); var stream = controller.stream.transform(new MimeMultipartTransformer(boundary)); @@ -117,12 +117,12 @@ void _runParseTest(String message, String boundary, TestMode mode, Future testCompletePartAfterCancel(List data, int parts, [int chunkSize = -1]) { var completer = new Completer(); - var controller = new StreamController(sync: true); + var controller = new StreamController>(sync: true); var stream = controller.stream.transform(new MimeMultipartTransformer(boundary)); var subscription; int i = 0; - var futures = []; + var futures = []; subscription = stream.listen((multipart) { int partIndex = i; diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 0ac32f586..87de96df3 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -93,7 +93,7 @@ void main() { }); test('default magic number', () { - var actualMaxBytes = DEFAULT_MAGIC_NUMBERS.fold(0, (previous, magic) { + var actualMaxBytes = DEFAULT_MAGIC_NUMBERS.fold(0, (num previous, magic) { return math.max(previous, magic.numbers.length); }); From 692cb13c0c34e90bb2b30b692772d664565162a9 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 10 Sep 2017 23:55:34 -0700 Subject: [PATCH 031/118] Travis ci (dart-lang/mime#8) * Fix analysis options * Add travis-ci file * dartfmt --- pkgs/mime/.analysis_options | 2 - pkgs/mime/.travis.yml | 17 + pkgs/mime/analysis_options.yaml | 40 + pkgs/mime/lib/src/bound_multipart_stream.dart | 75 +- pkgs/mime/lib/src/default_extension_map.dart | 1968 +++++++++-------- pkgs/mime/lib/src/magic_number.dart | 33 +- .../lib/src/mime_multipart_transformer.dart | 2 +- pkgs/mime/lib/src/mime_shared.dart | 2 +- .../test/mime_multipart_transformer_test.dart | 10 +- pkgs/mime/test/mime_type_test.dart | 56 +- 10 files changed, 1168 insertions(+), 1037 deletions(-) delete mode 100644 pkgs/mime/.analysis_options create mode 100644 pkgs/mime/.travis.yml create mode 100644 pkgs/mime/analysis_options.yaml diff --git a/pkgs/mime/.analysis_options b/pkgs/mime/.analysis_options deleted file mode 100644 index a10d4c5a0..000000000 --- a/pkgs/mime/.analysis_options +++ /dev/null @@ -1,2 +0,0 @@ -analyzer: - strong-mode: true diff --git a/pkgs/mime/.travis.yml b/pkgs/mime/.travis.yml new file mode 100644 index 000000000..da58f76ba --- /dev/null +++ b/pkgs/mime/.travis.yml @@ -0,0 +1,17 @@ +language: dart +sudo: false +dart: + - dev + - stable +dart_task: + - test + - dartfmt + - dartanalyzer + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + +cache: + directories: + - $HOME/.pub-cache diff --git a/pkgs/mime/analysis_options.yaml b/pkgs/mime/analysis_options.yaml new file mode 100644 index 000000000..6ff678df9 --- /dev/null +++ b/pkgs/mime/analysis_options.yaml @@ -0,0 +1,40 @@ +analyzer: + strong-mode: + implicit-casts: false + errors: + unused_element: error + unused_import: error + unused_local_variable: error + dead_code: error +linter: + rules: + # Errors + - avoid_empty_else + #- comment_references + - control_flow_in_finally + - empty_statements + - hash_and_equals + - implementation_imports + - test_types_in_equals + - throw_in_finally + - unrelated_type_equality_checks + - valid_regexps + + # Style + #- annotate_overrides + - avoid_init_to_null + - avoid_return_types_on_setters + - await_only_futures + - camel_case_types + - directives_ordering + - empty_catches + - empty_constructor_bodies + - library_names + - library_prefixes + - non_constant_identifier_names + - only_throw_errors + - prefer_final_fields + - prefer_is_not_empty + #- prefer_single_quotes + #- slash_for_doc_comments + - type_init_formals diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index 73811e7c5..aab7ddda2 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -6,12 +6,31 @@ library mime.bound_multipart_stream; import 'dart:async'; import 'dart:convert'; -import 'mime_shared.dart'; import 'char_code.dart'; +import 'mime_shared.dart'; // Bytes for '()<>@,;:\\"/[]?={} \t'. -const _SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, 91, 93, - 63, 61, 123, 125, 32, 9]; +const _SEPARATORS = const [ + 40, + 41, + 60, + 62, + 64, + 44, + 59, + 58, + 92, + 34, + 47, + 91, + 93, + 63, + 61, + 123, + 125, + 32, + 9 +]; bool _isTokenChar(int byte) { return byte > 31 && byte < 128 && _SEPARATORS.indexOf(byte) == -1; @@ -102,25 +121,27 @@ class BoundMultipartStream { _controller = new StreamController( sync: true, onPause: _pauseStream, - onResume: _resumeStream, onCancel: () { - _controllerState = _CONTROLLER_STATE_CANCELED; - _tryPropagateControllerState(); - }, onListen: () { - _controllerState = _CONTROLLER_STATE_ACTIVE; - _subscription = stream.listen((data) { - assert(_buffer == null); - _subscription.pause(); - _buffer = data; - _index = 0; - _parse(); - }, onDone: () { - if (_state != _DONE) { - _controller - .addError(new MimeMultipartException("Bad multipart ending")); - } - _controller.close(); - }, onError: _controller.addError); - }); + onResume: _resumeStream, + onCancel: () { + _controllerState = _CONTROLLER_STATE_CANCELED; + _tryPropagateControllerState(); + }, + onListen: () { + _controllerState = _CONTROLLER_STATE_ACTIVE; + _subscription = stream.listen((data) { + assert(_buffer == null); + _subscription.pause(); + _buffer = data; + _index = 0; + _parse(); + }, onDone: () { + if (_state != _DONE) { + _controller + .addError(new MimeMultipartException("Bad multipart ending")); + } + _controller.close(); + }, onError: _controller.addError); + }); } void _resumeStream() { @@ -300,9 +321,13 @@ class BoundMultipartStream { case _HEADER_ENDING: _expectByteValue(byte, CharCode.LF); - _multipartController = new StreamController(sync: true, onListen: () { - if (_subscription.isPaused) _subscription.resume(); - }, onPause: _subscription.pause, onResume: _subscription.resume); + _multipartController = new StreamController( + sync: true, + onListen: () { + if (_subscription.isPaused) _subscription.resume(); + }, + onPause: _subscription.pause, + onResume: _subscription.resume); _controller .add(new _MimeMultipart(_headers, _multipartController.stream)); _headers = null; diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index ae0d7df5d..cfa42ed9d 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -6,985 +6,991 @@ library mime.extension_map; // TODO(ajohnsen): Use const map once Issue 7559 is fixed. final Map defaultExtensionMap = { -'123':'application/vnd.lotus-1-2-3', -'3dml':'text/vnd.in3d.3dml', -'3ds':'image/x-3ds', -'3g2':'video/3gpp2', -'3gp':'video/3gpp', -'7z':'application/x-7z-compressed', -'aab':'application/x-authorware-bin', -'aac':'audio/x-aac', -'aam':'application/x-authorware-map', -'aas':'application/x-authorware-seg', -'abw':'application/x-abiword', -'ac':'application/pkix-attr-cert', -'acc':'application/vnd.americandynamics.acc', -'ace':'application/x-ace-compressed', -'acu':'application/vnd.acucobol', -'acutc':'application/vnd.acucorp', -'adp':'audio/adpcm', -'aep':'application/vnd.audiograph', -'afm':'application/x-font-type1', -'afp':'application/vnd.ibm.modcap', -'ahead':'application/vnd.ahead.space', -'ai':'application/postscript', -'aif':'audio/x-aiff', -'aifc':'audio/x-aiff', -'aiff':'audio/x-aiff', -'air':'application/vnd.adobe.air-application-installer-package+zip', -'ait':'application/vnd.dvb.ait', -'ami':'application/vnd.amiga.ami', -'apk':'application/vnd.android.package-archive', -'appcache':'text/cache-manifest', -'application':'application/x-ms-application', -'apr':'application/vnd.lotus-approach', -'arc':'application/x-freearc', -'asc':'application/pgp-signature', -'asf':'video/x-ms-asf', -'asm':'text/x-asm', -'aso':'application/vnd.accpac.simply.aso', -'asx':'video/x-ms-asf', -'atc':'application/vnd.acucorp', -'atom':'application/atom+xml', -'atomcat':'application/atomcat+xml', -'atomsvc':'application/atomsvc+xml', -'atx':'application/vnd.antix.game-component', -'au':'audio/basic', -'avi':'video/x-msvideo', -'aw':'application/applixware', -'azf':'application/vnd.airzip.filesecure.azf', -'azs':'application/vnd.airzip.filesecure.azs', -'azw':'application/vnd.amazon.ebook', -'bat':'application/x-msdownload', -'bcpio':'application/x-bcpio', -'bdf':'application/x-font-bdf', -'bdm':'application/vnd.syncml.dm+wbxml', -'bed':'application/vnd.realvnc.bed', -'bh2':'application/vnd.fujitsu.oasysprs', -'bin':'application/octet-stream', -'blb':'application/x-blorb', -'blorb':'application/x-blorb', -'bmi':'application/vnd.bmi', -'bmp':'image/bmp', -'book':'application/vnd.framemaker', -'box':'application/vnd.previewsystems.box', -'boz':'application/x-bzip2', -'bpk':'application/octet-stream', -'btif':'image/prs.btif', -'bz':'application/x-bzip', -'bz2':'application/x-bzip2', -'c':'text/x-c', -'c11amc':'application/vnd.cluetrust.cartomobile-config', -'c11amz':'application/vnd.cluetrust.cartomobile-config-pkg', -'c4d':'application/vnd.clonk.c4group', -'c4f':'application/vnd.clonk.c4group', -'c4g':'application/vnd.clonk.c4group', -'c4p':'application/vnd.clonk.c4group', -'c4u':'application/vnd.clonk.c4group', -'cab':'application/vnd.ms-cab-compressed', -'caf':'audio/x-caf', -'cap':'application/vnd.tcpdump.pcap', -'car':'application/vnd.curl.car', -'cat':'application/vnd.ms-pki.seccat', -'cb7':'application/x-cbr', -'cba':'application/x-cbr', -'cbr':'application/x-cbr', -'cbt':'application/x-cbr', -'cbz':'application/x-cbr', -'cc':'text/x-c', -'cct':'application/x-director', -'ccxml':'application/ccxml+xml', -'cdbcmsg':'application/vnd.contact.cmsg', -'cdf':'application/x-netcdf', -'cdkey':'application/vnd.mediastation.cdkey', -'cdmia':'application/cdmi-capability', -'cdmic':'application/cdmi-container', -'cdmid':'application/cdmi-domain', -'cdmio':'application/cdmi-object', -'cdmiq':'application/cdmi-queue', -'cdx':'chemical/x-cdx', -'cdxml':'application/vnd.chemdraw+xml', -'cdy':'application/vnd.cinderella', -'cer':'application/pkix-cert', -'cfs':'application/x-cfs-compressed', -'cgm':'image/cgm', -'chat':'application/x-chat', -'chm':'application/vnd.ms-htmlhelp', -'chrt':'application/vnd.kde.kchart', -'cif':'chemical/x-cif', -'cii':'application/vnd.anser-web-certificate-issue-initiation', -'cil':'application/vnd.ms-artgalry', -'cla':'application/vnd.claymore', -'class':'application/java-vm', -'clkk':'application/vnd.crick.clicker.keyboard', -'clkp':'application/vnd.crick.clicker.palette', -'clkt':'application/vnd.crick.clicker.template', -'clkw':'application/vnd.crick.clicker.wordbank', -'clkx':'application/vnd.crick.clicker', -'clp':'application/x-msclip', -'cmc':'application/vnd.cosmocaller', -'cmdf':'chemical/x-cmdf', -'cml':'chemical/x-cml', -'cmp':'application/vnd.yellowriver-custom-menu', -'cmx':'image/x-cmx', -'cod':'application/vnd.rim.cod', -'com':'application/x-msdownload', -'conf':'text/plain', -'cpio':'application/x-cpio', -'cpp':'text/x-c', -'cpt':'application/mac-compactpro', -'crd':'application/x-mscardfile', -'crl':'application/pkix-crl', -'crt':'application/x-x509-ca-cert', -'cryptonote':'application/vnd.rig.cryptonote', -'csh':'application/x-csh', -'csml':'chemical/x-csml', -'csp':'application/vnd.commonspace', -'css':'text/css', -'cst':'application/x-director', -'csv':'text/csv', -'cu':'application/cu-seeme', -'curl':'text/vnd.curl', -'cww':'application/prs.cww', -'cxt':'application/x-director', -'cxx':'text/x-c', -'dae':'model/vnd.collada+xml', -'daf':'application/vnd.mobius.daf', -'dart':'application/dart', -'dataless':'application/vnd.fdsn.seed', -'davmount':'application/davmount+xml', -'dbk':'application/docbook+xml', -'dcr':'application/x-director', -'dcurl':'text/vnd.curl.dcurl', -'dd2':'application/vnd.oma.dd2+xml', -'ddd':'application/vnd.fujixerox.ddd', -'deb':'application/x-debian-package', -'def':'text/plain', -'deploy':'application/octet-stream', -'der':'application/x-x509-ca-cert', -'dfac':'application/vnd.dreamfactory', -'dgc':'application/x-dgc-compressed', -'dic':'text/x-c', -'dir':'application/x-director', -'dis':'application/vnd.mobius.dis', -'dist':'application/octet-stream', -'distz':'application/octet-stream', -'djv':'image/vnd.djvu', -'djvu':'image/vnd.djvu', -'dll':'application/x-msdownload', -'dmg':'application/x-apple-diskimage', -'dmp':'application/vnd.tcpdump.pcap', -'dms':'application/octet-stream', -'dna':'application/vnd.dna', -'doc':'application/msword', -'docm':'application/vnd.ms-word.document.macroenabled.12', -'docx':'application/vnd.openxmlformats-officedocument.wordprocessingml.document', -'dot':'application/msword', -'dotm':'application/vnd.ms-word.template.macroenabled.12', -'dotx':'application/vnd.openxmlformats-officedocument.wordprocessingml.template', -'dp':'application/vnd.osgi.dp', -'dpg':'application/vnd.dpgraph', -'dra':'audio/vnd.dra', -'dsc':'text/prs.lines.tag', -'dssc':'application/dssc+der', -'dtb':'application/x-dtbook+xml', -'dtd':'application/xml-dtd', -'dts':'audio/vnd.dts', -'dtshd':'audio/vnd.dts.hd', -'dump':'application/octet-stream', -'dvb':'video/vnd.dvb.file', -'dvi':'application/x-dvi', -'dwf':'model/vnd.dwf', -'dwg':'image/vnd.dwg', -'dxf':'image/vnd.dxf', -'dxp':'application/vnd.spotfire.dxp', -'dxr':'application/x-director', -'ecelp4800':'audio/vnd.nuera.ecelp4800', -'ecelp7470':'audio/vnd.nuera.ecelp7470', -'ecelp9600':'audio/vnd.nuera.ecelp9600', -'ecma':'application/ecmascript', -'edm':'application/vnd.novadigm.edm', -'edx':'application/vnd.novadigm.edx', -'efif':'application/vnd.picsel', -'ei6':'application/vnd.pg.osasli', -'elc':'application/octet-stream', -'emf':'application/x-msmetafile', -'eml':'message/rfc822', -'emma':'application/emma+xml', -'emz':'application/x-msmetafile', -'eol':'audio/vnd.digital-winds', -'eot':'application/vnd.ms-fontobject', -'eps':'application/postscript', -'epub':'application/epub+zip', -'es3':'application/vnd.eszigno3+xml', -'esa':'application/vnd.osgi.subsystem', -'esf':'application/vnd.epson.esf', -'et3':'application/vnd.eszigno3+xml', -'etx':'text/x-setext', -'eva':'application/x-eva', -'evy':'application/x-envoy', -'exe':'application/x-msdownload', -'exi':'application/exi', -'ext':'application/vnd.novadigm.ext', -'ez':'application/andrew-inset', -'ez2':'application/vnd.ezpix-album', -'ez3':'application/vnd.ezpix-package', -'f':'text/x-fortran', -'f4v':'video/x-f4v', -'f77':'text/x-fortran', -'f90':'text/x-fortran', -'fbs':'image/vnd.fastbidsheet', -'fcdt':'application/vnd.adobe.formscentral.fcdt', -'fcs':'application/vnd.isac.fcs', -'fdf':'application/vnd.fdf', -'fe_launch':'application/vnd.denovo.fcselayout-link', -'fg5':'application/vnd.fujitsu.oasysgp', -'fgd':'application/x-director', -'fh':'image/x-freehand', -'fh4':'image/x-freehand', -'fh5':'image/x-freehand', -'fh7':'image/x-freehand', -'fhc':'image/x-freehand', -'fig':'application/x-xfig', -'flac':'audio/x-flac', -'fli':'video/x-fli', -'flo':'application/vnd.micrografx.flo', -'flv':'video/x-flv', -'flw':'application/vnd.kde.kivio', -'flx':'text/vnd.fmi.flexstor', -'fly':'text/vnd.fly', -'fm':'application/vnd.framemaker', -'fnc':'application/vnd.frogans.fnc', -'for':'text/x-fortran', -'fpx':'image/vnd.fpx', -'frame':'application/vnd.framemaker', -'fsc':'application/vnd.fsc.weblaunch', -'fst':'image/vnd.fst', -'ftc':'application/vnd.fluxtime.clip', -'fti':'application/vnd.anser-web-funds-transfer-initiation', -'fvt':'video/vnd.fvt', -'fxp':'application/vnd.adobe.fxp', -'fxpl':'application/vnd.adobe.fxp', -'fzs':'application/vnd.fuzzysheet', -'g2w':'application/vnd.geoplan', -'g3':'image/g3fax', -'g3w':'application/vnd.geospace', -'gac':'application/vnd.groove-account', -'gam':'application/x-tads', -'gbr':'application/rpki-ghostbusters', -'gca':'application/x-gca-compressed', -'gdl':'model/vnd.gdl', -'geo':'application/vnd.dynageo', -'gex':'application/vnd.geometry-explorer', -'ggb':'application/vnd.geogebra.file', -'ggt':'application/vnd.geogebra.tool', -'ghf':'application/vnd.groove-help', -'gif':'image/gif', -'gim':'application/vnd.groove-identity-message', -'gml':'application/gml+xml', -'gmx':'application/vnd.gmx', -'gnumeric':'application/x-gnumeric', -'gph':'application/vnd.flographit', -'gpx':'application/gpx+xml', -'gqf':'application/vnd.grafeq', -'gqs':'application/vnd.grafeq', -'gram':'application/srgs', -'gramps':'application/x-gramps-xml', -'gre':'application/vnd.geometry-explorer', -'grv':'application/vnd.groove-injector', -'grxml':'application/srgs+xml', -'gsf':'application/x-font-ghostscript', -'gtar':'application/x-gtar', -'gtm':'application/vnd.groove-tool-message', -'gtw':'model/vnd.gtw', -'gv':'text/vnd.graphviz', -'gxf':'application/gxf', -'gxt':'application/vnd.geonext', -'h':'text/x-c', -'h261':'video/h261', -'h263':'video/h263', -'h264':'video/h264', -'hal':'application/vnd.hal+xml', -'hbci':'application/vnd.hbci', -'hdf':'application/x-hdf', -'hh':'text/x-c', -'hlp':'application/winhlp', -'hpgl':'application/vnd.hp-hpgl', -'hpid':'application/vnd.hp-hpid', -'hps':'application/vnd.hp-hps', -'hqx':'application/mac-binhex40', -'htke':'application/vnd.kenameaapp', -'htm':'text/html', -'html':'text/html', -'hvd':'application/vnd.yamaha.hv-dic', -'hvp':'application/vnd.yamaha.hv-voice', -'hvs':'application/vnd.yamaha.hv-script', -'i2g':'application/vnd.intergeo', -'icc':'application/vnd.iccprofile', -'ice':'x-conference/x-cooltalk', -'icm':'application/vnd.iccprofile', -'ico':'image/x-icon', -'ics':'text/calendar', -'ief':'image/ief', -'ifb':'text/calendar', -'ifm':'application/vnd.shana.informed.formdata', -'iges':'model/iges', -'igl':'application/vnd.igloader', -'igm':'application/vnd.insors.igm', -'igs':'model/iges', -'igx':'application/vnd.micrografx.igx', -'iif':'application/vnd.shana.informed.interchange', -'imp':'application/vnd.accpac.simply.imp', -'ims':'application/vnd.ms-ims', -'in':'text/plain', -'ink':'application/inkml+xml', -'inkml':'application/inkml+xml', -'install':'application/x-install-instructions', -'iota':'application/vnd.astraea-software.iota', -'ipfix':'application/ipfix', -'ipk':'application/vnd.shana.informed.package', -'irm':'application/vnd.ibm.rights-management', -'irp':'application/vnd.irepository.package+xml', -'iso':'application/x-iso9660-image', -'itp':'application/vnd.shana.informed.formtemplate', -'ivp':'application/vnd.immervision-ivp', -'ivu':'application/vnd.immervision-ivu', -'jad':'text/vnd.sun.j2me.app-descriptor', -'jam':'application/vnd.jam', -'jar':'application/java-archive', -'java':'text/x-java-source', -'jisp':'application/vnd.jisp', -'jlt':'application/vnd.hp-jlyt', -'jnlp':'application/x-java-jnlp-file', -'joda':'application/vnd.joost.joda-archive', -'jpe':'image/jpeg', -'jpeg':'image/jpeg', -'jpg':'image/jpeg', -'jpgm':'video/jpm', -'jpgv':'video/jpeg', -'jpm':'video/jpm', -'js':'application/javascript', -'json':'application/json', -'jsonml':'application/jsonml+json', -'kar':'audio/midi', -'karbon':'application/vnd.kde.karbon', -'kfo':'application/vnd.kde.kformula', -'kia':'application/vnd.kidspiration', -'kml':'application/vnd.google-earth.kml+xml', -'kmz':'application/vnd.google-earth.kmz', -'kne':'application/vnd.kinar', -'knp':'application/vnd.kinar', -'kon':'application/vnd.kde.kontour', -'kpr':'application/vnd.kde.kpresenter', -'kpt':'application/vnd.kde.kpresenter', -'kpxx':'application/vnd.ds-keypoint', -'ksp':'application/vnd.kde.kspread', -'ktr':'application/vnd.kahootz', -'ktx':'image/ktx', -'ktz':'application/vnd.kahootz', -'kwd':'application/vnd.kde.kword', -'kwt':'application/vnd.kde.kword', -'lasxml':'application/vnd.las.las+xml', -'latex':'application/x-latex', -'lbd':'application/vnd.llamagraphics.life-balance.desktop', -'lbe':'application/vnd.llamagraphics.life-balance.exchange+xml', -'les':'application/vnd.hhe.lesson-player', -'lha':'application/x-lzh-compressed', -'link66':'application/vnd.route66.link66+xml', -'list':'text/plain', -'list3820':'application/vnd.ibm.modcap', -'listafp':'application/vnd.ibm.modcap', -'lnk':'application/x-ms-shortcut', -'log':'text/plain', -'lostxml':'application/lost+xml', -'lrf':'application/octet-stream', -'lrm':'application/vnd.ms-lrm', -'ltf':'application/vnd.frogans.ltf', -'lvp':'audio/vnd.lucent.voice', -'lwp':'application/vnd.lotus-wordpro', -'lzh':'application/x-lzh-compressed', -'m13':'application/x-msmediaview', -'m14':'application/x-msmediaview', -'m1v':'video/mpeg', -'m21':'application/mp21', -'m2a':'audio/mpeg', -'m2v':'video/mpeg', -'m3a':'audio/mpeg', -'m3u':'audio/x-mpegurl', -'m3u8':'application/vnd.apple.mpegurl', -'m4u':'video/vnd.mpegurl', -'m4v':'video/x-m4v', -'ma':'application/mathematica', -'mads':'application/mads+xml', -'mag':'application/vnd.ecowin.chart', -'maker':'application/vnd.framemaker', -'man':'text/troff', -'mar':'application/octet-stream', -'mathml':'application/mathml+xml', -'mb':'application/mathematica', -'mbk':'application/vnd.mobius.mbk', -'mbox':'application/mbox', -'mc1':'application/vnd.medcalcdata', -'mcd':'application/vnd.mcd', -'mcurl':'text/vnd.curl.mcurl', -'mdb':'application/x-msaccess', -'mdi':'image/vnd.ms-modi', -'me':'text/troff', -'mesh':'model/mesh', -'meta4':'application/metalink4+xml', -'metalink':'application/metalink+xml', -'mets':'application/mets+xml', -'mfm':'application/vnd.mfmp', -'mft':'application/rpki-manifest', -'mgp':'application/vnd.osgeo.mapguide.package', -'mgz':'application/vnd.proteus.magazine', -'mid':'audio/midi', -'midi':'audio/midi', -'mie':'application/x-mie', -'mif':'application/vnd.mif', -'mime':'message/rfc822', -'mj2':'video/mj2', -'mjp2':'video/mj2', -'mk3d':'video/x-matroska', -'mka':'audio/x-matroska', -'mks':'video/x-matroska', -'mkv':'video/x-matroska', -'mlp':'application/vnd.dolby.mlp', -'mmd':'application/vnd.chipnuts.karaoke-mmd', -'mmf':'application/vnd.smaf', -'mmr':'image/vnd.fujixerox.edmics-mmr', -'mng':'video/x-mng', -'mny':'application/x-msmoney', -'mobi':'application/x-mobipocket-ebook', -'mods':'application/mods+xml', -'mov':'video/quicktime', -'movie':'video/x-sgi-movie', -'mp2':'audio/mpeg', -'mp21':'application/mp21', -'mp2a':'audio/mpeg', -'mp3':'audio/mpeg', -'mp4':'video/mp4', -'mp4a':'audio/mp4', -'mp4s':'application/mp4', -'mp4v':'video/mp4', -'mpc':'application/vnd.mophun.certificate', -'mpe':'video/mpeg', -'mpeg':'video/mpeg', -'mpg':'video/mpeg', -'mpg4':'video/mp4', -'mpga':'audio/mpeg', -'mpkg':'application/vnd.apple.installer+xml', -'mpm':'application/vnd.blueice.multipass', -'mpn':'application/vnd.mophun.application', -'mpp':'application/vnd.ms-project', -'mpt':'application/vnd.ms-project', -'mpy':'application/vnd.ibm.minipay', -'mqy':'application/vnd.mobius.mqy', -'mrc':'application/marc', -'mrcx':'application/marcxml+xml', -'ms':'text/troff', -'mscml':'application/mediaservercontrol+xml', -'mseed':'application/vnd.fdsn.mseed', -'mseq':'application/vnd.mseq', -'msf':'application/vnd.epson.msf', -'msh':'model/mesh', -'msi':'application/x-msdownload', -'msl':'application/vnd.mobius.msl', -'msty':'application/vnd.muvee.style', -'mts':'model/vnd.mts', -'mus':'application/vnd.musician', -'musicxml':'application/vnd.recordare.musicxml+xml', -'mvb':'application/x-msmediaview', -'mwf':'application/vnd.mfer', -'mxf':'application/mxf', -'mxl':'application/vnd.recordare.musicxml', -'mxml':'application/xv+xml', -'mxs':'application/vnd.triscape.mxs', -'mxu':'video/vnd.mpegurl', -'n-gage':'application/vnd.nokia.n-gage.symbian.install', -'n3':'text/n3', -'nb':'application/mathematica', -'nbp':'application/vnd.wolfram.player', -'nc':'application/x-netcdf', -'ncx':'application/x-dtbncx+xml', -'nfo':'text/x-nfo', -'ngdat':'application/vnd.nokia.n-gage.data', -'nitf':'application/vnd.nitf', -'nlu':'application/vnd.neurolanguage.nlu', -'nml':'application/vnd.enliven', -'nnd':'application/vnd.noblenet-directory', -'nns':'application/vnd.noblenet-sealer', -'nnw':'application/vnd.noblenet-web', -'npx':'image/vnd.net-fpx', -'nsc':'application/x-conference', -'nsf':'application/vnd.lotus-notes', -'ntf':'application/vnd.nitf', -'nzb':'application/x-nzb', -'oa2':'application/vnd.fujitsu.oasys2', -'oa3':'application/vnd.fujitsu.oasys3', -'oas':'application/vnd.fujitsu.oasys', -'obd':'application/x-msbinder', -'obj':'application/x-tgif', -'oda':'application/oda', -'odb':'application/vnd.oasis.opendocument.database', -'odc':'application/vnd.oasis.opendocument.chart', -'odf':'application/vnd.oasis.opendocument.formula', -'odft':'application/vnd.oasis.opendocument.formula-template', -'odg':'application/vnd.oasis.opendocument.graphics', -'odi':'application/vnd.oasis.opendocument.image', -'odm':'application/vnd.oasis.opendocument.text-master', -'odp':'application/vnd.oasis.opendocument.presentation', -'ods':'application/vnd.oasis.opendocument.spreadsheet', -'odt':'application/vnd.oasis.opendocument.text', -'oga':'audio/ogg', -'ogg':'audio/ogg', -'ogv':'video/ogg', -'ogx':'application/ogg', -'omdoc':'application/omdoc+xml', -'onepkg':'application/onenote', -'onetmp':'application/onenote', -'onetoc':'application/onenote', -'onetoc2':'application/onenote', -'opf':'application/oebps-package+xml', -'opml':'text/x-opml', -'oprc':'application/vnd.palm', -'org':'application/vnd.lotus-organizer', -'osf':'application/vnd.yamaha.openscoreformat', -'osfpvg':'application/vnd.yamaha.openscoreformat.osfpvg+xml', -'otc':'application/vnd.oasis.opendocument.chart-template', -'otf':'application/x-font-otf', -'otg':'application/vnd.oasis.opendocument.graphics-template', -'oth':'application/vnd.oasis.opendocument.text-web', -'oti':'application/vnd.oasis.opendocument.image-template', -'otp':'application/vnd.oasis.opendocument.presentation-template', -'ots':'application/vnd.oasis.opendocument.spreadsheet-template', -'ott':'application/vnd.oasis.opendocument.text-template', -'oxps':'application/oxps', -'oxt':'application/vnd.openofficeorg.extension', -'p':'text/x-pascal', -'p10':'application/pkcs10', -'p12':'application/x-pkcs12', -'p7b':'application/x-pkcs7-certificates', -'p7c':'application/pkcs7-mime', -'p7m':'application/pkcs7-mime', -'p7r':'application/x-pkcs7-certreqresp', -'p7s':'application/pkcs7-signature', -'p8':'application/pkcs8', -'pas':'text/x-pascal', -'paw':'application/vnd.pawaafile', -'pbd':'application/vnd.powerbuilder6', -'pbm':'image/x-portable-bitmap', -'pcap':'application/vnd.tcpdump.pcap', -'pcf':'application/x-font-pcf', -'pcl':'application/vnd.hp-pcl', -'pclxl':'application/vnd.hp-pclxl', -'pct':'image/x-pict', -'pcurl':'application/vnd.curl.pcurl', -'pcx':'image/x-pcx', -'pdb':'application/vnd.palm', -'pdf':'application/pdf', -'pfa':'application/x-font-type1', -'pfb':'application/x-font-type1', -'pfm':'application/x-font-type1', -'pfr':'application/font-tdpfr', -'pfx':'application/x-pkcs12', -'pgm':'image/x-portable-graymap', -'pgn':'application/x-chess-pgn', -'pgp':'application/pgp-encrypted', -'pic':'image/x-pict', -'pkg':'application/octet-stream', -'pki':'application/pkixcmp', -'pkipath':'application/pkix-pkipath', -'plb':'application/vnd.3gpp.pic-bw-large', -'plc':'application/vnd.mobius.plc', -'plf':'application/vnd.pocketlearn', -'pls':'application/pls+xml', -'pml':'application/vnd.ctc-posml', -'png':'image/png', -'pnm':'image/x-portable-anymap', -'portpkg':'application/vnd.macports.portpkg', -'pot':'application/vnd.ms-powerpoint', -'potm':'application/vnd.ms-powerpoint.template.macroenabled.12', -'potx':'application/vnd.openxmlformats-officedocument.presentationml.template', -'ppam':'application/vnd.ms-powerpoint.addin.macroenabled.12', -'ppd':'application/vnd.cups-ppd', -'ppm':'image/x-portable-pixmap', -'pps':'application/vnd.ms-powerpoint', -'ppsm':'application/vnd.ms-powerpoint.slideshow.macroenabled.12', -'ppsx':'application/vnd.openxmlformats-officedocument.presentationml.slideshow', -'ppt':'application/vnd.ms-powerpoint', -'pptm':'application/vnd.ms-powerpoint.presentation.macroenabled.12', -'pptx':'application/vnd.openxmlformats-officedocument.presentationml.presentation', -'pqa':'application/vnd.palm', -'prc':'application/x-mobipocket-ebook', -'pre':'application/vnd.lotus-freelance', -'prf':'application/pics-rules', -'ps':'application/postscript', -'psb':'application/vnd.3gpp.pic-bw-small', -'psd':'image/vnd.adobe.photoshop', -'psf':'application/x-font-linux-psf', -'pskcxml':'application/pskc+xml', -'ptid':'application/vnd.pvi.ptid1', -'pub':'application/x-mspublisher', -'pvb':'application/vnd.3gpp.pic-bw-var', -'pwn':'application/vnd.3m.post-it-notes', -'pya':'audio/vnd.ms-playready.media.pya', -'pyv':'video/vnd.ms-playready.media.pyv', -'qam':'application/vnd.epson.quickanime', -'qbo':'application/vnd.intu.qbo', -'qfx':'application/vnd.intu.qfx', -'qps':'application/vnd.publishare-delta-tree', -'qt':'video/quicktime', -'qwd':'application/vnd.quark.quarkxpress', -'qwt':'application/vnd.quark.quarkxpress', -'qxb':'application/vnd.quark.quarkxpress', -'qxd':'application/vnd.quark.quarkxpress', -'qxl':'application/vnd.quark.quarkxpress', -'qxt':'application/vnd.quark.quarkxpress', -'ra':'audio/x-pn-realaudio', -'ram':'audio/x-pn-realaudio', -'rar':'application/x-rar-compressed', -'ras':'image/x-cmu-raster', -'rcprofile':'application/vnd.ipunplugged.rcprofile', -'rdf':'application/rdf+xml', -'rdz':'application/vnd.data-vision.rdz', -'rep':'application/vnd.businessobjects', -'res':'application/x-dtbresource+xml', -'rgb':'image/x-rgb', -'rif':'application/reginfo+xml', -'rip':'audio/vnd.rip', -'ris':'application/x-research-info-systems', -'rl':'application/resource-lists+xml', -'rlc':'image/vnd.fujixerox.edmics-rlc', -'rld':'application/resource-lists-diff+xml', -'rm':'application/vnd.rn-realmedia', -'rmi':'audio/midi', -'rmp':'audio/x-pn-realaudio-plugin', -'rms':'application/vnd.jcp.javame.midlet-rms', -'rmvb':'application/vnd.rn-realmedia-vbr', -'rnc':'application/relax-ng-compact-syntax', -'roa':'application/rpki-roa', -'roff':'text/troff', -'rp9':'application/vnd.cloanto.rp9', -'rpss':'application/vnd.nokia.radio-presets', -'rpst':'application/vnd.nokia.radio-preset', -'rq':'application/sparql-query', -'rs':'application/rls-services+xml', -'rsd':'application/rsd+xml', -'rss':'application/rss+xml', -'rtf':'application/rtf', -'rtx':'text/richtext', -'s':'text/x-asm', -'s3m':'audio/s3m', -'saf':'application/vnd.yamaha.smaf-audio', -'sbml':'application/sbml+xml', -'sc':'application/vnd.ibm.secure-container', -'scd':'application/x-msschedule', -'scm':'application/vnd.lotus-screencam', -'scq':'application/scvp-cv-request', -'scs':'application/scvp-cv-response', -'scurl':'text/vnd.curl.scurl', -'sda':'application/vnd.stardivision.draw', -'sdc':'application/vnd.stardivision.calc', -'sdd':'application/vnd.stardivision.impress', -'sdkd':'application/vnd.solent.sdkm+xml', -'sdkm':'application/vnd.solent.sdkm+xml', -'sdp':'application/sdp', -'sdw':'application/vnd.stardivision.writer', -'see':'application/vnd.seemail', -'seed':'application/vnd.fdsn.seed', -'sema':'application/vnd.sema', -'semd':'application/vnd.semd', -'semf':'application/vnd.semf', -'ser':'application/java-serialized-object', -'setpay':'application/set-payment-initiation', -'setreg':'application/set-registration-initiation', -'sfd-hdstx':'application/vnd.hydrostatix.sof-data', -'sfs':'application/vnd.spotfire.sfs', -'sfv':'text/x-sfv', -'sgi':'image/sgi', -'sgl':'application/vnd.stardivision.writer-global', -'sgm':'text/sgml', -'sgml':'text/sgml', -'sh':'application/x-sh', -'shar':'application/x-shar', -'shf':'application/shf+xml', -'sid':'image/x-mrsid-image', -'sig':'application/pgp-signature', -'sil':'audio/silk', -'silo':'model/mesh', -'sis':'application/vnd.symbian.install', -'sisx':'application/vnd.symbian.install', -'sit':'application/x-stuffit', -'sitx':'application/x-stuffitx', -'skd':'application/vnd.koan', -'skm':'application/vnd.koan', -'skp':'application/vnd.koan', -'skt':'application/vnd.koan', -'sldm':'application/vnd.ms-powerpoint.slide.macroenabled.12', -'sldx':'application/vnd.openxmlformats-officedocument.presentationml.slide', -'slt':'application/vnd.epson.salt', -'sm':'application/vnd.stepmania.stepchart', -'smf':'application/vnd.stardivision.math', -'smi':'application/smil+xml', -'smil':'application/smil+xml', -'smv':'video/x-smv', -'smzip':'application/vnd.stepmania.package', -'snd':'audio/basic', -'snf':'application/x-font-snf', -'so':'application/octet-stream', -'spc':'application/x-pkcs7-certificates', -'spf':'application/vnd.yamaha.smaf-phrase', -'spl':'application/x-futuresplash', -'spot':'text/vnd.in3d.spot', -'spp':'application/scvp-vp-response', -'spq':'application/scvp-vp-request', -'spx':'audio/ogg', -'sql':'application/x-sql', -'src':'application/x-wais-source', -'srt':'application/x-subrip', -'sru':'application/sru+xml', -'srx':'application/sparql-results+xml', -'ssdl':'application/ssdl+xml', -'sse':'application/vnd.kodak-descriptor', -'ssf':'application/vnd.epson.ssf', -'ssml':'application/ssml+xml', -'st':'application/vnd.sailingtracker.track', -'stc':'application/vnd.sun.xml.calc.template', -'std':'application/vnd.sun.xml.draw.template', -'stf':'application/vnd.wt.stf', -'sti':'application/vnd.sun.xml.impress.template', -'stk':'application/hyperstudio', -'stl':'application/vnd.ms-pki.stl', -'str':'application/vnd.pg.format', -'stw':'application/vnd.sun.xml.writer.template', -'sub':'text/vnd.dvb.subtitle', -'sus':'application/vnd.sus-calendar', -'susp':'application/vnd.sus-calendar', -'sv4cpio':'application/x-sv4cpio', -'sv4crc':'application/x-sv4crc', -'svc':'application/vnd.dvb.service', -'svd':'application/vnd.svd', -'svg':'image/svg+xml', -'svgz':'image/svg+xml', -'swa':'application/x-director', -'swf':'application/x-shockwave-flash', -'swi':'application/vnd.aristanetworks.swi', -'sxc':'application/vnd.sun.xml.calc', -'sxd':'application/vnd.sun.xml.draw', -'sxg':'application/vnd.sun.xml.writer.global', -'sxi':'application/vnd.sun.xml.impress', -'sxm':'application/vnd.sun.xml.math', -'sxw':'application/vnd.sun.xml.writer', -'t':'text/troff', -'t3':'application/x-t3vm-image', -'taglet':'application/vnd.mynfc', -'tao':'application/vnd.tao.intent-module-archive', -'tar':'application/x-tar', -'tcap':'application/vnd.3gpp2.tcap', -'tcl':'application/x-tcl', -'teacher':'application/vnd.smart.teacher', -'tei':'application/tei+xml', -'teicorpus':'application/tei+xml', -'tex':'application/x-tex', -'texi':'application/x-texinfo', -'texinfo':'application/x-texinfo', -'text':'text/plain', -'tfi':'application/thraud+xml', -'tfm':'application/x-tex-tfm', -'tga':'image/x-tga', -'thmx':'application/vnd.ms-officetheme', -'tif':'image/tiff', -'tiff':'image/tiff', -'tmo':'application/vnd.tmobile-livetv', -'torrent':'application/x-bittorrent', -'tpl':'application/vnd.groove-tool-template', -'tpt':'application/vnd.trid.tpt', -'tr':'text/troff', -'tra':'application/vnd.trueapp', -'trm':'application/x-msterminal', -'tsd':'application/timestamped-data', -'tsv':'text/tab-separated-values', -'ttc':'application/x-font-ttf', -'ttf':'application/x-font-ttf', -'ttl':'text/turtle', -'twd':'application/vnd.simtech-mindmapper', -'twds':'application/vnd.simtech-mindmapper', -'txd':'application/vnd.genomatix.tuxedo', -'txf':'application/vnd.mobius.txf', -'txt':'text/plain', -'u32':'application/x-authorware-bin', -'udeb':'application/x-debian-package', -'ufd':'application/vnd.ufdl', -'ufdl':'application/vnd.ufdl', -'ulx':'application/x-glulx', -'umj':'application/vnd.umajin', -'unityweb':'application/vnd.unity', -'uoml':'application/vnd.uoml+xml', -'uri':'text/uri-list', -'uris':'text/uri-list', -'urls':'text/uri-list', -'ustar':'application/x-ustar', -'utz':'application/vnd.uiq.theme', -'uu':'text/x-uuencode', -'uva':'audio/vnd.dece.audio', -'uvd':'application/vnd.dece.data', -'uvf':'application/vnd.dece.data', -'uvg':'image/vnd.dece.graphic', -'uvh':'video/vnd.dece.hd', -'uvi':'image/vnd.dece.graphic', -'uvm':'video/vnd.dece.mobile', -'uvp':'video/vnd.dece.pd', -'uvs':'video/vnd.dece.sd', -'uvt':'application/vnd.dece.ttml+xml', -'uvu':'video/vnd.uvvu.mp4', -'uvv':'video/vnd.dece.video', -'uvva':'audio/vnd.dece.audio', -'uvvd':'application/vnd.dece.data', -'uvvf':'application/vnd.dece.data', -'uvvg':'image/vnd.dece.graphic', -'uvvh':'video/vnd.dece.hd', -'uvvi':'image/vnd.dece.graphic', -'uvvm':'video/vnd.dece.mobile', -'uvvp':'video/vnd.dece.pd', -'uvvs':'video/vnd.dece.sd', -'uvvt':'application/vnd.dece.ttml+xml', -'uvvu':'video/vnd.uvvu.mp4', -'uvvv':'video/vnd.dece.video', -'uvvx':'application/vnd.dece.unspecified', -'uvvz':'application/vnd.dece.zip', -'uvx':'application/vnd.dece.unspecified', -'uvz':'application/vnd.dece.zip', -'vcard':'text/vcard', -'vcd':'application/x-cdlink', -'vcf':'text/x-vcard', -'vcg':'application/vnd.groove-vcard', -'vcs':'text/x-vcalendar', -'vcx':'application/vnd.vcx', -'vis':'application/vnd.visionary', -'viv':'video/vnd.vivo', -'vob':'video/x-ms-vob', -'vor':'application/vnd.stardivision.writer', -'vox':'application/x-authorware-bin', -'vrml':'model/vrml', -'vsd':'application/vnd.visio', -'vsf':'application/vnd.vsf', -'vss':'application/vnd.visio', -'vst':'application/vnd.visio', -'vsw':'application/vnd.visio', -'vtu':'model/vnd.vtu', -'vxml':'application/voicexml+xml', -'w3d':'application/x-director', -'wad':'application/x-doom', -'wav':'audio/x-wav', -'wax':'audio/x-ms-wax', -'wbmp':'image/vnd.wap.wbmp', -'wbs':'application/vnd.criticaltools.wbs+xml', -'wbxml':'application/vnd.wap.wbxml', -'wcm':'application/vnd.ms-works', -'wdb':'application/vnd.ms-works', -'wdp':'image/vnd.ms-photo', -'weba':'audio/webm', -'webm':'video/webm', -'webp':'image/webp', -'wg':'application/vnd.pmi.widget', -'wgt':'application/widget', -'wks':'application/vnd.ms-works', -'wm':'video/x-ms-wm', -'wma':'audio/x-ms-wma', -'wmd':'application/x-ms-wmd', -'wmf':'application/x-msmetafile', -'wml':'text/vnd.wap.wml', -'wmlc':'application/vnd.wap.wmlc', -'wmls':'text/vnd.wap.wmlscript', -'wmlsc':'application/vnd.wap.wmlscriptc', -'wmv':'video/x-ms-wmv', -'wmx':'video/x-ms-wmx', -'wmz':'application/x-ms-wmz', -'woff':'application/x-font-woff', -'wpd':'application/vnd.wordperfect', -'wpl':'application/vnd.ms-wpl', -'wps':'application/vnd.ms-works', -'wqd':'application/vnd.wqd', -'wri':'application/x-mswrite', -'wrl':'model/vrml', -'wsdl':'application/wsdl+xml', -'wspolicy':'application/wspolicy+xml', -'wtb':'application/vnd.webturbo', -'wvx':'video/x-ms-wvx', -'x32':'application/x-authorware-bin', -'x3d':'model/x3d+xml', -'x3db':'model/x3d+binary', -'x3dbz':'model/x3d+binary', -'x3dv':'model/x3d+vrml', -'x3dvz':'model/x3d+vrml', -'x3dz':'model/x3d+xml', -'xaml':'application/xaml+xml', -'xap':'application/x-silverlight-app', -'xar':'application/vnd.xara', -'xbap':'application/x-ms-xbap', -'xbd':'application/vnd.fujixerox.docuworks.binder', -'xbm':'image/x-xbitmap', -'xdf':'application/xcap-diff+xml', -'xdm':'application/vnd.syncml.dm+xml', -'xdp':'application/vnd.adobe.xdp+xml', -'xdssc':'application/dssc+xml', -'xdw':'application/vnd.fujixerox.docuworks', -'xenc':'application/xenc+xml', -'xer':'application/patch-ops-error+xml', -'xfdf':'application/vnd.adobe.xfdf', -'xfdl':'application/vnd.xfdl', -'xht':'application/xhtml+xml', -'xhtml':'application/xhtml+xml', -'xhvml':'application/xv+xml', -'xif':'image/vnd.xiff', -'xla':'application/vnd.ms-excel', -'xlam':'application/vnd.ms-excel.addin.macroenabled.12', -'xlc':'application/vnd.ms-excel', -'xlf':'application/x-xliff+xml', -'xlm':'application/vnd.ms-excel', -'xls':'application/vnd.ms-excel', -'xlsb':'application/vnd.ms-excel.sheet.binary.macroenabled.12', -'xlsm':'application/vnd.ms-excel.sheet.macroenabled.12', -'xlsx':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', -'xlt':'application/vnd.ms-excel', -'xltm':'application/vnd.ms-excel.template.macroenabled.12', -'xltx':'application/vnd.openxmlformats-officedocument.spreadsheetml.template', -'xlw':'application/vnd.ms-excel', -'xm':'audio/xm', -'xml':'application/xml', -'xo':'application/vnd.olpc-sugar', -'xop':'application/xop+xml', -'xpi':'application/x-xpinstall', -'xpl':'application/xproc+xml', -'xpm':'image/x-xpixmap', -'xpr':'application/vnd.is-xpr', -'xps':'application/vnd.ms-xpsdocument', -'xpw':'application/vnd.intercon.formnet', -'xpx':'application/vnd.intercon.formnet', -'xsl':'application/xml', -'xslt':'application/xslt+xml', -'xsm':'application/vnd.syncml+xml', -'xspf':'application/xspf+xml', -'xul':'application/vnd.mozilla.xul+xml', -'xvm':'application/xv+xml', -'xvml':'application/xv+xml', -'xwd':'image/x-xwindowdump', -'xyz':'chemical/x-xyz', -'xz':'application/x-xz', -'yang':'application/yang', -'yin':'application/yin+xml', -'z1':'application/x-zmachine', -'z2':'application/x-zmachine', -'z3':'application/x-zmachine', -'z4':'application/x-zmachine', -'z5':'application/x-zmachine', -'z6':'application/x-zmachine', -'z7':'application/x-zmachine', -'z8':'application/x-zmachine', -'zaz':'application/vnd.zzazz.deck+xml', -'zip':'application/zip', -'zir':'application/vnd.zul', -'zirz':'application/vnd.zul', -'zmm':'application/vnd.handheld-entertainment+xml', + '123': 'application/vnd.lotus-1-2-3', + '3dml': 'text/vnd.in3d.3dml', + '3ds': 'image/x-3ds', + '3g2': 'video/3gpp2', + '3gp': 'video/3gpp', + '7z': 'application/x-7z-compressed', + 'aab': 'application/x-authorware-bin', + 'aac': 'audio/x-aac', + 'aam': 'application/x-authorware-map', + 'aas': 'application/x-authorware-seg', + 'abw': 'application/x-abiword', + 'ac': 'application/pkix-attr-cert', + 'acc': 'application/vnd.americandynamics.acc', + 'ace': 'application/x-ace-compressed', + 'acu': 'application/vnd.acucobol', + 'acutc': 'application/vnd.acucorp', + 'adp': 'audio/adpcm', + 'aep': 'application/vnd.audiograph', + 'afm': 'application/x-font-type1', + 'afp': 'application/vnd.ibm.modcap', + 'ahead': 'application/vnd.ahead.space', + 'ai': 'application/postscript', + 'aif': 'audio/x-aiff', + 'aifc': 'audio/x-aiff', + 'aiff': 'audio/x-aiff', + 'air': 'application/vnd.adobe.air-application-installer-package+zip', + 'ait': 'application/vnd.dvb.ait', + 'ami': 'application/vnd.amiga.ami', + 'apk': 'application/vnd.android.package-archive', + 'appcache': 'text/cache-manifest', + 'application': 'application/x-ms-application', + 'apr': 'application/vnd.lotus-approach', + 'arc': 'application/x-freearc', + 'asc': 'application/pgp-signature', + 'asf': 'video/x-ms-asf', + 'asm': 'text/x-asm', + 'aso': 'application/vnd.accpac.simply.aso', + 'asx': 'video/x-ms-asf', + 'atc': 'application/vnd.acucorp', + 'atom': 'application/atom+xml', + 'atomcat': 'application/atomcat+xml', + 'atomsvc': 'application/atomsvc+xml', + 'atx': 'application/vnd.antix.game-component', + 'au': 'audio/basic', + 'avi': 'video/x-msvideo', + 'aw': 'application/applixware', + 'azf': 'application/vnd.airzip.filesecure.azf', + 'azs': 'application/vnd.airzip.filesecure.azs', + 'azw': 'application/vnd.amazon.ebook', + 'bat': 'application/x-msdownload', + 'bcpio': 'application/x-bcpio', + 'bdf': 'application/x-font-bdf', + 'bdm': 'application/vnd.syncml.dm+wbxml', + 'bed': 'application/vnd.realvnc.bed', + 'bh2': 'application/vnd.fujitsu.oasysprs', + 'bin': 'application/octet-stream', + 'blb': 'application/x-blorb', + 'blorb': 'application/x-blorb', + 'bmi': 'application/vnd.bmi', + 'bmp': 'image/bmp', + 'book': 'application/vnd.framemaker', + 'box': 'application/vnd.previewsystems.box', + 'boz': 'application/x-bzip2', + 'bpk': 'application/octet-stream', + 'btif': 'image/prs.btif', + 'bz': 'application/x-bzip', + 'bz2': 'application/x-bzip2', + 'c': 'text/x-c', + 'c11amc': 'application/vnd.cluetrust.cartomobile-config', + 'c11amz': 'application/vnd.cluetrust.cartomobile-config-pkg', + 'c4d': 'application/vnd.clonk.c4group', + 'c4f': 'application/vnd.clonk.c4group', + 'c4g': 'application/vnd.clonk.c4group', + 'c4p': 'application/vnd.clonk.c4group', + 'c4u': 'application/vnd.clonk.c4group', + 'cab': 'application/vnd.ms-cab-compressed', + 'caf': 'audio/x-caf', + 'cap': 'application/vnd.tcpdump.pcap', + 'car': 'application/vnd.curl.car', + 'cat': 'application/vnd.ms-pki.seccat', + 'cb7': 'application/x-cbr', + 'cba': 'application/x-cbr', + 'cbr': 'application/x-cbr', + 'cbt': 'application/x-cbr', + 'cbz': 'application/x-cbr', + 'cc': 'text/x-c', + 'cct': 'application/x-director', + 'ccxml': 'application/ccxml+xml', + 'cdbcmsg': 'application/vnd.contact.cmsg', + 'cdf': 'application/x-netcdf', + 'cdkey': 'application/vnd.mediastation.cdkey', + 'cdmia': 'application/cdmi-capability', + 'cdmic': 'application/cdmi-container', + 'cdmid': 'application/cdmi-domain', + 'cdmio': 'application/cdmi-object', + 'cdmiq': 'application/cdmi-queue', + 'cdx': 'chemical/x-cdx', + 'cdxml': 'application/vnd.chemdraw+xml', + 'cdy': 'application/vnd.cinderella', + 'cer': 'application/pkix-cert', + 'cfs': 'application/x-cfs-compressed', + 'cgm': 'image/cgm', + 'chat': 'application/x-chat', + 'chm': 'application/vnd.ms-htmlhelp', + 'chrt': 'application/vnd.kde.kchart', + 'cif': 'chemical/x-cif', + 'cii': 'application/vnd.anser-web-certificate-issue-initiation', + 'cil': 'application/vnd.ms-artgalry', + 'cla': 'application/vnd.claymore', + 'class': 'application/java-vm', + 'clkk': 'application/vnd.crick.clicker.keyboard', + 'clkp': 'application/vnd.crick.clicker.palette', + 'clkt': 'application/vnd.crick.clicker.template', + 'clkw': 'application/vnd.crick.clicker.wordbank', + 'clkx': 'application/vnd.crick.clicker', + 'clp': 'application/x-msclip', + 'cmc': 'application/vnd.cosmocaller', + 'cmdf': 'chemical/x-cmdf', + 'cml': 'chemical/x-cml', + 'cmp': 'application/vnd.yellowriver-custom-menu', + 'cmx': 'image/x-cmx', + 'cod': 'application/vnd.rim.cod', + 'com': 'application/x-msdownload', + 'conf': 'text/plain', + 'cpio': 'application/x-cpio', + 'cpp': 'text/x-c', + 'cpt': 'application/mac-compactpro', + 'crd': 'application/x-mscardfile', + 'crl': 'application/pkix-crl', + 'crt': 'application/x-x509-ca-cert', + 'cryptonote': 'application/vnd.rig.cryptonote', + 'csh': 'application/x-csh', + 'csml': 'chemical/x-csml', + 'csp': 'application/vnd.commonspace', + 'css': 'text/css', + 'cst': 'application/x-director', + 'csv': 'text/csv', + 'cu': 'application/cu-seeme', + 'curl': 'text/vnd.curl', + 'cww': 'application/prs.cww', + 'cxt': 'application/x-director', + 'cxx': 'text/x-c', + 'dae': 'model/vnd.collada+xml', + 'daf': 'application/vnd.mobius.daf', + 'dart': 'application/dart', + 'dataless': 'application/vnd.fdsn.seed', + 'davmount': 'application/davmount+xml', + 'dbk': 'application/docbook+xml', + 'dcr': 'application/x-director', + 'dcurl': 'text/vnd.curl.dcurl', + 'dd2': 'application/vnd.oma.dd2+xml', + 'ddd': 'application/vnd.fujixerox.ddd', + 'deb': 'application/x-debian-package', + 'def': 'text/plain', + 'deploy': 'application/octet-stream', + 'der': 'application/x-x509-ca-cert', + 'dfac': 'application/vnd.dreamfactory', + 'dgc': 'application/x-dgc-compressed', + 'dic': 'text/x-c', + 'dir': 'application/x-director', + 'dis': 'application/vnd.mobius.dis', + 'dist': 'application/octet-stream', + 'distz': 'application/octet-stream', + 'djv': 'image/vnd.djvu', + 'djvu': 'image/vnd.djvu', + 'dll': 'application/x-msdownload', + 'dmg': 'application/x-apple-diskimage', + 'dmp': 'application/vnd.tcpdump.pcap', + 'dms': 'application/octet-stream', + 'dna': 'application/vnd.dna', + 'doc': 'application/msword', + 'docm': 'application/vnd.ms-word.document.macroenabled.12', + 'docx': + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dot': 'application/msword', + 'dotm': 'application/vnd.ms-word.template.macroenabled.12', + 'dotx': + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'dp': 'application/vnd.osgi.dp', + 'dpg': 'application/vnd.dpgraph', + 'dra': 'audio/vnd.dra', + 'dsc': 'text/prs.lines.tag', + 'dssc': 'application/dssc+der', + 'dtb': 'application/x-dtbook+xml', + 'dtd': 'application/xml-dtd', + 'dts': 'audio/vnd.dts', + 'dtshd': 'audio/vnd.dts.hd', + 'dump': 'application/octet-stream', + 'dvb': 'video/vnd.dvb.file', + 'dvi': 'application/x-dvi', + 'dwf': 'model/vnd.dwf', + 'dwg': 'image/vnd.dwg', + 'dxf': 'image/vnd.dxf', + 'dxp': 'application/vnd.spotfire.dxp', + 'dxr': 'application/x-director', + 'ecelp4800': 'audio/vnd.nuera.ecelp4800', + 'ecelp7470': 'audio/vnd.nuera.ecelp7470', + 'ecelp9600': 'audio/vnd.nuera.ecelp9600', + 'ecma': 'application/ecmascript', + 'edm': 'application/vnd.novadigm.edm', + 'edx': 'application/vnd.novadigm.edx', + 'efif': 'application/vnd.picsel', + 'ei6': 'application/vnd.pg.osasli', + 'elc': 'application/octet-stream', + 'emf': 'application/x-msmetafile', + 'eml': 'message/rfc822', + 'emma': 'application/emma+xml', + 'emz': 'application/x-msmetafile', + 'eol': 'audio/vnd.digital-winds', + 'eot': 'application/vnd.ms-fontobject', + 'eps': 'application/postscript', + 'epub': 'application/epub+zip', + 'es3': 'application/vnd.eszigno3+xml', + 'esa': 'application/vnd.osgi.subsystem', + 'esf': 'application/vnd.epson.esf', + 'et3': 'application/vnd.eszigno3+xml', + 'etx': 'text/x-setext', + 'eva': 'application/x-eva', + 'evy': 'application/x-envoy', + 'exe': 'application/x-msdownload', + 'exi': 'application/exi', + 'ext': 'application/vnd.novadigm.ext', + 'ez': 'application/andrew-inset', + 'ez2': 'application/vnd.ezpix-album', + 'ez3': 'application/vnd.ezpix-package', + 'f': 'text/x-fortran', + 'f4v': 'video/x-f4v', + 'f77': 'text/x-fortran', + 'f90': 'text/x-fortran', + 'fbs': 'image/vnd.fastbidsheet', + 'fcdt': 'application/vnd.adobe.formscentral.fcdt', + 'fcs': 'application/vnd.isac.fcs', + 'fdf': 'application/vnd.fdf', + 'fe_launch': 'application/vnd.denovo.fcselayout-link', + 'fg5': 'application/vnd.fujitsu.oasysgp', + 'fgd': 'application/x-director', + 'fh': 'image/x-freehand', + 'fh4': 'image/x-freehand', + 'fh5': 'image/x-freehand', + 'fh7': 'image/x-freehand', + 'fhc': 'image/x-freehand', + 'fig': 'application/x-xfig', + 'flac': 'audio/x-flac', + 'fli': 'video/x-fli', + 'flo': 'application/vnd.micrografx.flo', + 'flv': 'video/x-flv', + 'flw': 'application/vnd.kde.kivio', + 'flx': 'text/vnd.fmi.flexstor', + 'fly': 'text/vnd.fly', + 'fm': 'application/vnd.framemaker', + 'fnc': 'application/vnd.frogans.fnc', + 'for': 'text/x-fortran', + 'fpx': 'image/vnd.fpx', + 'frame': 'application/vnd.framemaker', + 'fsc': 'application/vnd.fsc.weblaunch', + 'fst': 'image/vnd.fst', + 'ftc': 'application/vnd.fluxtime.clip', + 'fti': 'application/vnd.anser-web-funds-transfer-initiation', + 'fvt': 'video/vnd.fvt', + 'fxp': 'application/vnd.adobe.fxp', + 'fxpl': 'application/vnd.adobe.fxp', + 'fzs': 'application/vnd.fuzzysheet', + 'g2w': 'application/vnd.geoplan', + 'g3': 'image/g3fax', + 'g3w': 'application/vnd.geospace', + 'gac': 'application/vnd.groove-account', + 'gam': 'application/x-tads', + 'gbr': 'application/rpki-ghostbusters', + 'gca': 'application/x-gca-compressed', + 'gdl': 'model/vnd.gdl', + 'geo': 'application/vnd.dynageo', + 'gex': 'application/vnd.geometry-explorer', + 'ggb': 'application/vnd.geogebra.file', + 'ggt': 'application/vnd.geogebra.tool', + 'ghf': 'application/vnd.groove-help', + 'gif': 'image/gif', + 'gim': 'application/vnd.groove-identity-message', + 'gml': 'application/gml+xml', + 'gmx': 'application/vnd.gmx', + 'gnumeric': 'application/x-gnumeric', + 'gph': 'application/vnd.flographit', + 'gpx': 'application/gpx+xml', + 'gqf': 'application/vnd.grafeq', + 'gqs': 'application/vnd.grafeq', + 'gram': 'application/srgs', + 'gramps': 'application/x-gramps-xml', + 'gre': 'application/vnd.geometry-explorer', + 'grv': 'application/vnd.groove-injector', + 'grxml': 'application/srgs+xml', + 'gsf': 'application/x-font-ghostscript', + 'gtar': 'application/x-gtar', + 'gtm': 'application/vnd.groove-tool-message', + 'gtw': 'model/vnd.gtw', + 'gv': 'text/vnd.graphviz', + 'gxf': 'application/gxf', + 'gxt': 'application/vnd.geonext', + 'h': 'text/x-c', + 'h261': 'video/h261', + 'h263': 'video/h263', + 'h264': 'video/h264', + 'hal': 'application/vnd.hal+xml', + 'hbci': 'application/vnd.hbci', + 'hdf': 'application/x-hdf', + 'hh': 'text/x-c', + 'hlp': 'application/winhlp', + 'hpgl': 'application/vnd.hp-hpgl', + 'hpid': 'application/vnd.hp-hpid', + 'hps': 'application/vnd.hp-hps', + 'hqx': 'application/mac-binhex40', + 'htke': 'application/vnd.kenameaapp', + 'htm': 'text/html', + 'html': 'text/html', + 'hvd': 'application/vnd.yamaha.hv-dic', + 'hvp': 'application/vnd.yamaha.hv-voice', + 'hvs': 'application/vnd.yamaha.hv-script', + 'i2g': 'application/vnd.intergeo', + 'icc': 'application/vnd.iccprofile', + 'ice': 'x-conference/x-cooltalk', + 'icm': 'application/vnd.iccprofile', + 'ico': 'image/x-icon', + 'ics': 'text/calendar', + 'ief': 'image/ief', + 'ifb': 'text/calendar', + 'ifm': 'application/vnd.shana.informed.formdata', + 'iges': 'model/iges', + 'igl': 'application/vnd.igloader', + 'igm': 'application/vnd.insors.igm', + 'igs': 'model/iges', + 'igx': 'application/vnd.micrografx.igx', + 'iif': 'application/vnd.shana.informed.interchange', + 'imp': 'application/vnd.accpac.simply.imp', + 'ims': 'application/vnd.ms-ims', + 'in': 'text/plain', + 'ink': 'application/inkml+xml', + 'inkml': 'application/inkml+xml', + 'install': 'application/x-install-instructions', + 'iota': 'application/vnd.astraea-software.iota', + 'ipfix': 'application/ipfix', + 'ipk': 'application/vnd.shana.informed.package', + 'irm': 'application/vnd.ibm.rights-management', + 'irp': 'application/vnd.irepository.package+xml', + 'iso': 'application/x-iso9660-image', + 'itp': 'application/vnd.shana.informed.formtemplate', + 'ivp': 'application/vnd.immervision-ivp', + 'ivu': 'application/vnd.immervision-ivu', + 'jad': 'text/vnd.sun.j2me.app-descriptor', + 'jam': 'application/vnd.jam', + 'jar': 'application/java-archive', + 'java': 'text/x-java-source', + 'jisp': 'application/vnd.jisp', + 'jlt': 'application/vnd.hp-jlyt', + 'jnlp': 'application/x-java-jnlp-file', + 'joda': 'application/vnd.joost.joda-archive', + 'jpe': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'jpg': 'image/jpeg', + 'jpgm': 'video/jpm', + 'jpgv': 'video/jpeg', + 'jpm': 'video/jpm', + 'js': 'application/javascript', + 'json': 'application/json', + 'jsonml': 'application/jsonml+json', + 'kar': 'audio/midi', + 'karbon': 'application/vnd.kde.karbon', + 'kfo': 'application/vnd.kde.kformula', + 'kia': 'application/vnd.kidspiration', + 'kml': 'application/vnd.google-earth.kml+xml', + 'kmz': 'application/vnd.google-earth.kmz', + 'kne': 'application/vnd.kinar', + 'knp': 'application/vnd.kinar', + 'kon': 'application/vnd.kde.kontour', + 'kpr': 'application/vnd.kde.kpresenter', + 'kpt': 'application/vnd.kde.kpresenter', + 'kpxx': 'application/vnd.ds-keypoint', + 'ksp': 'application/vnd.kde.kspread', + 'ktr': 'application/vnd.kahootz', + 'ktx': 'image/ktx', + 'ktz': 'application/vnd.kahootz', + 'kwd': 'application/vnd.kde.kword', + 'kwt': 'application/vnd.kde.kword', + 'lasxml': 'application/vnd.las.las+xml', + 'latex': 'application/x-latex', + 'lbd': 'application/vnd.llamagraphics.life-balance.desktop', + 'lbe': 'application/vnd.llamagraphics.life-balance.exchange+xml', + 'les': 'application/vnd.hhe.lesson-player', + 'lha': 'application/x-lzh-compressed', + 'link66': 'application/vnd.route66.link66+xml', + 'list': 'text/plain', + 'list3820': 'application/vnd.ibm.modcap', + 'listafp': 'application/vnd.ibm.modcap', + 'lnk': 'application/x-ms-shortcut', + 'log': 'text/plain', + 'lostxml': 'application/lost+xml', + 'lrf': 'application/octet-stream', + 'lrm': 'application/vnd.ms-lrm', + 'ltf': 'application/vnd.frogans.ltf', + 'lvp': 'audio/vnd.lucent.voice', + 'lwp': 'application/vnd.lotus-wordpro', + 'lzh': 'application/x-lzh-compressed', + 'm13': 'application/x-msmediaview', + 'm14': 'application/x-msmediaview', + 'm1v': 'video/mpeg', + 'm21': 'application/mp21', + 'm2a': 'audio/mpeg', + 'm2v': 'video/mpeg', + 'm3a': 'audio/mpeg', + 'm3u': 'audio/x-mpegurl', + 'm3u8': 'application/vnd.apple.mpegurl', + 'm4u': 'video/vnd.mpegurl', + 'm4v': 'video/x-m4v', + 'ma': 'application/mathematica', + 'mads': 'application/mads+xml', + 'mag': 'application/vnd.ecowin.chart', + 'maker': 'application/vnd.framemaker', + 'man': 'text/troff', + 'mar': 'application/octet-stream', + 'mathml': 'application/mathml+xml', + 'mb': 'application/mathematica', + 'mbk': 'application/vnd.mobius.mbk', + 'mbox': 'application/mbox', + 'mc1': 'application/vnd.medcalcdata', + 'mcd': 'application/vnd.mcd', + 'mcurl': 'text/vnd.curl.mcurl', + 'mdb': 'application/x-msaccess', + 'mdi': 'image/vnd.ms-modi', + 'me': 'text/troff', + 'mesh': 'model/mesh', + 'meta4': 'application/metalink4+xml', + 'metalink': 'application/metalink+xml', + 'mets': 'application/mets+xml', + 'mfm': 'application/vnd.mfmp', + 'mft': 'application/rpki-manifest', + 'mgp': 'application/vnd.osgeo.mapguide.package', + 'mgz': 'application/vnd.proteus.magazine', + 'mid': 'audio/midi', + 'midi': 'audio/midi', + 'mie': 'application/x-mie', + 'mif': 'application/vnd.mif', + 'mime': 'message/rfc822', + 'mj2': 'video/mj2', + 'mjp2': 'video/mj2', + 'mk3d': 'video/x-matroska', + 'mka': 'audio/x-matroska', + 'mks': 'video/x-matroska', + 'mkv': 'video/x-matroska', + 'mlp': 'application/vnd.dolby.mlp', + 'mmd': 'application/vnd.chipnuts.karaoke-mmd', + 'mmf': 'application/vnd.smaf', + 'mmr': 'image/vnd.fujixerox.edmics-mmr', + 'mng': 'video/x-mng', + 'mny': 'application/x-msmoney', + 'mobi': 'application/x-mobipocket-ebook', + 'mods': 'application/mods+xml', + 'mov': 'video/quicktime', + 'movie': 'video/x-sgi-movie', + 'mp2': 'audio/mpeg', + 'mp21': 'application/mp21', + 'mp2a': 'audio/mpeg', + 'mp3': 'audio/mpeg', + 'mp4': 'video/mp4', + 'mp4a': 'audio/mp4', + 'mp4s': 'application/mp4', + 'mp4v': 'video/mp4', + 'mpc': 'application/vnd.mophun.certificate', + 'mpe': 'video/mpeg', + 'mpeg': 'video/mpeg', + 'mpg': 'video/mpeg', + 'mpg4': 'video/mp4', + 'mpga': 'audio/mpeg', + 'mpkg': 'application/vnd.apple.installer+xml', + 'mpm': 'application/vnd.blueice.multipass', + 'mpn': 'application/vnd.mophun.application', + 'mpp': 'application/vnd.ms-project', + 'mpt': 'application/vnd.ms-project', + 'mpy': 'application/vnd.ibm.minipay', + 'mqy': 'application/vnd.mobius.mqy', + 'mrc': 'application/marc', + 'mrcx': 'application/marcxml+xml', + 'ms': 'text/troff', + 'mscml': 'application/mediaservercontrol+xml', + 'mseed': 'application/vnd.fdsn.mseed', + 'mseq': 'application/vnd.mseq', + 'msf': 'application/vnd.epson.msf', + 'msh': 'model/mesh', + 'msi': 'application/x-msdownload', + 'msl': 'application/vnd.mobius.msl', + 'msty': 'application/vnd.muvee.style', + 'mts': 'model/vnd.mts', + 'mus': 'application/vnd.musician', + 'musicxml': 'application/vnd.recordare.musicxml+xml', + 'mvb': 'application/x-msmediaview', + 'mwf': 'application/vnd.mfer', + 'mxf': 'application/mxf', + 'mxl': 'application/vnd.recordare.musicxml', + 'mxml': 'application/xv+xml', + 'mxs': 'application/vnd.triscape.mxs', + 'mxu': 'video/vnd.mpegurl', + 'n-gage': 'application/vnd.nokia.n-gage.symbian.install', + 'n3': 'text/n3', + 'nb': 'application/mathematica', + 'nbp': 'application/vnd.wolfram.player', + 'nc': 'application/x-netcdf', + 'ncx': 'application/x-dtbncx+xml', + 'nfo': 'text/x-nfo', + 'ngdat': 'application/vnd.nokia.n-gage.data', + 'nitf': 'application/vnd.nitf', + 'nlu': 'application/vnd.neurolanguage.nlu', + 'nml': 'application/vnd.enliven', + 'nnd': 'application/vnd.noblenet-directory', + 'nns': 'application/vnd.noblenet-sealer', + 'nnw': 'application/vnd.noblenet-web', + 'npx': 'image/vnd.net-fpx', + 'nsc': 'application/x-conference', + 'nsf': 'application/vnd.lotus-notes', + 'ntf': 'application/vnd.nitf', + 'nzb': 'application/x-nzb', + 'oa2': 'application/vnd.fujitsu.oasys2', + 'oa3': 'application/vnd.fujitsu.oasys3', + 'oas': 'application/vnd.fujitsu.oasys', + 'obd': 'application/x-msbinder', + 'obj': 'application/x-tgif', + 'oda': 'application/oda', + 'odb': 'application/vnd.oasis.opendocument.database', + 'odc': 'application/vnd.oasis.opendocument.chart', + 'odf': 'application/vnd.oasis.opendocument.formula', + 'odft': 'application/vnd.oasis.opendocument.formula-template', + 'odg': 'application/vnd.oasis.opendocument.graphics', + 'odi': 'application/vnd.oasis.opendocument.image', + 'odm': 'application/vnd.oasis.opendocument.text-master', + 'odp': 'application/vnd.oasis.opendocument.presentation', + 'ods': 'application/vnd.oasis.opendocument.spreadsheet', + 'odt': 'application/vnd.oasis.opendocument.text', + 'oga': 'audio/ogg', + 'ogg': 'audio/ogg', + 'ogv': 'video/ogg', + 'ogx': 'application/ogg', + 'omdoc': 'application/omdoc+xml', + 'onepkg': 'application/onenote', + 'onetmp': 'application/onenote', + 'onetoc': 'application/onenote', + 'onetoc2': 'application/onenote', + 'opf': 'application/oebps-package+xml', + 'opml': 'text/x-opml', + 'oprc': 'application/vnd.palm', + 'org': 'application/vnd.lotus-organizer', + 'osf': 'application/vnd.yamaha.openscoreformat', + 'osfpvg': 'application/vnd.yamaha.openscoreformat.osfpvg+xml', + 'otc': 'application/vnd.oasis.opendocument.chart-template', + 'otf': 'application/x-font-otf', + 'otg': 'application/vnd.oasis.opendocument.graphics-template', + 'oth': 'application/vnd.oasis.opendocument.text-web', + 'oti': 'application/vnd.oasis.opendocument.image-template', + 'otp': 'application/vnd.oasis.opendocument.presentation-template', + 'ots': 'application/vnd.oasis.opendocument.spreadsheet-template', + 'ott': 'application/vnd.oasis.opendocument.text-template', + 'oxps': 'application/oxps', + 'oxt': 'application/vnd.openofficeorg.extension', + 'p': 'text/x-pascal', + 'p10': 'application/pkcs10', + 'p12': 'application/x-pkcs12', + 'p7b': 'application/x-pkcs7-certificates', + 'p7c': 'application/pkcs7-mime', + 'p7m': 'application/pkcs7-mime', + 'p7r': 'application/x-pkcs7-certreqresp', + 'p7s': 'application/pkcs7-signature', + 'p8': 'application/pkcs8', + 'pas': 'text/x-pascal', + 'paw': 'application/vnd.pawaafile', + 'pbd': 'application/vnd.powerbuilder6', + 'pbm': 'image/x-portable-bitmap', + 'pcap': 'application/vnd.tcpdump.pcap', + 'pcf': 'application/x-font-pcf', + 'pcl': 'application/vnd.hp-pcl', + 'pclxl': 'application/vnd.hp-pclxl', + 'pct': 'image/x-pict', + 'pcurl': 'application/vnd.curl.pcurl', + 'pcx': 'image/x-pcx', + 'pdb': 'application/vnd.palm', + 'pdf': 'application/pdf', + 'pfa': 'application/x-font-type1', + 'pfb': 'application/x-font-type1', + 'pfm': 'application/x-font-type1', + 'pfr': 'application/font-tdpfr', + 'pfx': 'application/x-pkcs12', + 'pgm': 'image/x-portable-graymap', + 'pgn': 'application/x-chess-pgn', + 'pgp': 'application/pgp-encrypted', + 'pic': 'image/x-pict', + 'pkg': 'application/octet-stream', + 'pki': 'application/pkixcmp', + 'pkipath': 'application/pkix-pkipath', + 'plb': 'application/vnd.3gpp.pic-bw-large', + 'plc': 'application/vnd.mobius.plc', + 'plf': 'application/vnd.pocketlearn', + 'pls': 'application/pls+xml', + 'pml': 'application/vnd.ctc-posml', + 'png': 'image/png', + 'pnm': 'image/x-portable-anymap', + 'portpkg': 'application/vnd.macports.portpkg', + 'pot': 'application/vnd.ms-powerpoint', + 'potm': 'application/vnd.ms-powerpoint.template.macroenabled.12', + 'potx': + 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppam': 'application/vnd.ms-powerpoint.addin.macroenabled.12', + 'ppd': 'application/vnd.cups-ppd', + 'ppm': 'image/x-portable-pixmap', + 'pps': 'application/vnd.ms-powerpoint', + 'ppsm': 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', + 'ppsx': + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'ppt': 'application/vnd.ms-powerpoint', + 'pptm': 'application/vnd.ms-powerpoint.presentation.macroenabled.12', + 'pptx': + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'pqa': 'application/vnd.palm', + 'prc': 'application/x-mobipocket-ebook', + 'pre': 'application/vnd.lotus-freelance', + 'prf': 'application/pics-rules', + 'ps': 'application/postscript', + 'psb': 'application/vnd.3gpp.pic-bw-small', + 'psd': 'image/vnd.adobe.photoshop', + 'psf': 'application/x-font-linux-psf', + 'pskcxml': 'application/pskc+xml', + 'ptid': 'application/vnd.pvi.ptid1', + 'pub': 'application/x-mspublisher', + 'pvb': 'application/vnd.3gpp.pic-bw-var', + 'pwn': 'application/vnd.3m.post-it-notes', + 'pya': 'audio/vnd.ms-playready.media.pya', + 'pyv': 'video/vnd.ms-playready.media.pyv', + 'qam': 'application/vnd.epson.quickanime', + 'qbo': 'application/vnd.intu.qbo', + 'qfx': 'application/vnd.intu.qfx', + 'qps': 'application/vnd.publishare-delta-tree', + 'qt': 'video/quicktime', + 'qwd': 'application/vnd.quark.quarkxpress', + 'qwt': 'application/vnd.quark.quarkxpress', + 'qxb': 'application/vnd.quark.quarkxpress', + 'qxd': 'application/vnd.quark.quarkxpress', + 'qxl': 'application/vnd.quark.quarkxpress', + 'qxt': 'application/vnd.quark.quarkxpress', + 'ra': 'audio/x-pn-realaudio', + 'ram': 'audio/x-pn-realaudio', + 'rar': 'application/x-rar-compressed', + 'ras': 'image/x-cmu-raster', + 'rcprofile': 'application/vnd.ipunplugged.rcprofile', + 'rdf': 'application/rdf+xml', + 'rdz': 'application/vnd.data-vision.rdz', + 'rep': 'application/vnd.businessobjects', + 'res': 'application/x-dtbresource+xml', + 'rgb': 'image/x-rgb', + 'rif': 'application/reginfo+xml', + 'rip': 'audio/vnd.rip', + 'ris': 'application/x-research-info-systems', + 'rl': 'application/resource-lists+xml', + 'rlc': 'image/vnd.fujixerox.edmics-rlc', + 'rld': 'application/resource-lists-diff+xml', + 'rm': 'application/vnd.rn-realmedia', + 'rmi': 'audio/midi', + 'rmp': 'audio/x-pn-realaudio-plugin', + 'rms': 'application/vnd.jcp.javame.midlet-rms', + 'rmvb': 'application/vnd.rn-realmedia-vbr', + 'rnc': 'application/relax-ng-compact-syntax', + 'roa': 'application/rpki-roa', + 'roff': 'text/troff', + 'rp9': 'application/vnd.cloanto.rp9', + 'rpss': 'application/vnd.nokia.radio-presets', + 'rpst': 'application/vnd.nokia.radio-preset', + 'rq': 'application/sparql-query', + 'rs': 'application/rls-services+xml', + 'rsd': 'application/rsd+xml', + 'rss': 'application/rss+xml', + 'rtf': 'application/rtf', + 'rtx': 'text/richtext', + 's': 'text/x-asm', + 's3m': 'audio/s3m', + 'saf': 'application/vnd.yamaha.smaf-audio', + 'sbml': 'application/sbml+xml', + 'sc': 'application/vnd.ibm.secure-container', + 'scd': 'application/x-msschedule', + 'scm': 'application/vnd.lotus-screencam', + 'scq': 'application/scvp-cv-request', + 'scs': 'application/scvp-cv-response', + 'scurl': 'text/vnd.curl.scurl', + 'sda': 'application/vnd.stardivision.draw', + 'sdc': 'application/vnd.stardivision.calc', + 'sdd': 'application/vnd.stardivision.impress', + 'sdkd': 'application/vnd.solent.sdkm+xml', + 'sdkm': 'application/vnd.solent.sdkm+xml', + 'sdp': 'application/sdp', + 'sdw': 'application/vnd.stardivision.writer', + 'see': 'application/vnd.seemail', + 'seed': 'application/vnd.fdsn.seed', + 'sema': 'application/vnd.sema', + 'semd': 'application/vnd.semd', + 'semf': 'application/vnd.semf', + 'ser': 'application/java-serialized-object', + 'setpay': 'application/set-payment-initiation', + 'setreg': 'application/set-registration-initiation', + 'sfd-hdstx': 'application/vnd.hydrostatix.sof-data', + 'sfs': 'application/vnd.spotfire.sfs', + 'sfv': 'text/x-sfv', + 'sgi': 'image/sgi', + 'sgl': 'application/vnd.stardivision.writer-global', + 'sgm': 'text/sgml', + 'sgml': 'text/sgml', + 'sh': 'application/x-sh', + 'shar': 'application/x-shar', + 'shf': 'application/shf+xml', + 'sid': 'image/x-mrsid-image', + 'sig': 'application/pgp-signature', + 'sil': 'audio/silk', + 'silo': 'model/mesh', + 'sis': 'application/vnd.symbian.install', + 'sisx': 'application/vnd.symbian.install', + 'sit': 'application/x-stuffit', + 'sitx': 'application/x-stuffitx', + 'skd': 'application/vnd.koan', + 'skm': 'application/vnd.koan', + 'skp': 'application/vnd.koan', + 'skt': 'application/vnd.koan', + 'sldm': 'application/vnd.ms-powerpoint.slide.macroenabled.12', + 'sldx': 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'slt': 'application/vnd.epson.salt', + 'sm': 'application/vnd.stepmania.stepchart', + 'smf': 'application/vnd.stardivision.math', + 'smi': 'application/smil+xml', + 'smil': 'application/smil+xml', + 'smv': 'video/x-smv', + 'smzip': 'application/vnd.stepmania.package', + 'snd': 'audio/basic', + 'snf': 'application/x-font-snf', + 'so': 'application/octet-stream', + 'spc': 'application/x-pkcs7-certificates', + 'spf': 'application/vnd.yamaha.smaf-phrase', + 'spl': 'application/x-futuresplash', + 'spot': 'text/vnd.in3d.spot', + 'spp': 'application/scvp-vp-response', + 'spq': 'application/scvp-vp-request', + 'spx': 'audio/ogg', + 'sql': 'application/x-sql', + 'src': 'application/x-wais-source', + 'srt': 'application/x-subrip', + 'sru': 'application/sru+xml', + 'srx': 'application/sparql-results+xml', + 'ssdl': 'application/ssdl+xml', + 'sse': 'application/vnd.kodak-descriptor', + 'ssf': 'application/vnd.epson.ssf', + 'ssml': 'application/ssml+xml', + 'st': 'application/vnd.sailingtracker.track', + 'stc': 'application/vnd.sun.xml.calc.template', + 'std': 'application/vnd.sun.xml.draw.template', + 'stf': 'application/vnd.wt.stf', + 'sti': 'application/vnd.sun.xml.impress.template', + 'stk': 'application/hyperstudio', + 'stl': 'application/vnd.ms-pki.stl', + 'str': 'application/vnd.pg.format', + 'stw': 'application/vnd.sun.xml.writer.template', + 'sub': 'text/vnd.dvb.subtitle', + 'sus': 'application/vnd.sus-calendar', + 'susp': 'application/vnd.sus-calendar', + 'sv4cpio': 'application/x-sv4cpio', + 'sv4crc': 'application/x-sv4crc', + 'svc': 'application/vnd.dvb.service', + 'svd': 'application/vnd.svd', + 'svg': 'image/svg+xml', + 'svgz': 'image/svg+xml', + 'swa': 'application/x-director', + 'swf': 'application/x-shockwave-flash', + 'swi': 'application/vnd.aristanetworks.swi', + 'sxc': 'application/vnd.sun.xml.calc', + 'sxd': 'application/vnd.sun.xml.draw', + 'sxg': 'application/vnd.sun.xml.writer.global', + 'sxi': 'application/vnd.sun.xml.impress', + 'sxm': 'application/vnd.sun.xml.math', + 'sxw': 'application/vnd.sun.xml.writer', + 't': 'text/troff', + 't3': 'application/x-t3vm-image', + 'taglet': 'application/vnd.mynfc', + 'tao': 'application/vnd.tao.intent-module-archive', + 'tar': 'application/x-tar', + 'tcap': 'application/vnd.3gpp2.tcap', + 'tcl': 'application/x-tcl', + 'teacher': 'application/vnd.smart.teacher', + 'tei': 'application/tei+xml', + 'teicorpus': 'application/tei+xml', + 'tex': 'application/x-tex', + 'texi': 'application/x-texinfo', + 'texinfo': 'application/x-texinfo', + 'text': 'text/plain', + 'tfi': 'application/thraud+xml', + 'tfm': 'application/x-tex-tfm', + 'tga': 'image/x-tga', + 'thmx': 'application/vnd.ms-officetheme', + 'tif': 'image/tiff', + 'tiff': 'image/tiff', + 'tmo': 'application/vnd.tmobile-livetv', + 'torrent': 'application/x-bittorrent', + 'tpl': 'application/vnd.groove-tool-template', + 'tpt': 'application/vnd.trid.tpt', + 'tr': 'text/troff', + 'tra': 'application/vnd.trueapp', + 'trm': 'application/x-msterminal', + 'tsd': 'application/timestamped-data', + 'tsv': 'text/tab-separated-values', + 'ttc': 'application/x-font-ttf', + 'ttf': 'application/x-font-ttf', + 'ttl': 'text/turtle', + 'twd': 'application/vnd.simtech-mindmapper', + 'twds': 'application/vnd.simtech-mindmapper', + 'txd': 'application/vnd.genomatix.tuxedo', + 'txf': 'application/vnd.mobius.txf', + 'txt': 'text/plain', + 'u32': 'application/x-authorware-bin', + 'udeb': 'application/x-debian-package', + 'ufd': 'application/vnd.ufdl', + 'ufdl': 'application/vnd.ufdl', + 'ulx': 'application/x-glulx', + 'umj': 'application/vnd.umajin', + 'unityweb': 'application/vnd.unity', + 'uoml': 'application/vnd.uoml+xml', + 'uri': 'text/uri-list', + 'uris': 'text/uri-list', + 'urls': 'text/uri-list', + 'ustar': 'application/x-ustar', + 'utz': 'application/vnd.uiq.theme', + 'uu': 'text/x-uuencode', + 'uva': 'audio/vnd.dece.audio', + 'uvd': 'application/vnd.dece.data', + 'uvf': 'application/vnd.dece.data', + 'uvg': 'image/vnd.dece.graphic', + 'uvh': 'video/vnd.dece.hd', + 'uvi': 'image/vnd.dece.graphic', + 'uvm': 'video/vnd.dece.mobile', + 'uvp': 'video/vnd.dece.pd', + 'uvs': 'video/vnd.dece.sd', + 'uvt': 'application/vnd.dece.ttml+xml', + 'uvu': 'video/vnd.uvvu.mp4', + 'uvv': 'video/vnd.dece.video', + 'uvva': 'audio/vnd.dece.audio', + 'uvvd': 'application/vnd.dece.data', + 'uvvf': 'application/vnd.dece.data', + 'uvvg': 'image/vnd.dece.graphic', + 'uvvh': 'video/vnd.dece.hd', + 'uvvi': 'image/vnd.dece.graphic', + 'uvvm': 'video/vnd.dece.mobile', + 'uvvp': 'video/vnd.dece.pd', + 'uvvs': 'video/vnd.dece.sd', + 'uvvt': 'application/vnd.dece.ttml+xml', + 'uvvu': 'video/vnd.uvvu.mp4', + 'uvvv': 'video/vnd.dece.video', + 'uvvx': 'application/vnd.dece.unspecified', + 'uvvz': 'application/vnd.dece.zip', + 'uvx': 'application/vnd.dece.unspecified', + 'uvz': 'application/vnd.dece.zip', + 'vcard': 'text/vcard', + 'vcd': 'application/x-cdlink', + 'vcf': 'text/x-vcard', + 'vcg': 'application/vnd.groove-vcard', + 'vcs': 'text/x-vcalendar', + 'vcx': 'application/vnd.vcx', + 'vis': 'application/vnd.visionary', + 'viv': 'video/vnd.vivo', + 'vob': 'video/x-ms-vob', + 'vor': 'application/vnd.stardivision.writer', + 'vox': 'application/x-authorware-bin', + 'vrml': 'model/vrml', + 'vsd': 'application/vnd.visio', + 'vsf': 'application/vnd.vsf', + 'vss': 'application/vnd.visio', + 'vst': 'application/vnd.visio', + 'vsw': 'application/vnd.visio', + 'vtu': 'model/vnd.vtu', + 'vxml': 'application/voicexml+xml', + 'w3d': 'application/x-director', + 'wad': 'application/x-doom', + 'wav': 'audio/x-wav', + 'wax': 'audio/x-ms-wax', + 'wbmp': 'image/vnd.wap.wbmp', + 'wbs': 'application/vnd.criticaltools.wbs+xml', + 'wbxml': 'application/vnd.wap.wbxml', + 'wcm': 'application/vnd.ms-works', + 'wdb': 'application/vnd.ms-works', + 'wdp': 'image/vnd.ms-photo', + 'weba': 'audio/webm', + 'webm': 'video/webm', + 'webp': 'image/webp', + 'wg': 'application/vnd.pmi.widget', + 'wgt': 'application/widget', + 'wks': 'application/vnd.ms-works', + 'wm': 'video/x-ms-wm', + 'wma': 'audio/x-ms-wma', + 'wmd': 'application/x-ms-wmd', + 'wmf': 'application/x-msmetafile', + 'wml': 'text/vnd.wap.wml', + 'wmlc': 'application/vnd.wap.wmlc', + 'wmls': 'text/vnd.wap.wmlscript', + 'wmlsc': 'application/vnd.wap.wmlscriptc', + 'wmv': 'video/x-ms-wmv', + 'wmx': 'video/x-ms-wmx', + 'wmz': 'application/x-ms-wmz', + 'woff': 'application/x-font-woff', + 'wpd': 'application/vnd.wordperfect', + 'wpl': 'application/vnd.ms-wpl', + 'wps': 'application/vnd.ms-works', + 'wqd': 'application/vnd.wqd', + 'wri': 'application/x-mswrite', + 'wrl': 'model/vrml', + 'wsdl': 'application/wsdl+xml', + 'wspolicy': 'application/wspolicy+xml', + 'wtb': 'application/vnd.webturbo', + 'wvx': 'video/x-ms-wvx', + 'x32': 'application/x-authorware-bin', + 'x3d': 'model/x3d+xml', + 'x3db': 'model/x3d+binary', + 'x3dbz': 'model/x3d+binary', + 'x3dv': 'model/x3d+vrml', + 'x3dvz': 'model/x3d+vrml', + 'x3dz': 'model/x3d+xml', + 'xaml': 'application/xaml+xml', + 'xap': 'application/x-silverlight-app', + 'xar': 'application/vnd.xara', + 'xbap': 'application/x-ms-xbap', + 'xbd': 'application/vnd.fujixerox.docuworks.binder', + 'xbm': 'image/x-xbitmap', + 'xdf': 'application/xcap-diff+xml', + 'xdm': 'application/vnd.syncml.dm+xml', + 'xdp': 'application/vnd.adobe.xdp+xml', + 'xdssc': 'application/dssc+xml', + 'xdw': 'application/vnd.fujixerox.docuworks', + 'xenc': 'application/xenc+xml', + 'xer': 'application/patch-ops-error+xml', + 'xfdf': 'application/vnd.adobe.xfdf', + 'xfdl': 'application/vnd.xfdl', + 'xht': 'application/xhtml+xml', + 'xhtml': 'application/xhtml+xml', + 'xhvml': 'application/xv+xml', + 'xif': 'image/vnd.xiff', + 'xla': 'application/vnd.ms-excel', + 'xlam': 'application/vnd.ms-excel.addin.macroenabled.12', + 'xlc': 'application/vnd.ms-excel', + 'xlf': 'application/x-xliff+xml', + 'xlm': 'application/vnd.ms-excel', + 'xls': 'application/vnd.ms-excel', + 'xlsb': 'application/vnd.ms-excel.sheet.binary.macroenabled.12', + 'xlsm': 'application/vnd.ms-excel.sheet.macroenabled.12', + 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xlt': 'application/vnd.ms-excel', + 'xltm': 'application/vnd.ms-excel.template.macroenabled.12', + 'xltx': + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'xlw': 'application/vnd.ms-excel', + 'xm': 'audio/xm', + 'xml': 'application/xml', + 'xo': 'application/vnd.olpc-sugar', + 'xop': 'application/xop+xml', + 'xpi': 'application/x-xpinstall', + 'xpl': 'application/xproc+xml', + 'xpm': 'image/x-xpixmap', + 'xpr': 'application/vnd.is-xpr', + 'xps': 'application/vnd.ms-xpsdocument', + 'xpw': 'application/vnd.intercon.formnet', + 'xpx': 'application/vnd.intercon.formnet', + 'xsl': 'application/xml', + 'xslt': 'application/xslt+xml', + 'xsm': 'application/vnd.syncml+xml', + 'xspf': 'application/xspf+xml', + 'xul': 'application/vnd.mozilla.xul+xml', + 'xvm': 'application/xv+xml', + 'xvml': 'application/xv+xml', + 'xwd': 'image/x-xwindowdump', + 'xyz': 'chemical/x-xyz', + 'xz': 'application/x-xz', + 'yang': 'application/yang', + 'yin': 'application/yin+xml', + 'z1': 'application/x-zmachine', + 'z2': 'application/x-zmachine', + 'z3': 'application/x-zmachine', + 'z4': 'application/x-zmachine', + 'z5': 'application/x-zmachine', + 'z6': 'application/x-zmachine', + 'z7': 'application/x-zmachine', + 'z8': 'application/x-zmachine', + 'zaz': 'application/vnd.zzazz.deck+xml', + 'zip': 'application/zip', + 'zir': 'application/vnd.zul', + 'zirz': 'application/vnd.zul', + 'zmm': 'application/vnd.handheld-entertainment+xml', }; diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index bc939f66c..7430284f5 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -38,10 +38,31 @@ const List DEFAULT_MAGIC_NUMBERS = const [ 'image/png', const [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), const MagicNumber('image/tiff', const [0x49, 0x49, 0x2A, 0x00]), const MagicNumber('image/tiff', const [0x4D, 0x4D, 0x00, 0x2A]), - const MagicNumber( - 'video/mp4', - const [0x00, 0x00, 0x00, 0x00, 0x66, 0x74, - 0x79, 0x70, 0x33, 0x67, 0x70, 0x35], - mask: const [0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]) + const MagicNumber('video/mp4', const [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x33, + 0x67, + 0x70, + 0x35 + ], mask: const [ + 0xFF, + 0xFF, + 0xFF, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]) ]; diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart index 781040eeb..ba1a5aeb2 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -7,8 +7,8 @@ import 'dart:async'; import 'dart:typed_data'; import 'bound_multipart_stream.dart'; -import 'mime_shared.dart'; import 'char_code.dart'; +import 'mime_shared.dart'; Uint8List _getBoundary(String boundary) { var charCodes = boundary.codeUnits; diff --git a/pkgs/mime/lib/src/mime_shared.dart b/pkgs/mime/lib/src/mime_shared.dart index 6d14e0a61..701fae592 100644 --- a/pkgs/mime/lib/src/mime_shared.dart +++ b/pkgs/mime/lib/src/mime_shared.dart @@ -8,7 +8,7 @@ import 'dart:async'; class MimeMultipartException implements Exception { final String message; - const MimeMultipartException([String this.message = ""]); + const MimeMultipartException([this.message = ""]); String toString() => "MimeMultipartException: $message"; } diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 76f6514ab..4a893fe7c 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -39,8 +39,8 @@ void _runParseTest(String message, String boundary, TestMode mode, } switch (mode) { case TestMode.IMMEDIATE_LISTEN: - futures.add(multipart.fold([], (buffer, data) => buffer..addAll(data)) - .then((data) { + futures.add(multipart + .fold([], (buffer, data) => buffer..addAll(data)).then((data) { if (expectedParts[part] != null) { expect(data, equals(expectedParts[part].codeUnits)); } @@ -49,8 +49,8 @@ void _runParseTest(String message, String boundary, TestMode mode, case TestMode.DELAY_LISTEN: futures.add(new Future(() { - return multipart.fold([], (buffer, data) => buffer..addAll(data)) - .then((data) { + return multipart + .fold([], (buffer, data) => buffer..addAll(data)).then((data) { if (expectedParts[part] != null) { expect(data, equals(expectedParts[part].codeUnits)); } @@ -127,7 +127,7 @@ void _runParseTest(String message, String boundary, TestMode mode, int partIndex = i; if (partIndex >= parts) { - throw 'Expected no more parts, but got one.'; + throw new StateError('Expected no more parts, but got one.'); } if (expectedHeaders != null) { diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 87de96df3..39365beeb 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -47,22 +47,46 @@ void main() { }); test('by-header-bytes', () { - _expectMimeType('file.jpg', - 'image/png', - headerBytes: [0x89, 0x50, 0x4E, 0x47, - 0x0D, 0x0A, 0x1A, 0x0A]); - _expectMimeType('file.jpg', - 'image/gif', - headerBytes: [0x47, 0x49, 0x46, 0x38, 0x39, - 0x61, 0x0D, 0x0A, 0x1A, 0x0A]); - _expectMimeType('file.gif', - 'image/jpeg', - headerBytes: [0xFF, 0xD8, 0x46, 0x38, 0x39, - 0x61, 0x0D, 0x0A, 0x1A, 0x0A]); - _expectMimeType('file.mp4', - 'video/mp4', - headerBytes: [0x00, 0x00, 0x00, 0x04, 0x66, 0x74, - 0x79, 0x70, 0x33, 0x67, 0x70, 0x35]); + _expectMimeType('file.jpg', 'image/png', + headerBytes: [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]); + _expectMimeType('file.jpg', 'image/gif', headerBytes: [ + 0x47, + 0x49, + 0x46, + 0x38, + 0x39, + 0x61, + 0x0D, + 0x0A, + 0x1A, + 0x0A + ]); + _expectMimeType('file.gif', 'image/jpeg', headerBytes: [ + 0xFF, + 0xD8, + 0x46, + 0x38, + 0x39, + 0x61, + 0x0D, + 0x0A, + 0x1A, + 0x0A + ]); + _expectMimeType('file.mp4', 'video/mp4', headerBytes: [ + 0x00, + 0x00, + 0x00, + 0x04, + 0x66, + 0x74, + 0x79, + 0x70, + 0x33, + 0x67, + 0x70, + 0x35 + ]); }); }); From d5ed77cbf29ee9b62b4a0b1ed7bb5021f2a8c051 Mon Sep 17 00:00:00 2001 From: mfrancis107 Date: Wed, 18 Oct 2017 12:07:30 -0400 Subject: [PATCH 032/118] Adds support for glTF - text and binary formats (dart-lang/mime#9) See: https://github.com/KhronosGroup/glTF --- pkgs/mime/lib/src/default_extension_map.dart | 2 ++ pkgs/mime/lib/src/magic_number.dart | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index cfa42ed9d..e3ee44cd7 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -283,6 +283,8 @@ final Map defaultExtensionMap = { 'ghf': 'application/vnd.groove-help', 'gif': 'image/gif', 'gim': 'application/vnd.groove-identity-message', + 'glb': 'model/gltf-binary', + 'gltf': 'model/gltf+json', 'gml': 'application/gml+xml', 'gmx': 'application/vnd.gmx', 'gnumeric': 'application/x-gnumeric', diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 7430284f5..7ea10fac3 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -64,5 +64,6 @@ const List DEFAULT_MAGIC_NUMBERS = const [ 0xFF, 0xFF, 0xFF - ]) + ]), + const MagicNumber('model/gltf-binary', const [0x46, 0x54, 0x6C, 0x67]), ]; From 207502065a5fbd451ba30e5f2693a75ce0e7a460 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 25 Oct 2017 10:27:20 -0700 Subject: [PATCH 033/118] Update readme --- pkgs/mime/README.md | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index d5bf11a4d..779783e25 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -1,27 +1,27 @@ -#MIME type package - Package for working with MIME type definitions and for processing streams of MIME multipart media types. -##Determining the MIME type for a file +## Determining the MIME type for a file The `MimeTypeResolver` class can be used to determine the MIME type of a file. It supports both using the extension of the file name and -looking at magic bytes from the begining of the file. +looking at magic bytes from the beginning of the file. There is a builtin instance of `MimeTypeResolver` accessible through the top level function `lookupMimeType`. This builtin instance has the most common file name extensions and magic bytes registered. - print(lookupMimeType('test.html')); // Will print text/html - print(lookupMimeType('test', [0xFF, 0xD8])); // Will print image/jpeg - print(lookupMimeType('test.html', [0xFF, 0xD8])); // Will print image/jpeg +```dart +print(lookupMimeType('test.html')); // Will print text/html +print(lookupMimeType('test', [0xFF, 0xD8])); // Will print image/jpeg +print(lookupMimeType('test.html', [0xFF, 0xD8])); // Will print image/jpeg +``` You can build you own resolver by creating an instance of `MimeTypeResolver` and adding file name extensions and magic bytes using `addExtension` and `addMagicNumber`. -##Processing MIME multipart media types +## Processing MIME multipart media types The class `MimeMultipartTransformer` is used to process a `Stream` of bytes encoded using a MIME multipart media types encoding. The @@ -32,18 +32,21 @@ part is provided as a stream of bytes. Below is an example showing how to process an HTTP request and print the length of the content of each part. - // HTTP request with content type multipart/form-data. - HttpRequest request = ...; - // Determine the boundary form the content type header - String boundary = request.headers.contentType.parameters['boundary']; +```dart +// HTTP request with content type multipart/form-data. +HttpRequest request = ...; +// Determine the boundary form the content type header +String boundary = request.headers.contentType.parameters['boundary']; - // Process the body just calculating the length of each part. - request.transform(new MimeMultipartTransformer(boundary)) - .map((part) => part.fold(0, (p, d) => p + d)) - .listen((length) => print('Part with length $length')); +// Process the body just calculating the length of each part. +request + .transform(new MimeMultipartTransformer(boundary)) + .map((part) => part.fold(0, (p, d) => p + d)) + .listen((length) => print('Part with length $length')); +``` Take a look at the `HttpBodyHandler` in the [http_server][http_server] -package for handling different content types in a HTTP request. +package for handling different content types in an HTTP request. ## Features and bugs From a0b20b2cd7565d37ac70434f36875bf0db9818de Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 25 Oct 2017 10:32:41 -0700 Subject: [PATCH 034/118] Prepare for 0.9.4 --- pkgs/mime/CHANGELOG.md | 4 ++++ pkgs/mime/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index a76441f07..ce041bcb5 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -2,6 +2,10 @@ * Updated Dart SDK requirement to `>= 1.8.3 <2.0.0` +* Strong-mode clean. + +* Added support for glTF text and binary formats. + # 0.9.3 * Fixed erroneous behavior for listening and when pausing/resuming diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index e90b74c52..0daf6575e 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.4-dev +version: 0.9.4 author: Dart Team description: Helper-package for working with MIME. homepage: https://www.github.com/dart-lang/mime From f38e11cfb563593c7e34fa89acdb9d7ae17a5131 Mon Sep 17 00:00:00 2001 From: Greg Littlefield Date: Thu, 7 Dec 2017 15:04:17 -0700 Subject: [PATCH 035/118] Add WebAssembly extension (dart-lang/mime#12) --- pkgs/mime/CHANGELOG.md | 4 ++++ pkgs/mime/lib/src/default_extension_map.dart | 1 + pkgs/mime/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index ce041bcb5..043c41256 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.5 + +* Add support for the WebAssembly format. + # 0.9.4 * Updated Dart SDK requirement to `>= 1.8.3 <2.0.0` diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index e3ee44cd7..2b27bef33 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -883,6 +883,7 @@ final Map defaultExtensionMap = { 'vxml': 'application/voicexml+xml', 'w3d': 'application/x-director', 'wad': 'application/x-doom', + 'wasm': 'application/wasm', 'wav': 'audio/x-wav', 'wax': 'audio/x-ms-wax', 'wbmp': 'image/vnd.wap.wbmp', diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 0daf6575e..75f045798 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.4 +version: 0.9.5 author: Dart Team description: Helper-package for working with MIME. homepage: https://www.github.com/dart-lang/mime From 0a4a8d1ec61d36643c4828f70d7715e67ed3fdd4 Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Wed, 31 Jan 2018 12:51:53 -0800 Subject: [PATCH 036/118] Updates for Dart 2.0 core library changes (wave 2.2) --- pkgs/mime/CHANGELOG.md | 7 +++++++ pkgs/mime/lib/src/mime_multipart_transformer.dart | 2 +- pkgs/mime/pubspec.yaml | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 043c41256..1e3f9a159 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,10 @@ +# 0.9.6 + +* Updates to support Dart 2.0 core library changes (wave + 2.2). See [issue 31847][sdk#31847] for details. + + [sdk#31847]: https://github.com/dart-lang/sdk/issues/31847 + # 0.9.5 * Add support for the WebAssembly format. diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart index ba1a5aeb2..a71e6d9a9 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -30,7 +30,7 @@ Uint8List _getBoundary(String boundary) { * of them streaming the multipart data. */ class MimeMultipartTransformer - implements StreamTransformer, MimeMultipart> { + extends StreamTransformerBase, MimeMultipart> { final List _boundary; /** diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 75f045798..181177121 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,9 +1,9 @@ name: mime -version: 0.9.5 +version: 0.9.6 author: Dart Team description: Helper-package for working with MIME. homepage: https://www.github.com/dart-lang/mime environment: - sdk: '>=1.8.3 <2.0.0' + sdk: '>=2.0.0-dev.20.0 <2.0.0' dev_dependencies: test: '^0.12.0' From db4360f02eb3245cb392770e51d8cdabc09a0f1a Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Wed, 31 Jan 2018 15:50:02 -0800 Subject: [PATCH 037/118] Remove stable from travis --- pkgs/mime/.travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/mime/.travis.yml b/pkgs/mime/.travis.yml index da58f76ba..8b6048dfd 100644 --- a/pkgs/mime/.travis.yml +++ b/pkgs/mime/.travis.yml @@ -2,7 +2,6 @@ language: dart sudo: false dart: - dev - - stable dart_task: - test - dartfmt From c2035887b33f9b6f55715845ed25e8a13d80e799 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 4 May 2018 11:46:37 +0200 Subject: [PATCH 038/118] Remove upper case constants (dart-lang/mime#17) Remove usage of upper-case constants. Update SDK version. --- pkgs/mime/CHANGELOG.md | 4 ++++ pkgs/mime/lib/src/bound_multipart_stream.dart | 4 ++-- pkgs/mime/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 1e3f9a159..86c37770a 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.6+1 + +- Stop using deprecated constants from the SDK. + # 0.9.6 * Updates to support Dart 2.0 core library changes (wave diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index aab7ddda2..e84372731 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -304,8 +304,8 @@ class BoundMultipartStream { if (byte == CharCode.SP || byte == CharCode.HT) { _state = _HEADER_VALUE_START; } else { - String headerField = UTF8.decode(_headerField); - String headerValue = UTF8.decode(_headerValue); + String headerField = utf8.decode(_headerField); + String headerValue = utf8.decode(_headerValue); _headers[headerField.toLowerCase()] = headerValue; _headerField.clear(); _headerValue.clear(); diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 181177121..e1fe57814 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.6 +version: 0.9.6+1 author: Dart Team description: Helper-package for working with MIME. homepage: https://www.github.com/dart-lang/mime From faa484bee3598ce9c7d3583ffd41bd924bd933ae Mon Sep 17 00:00:00 2001 From: BC Ko Date: Thu, 24 May 2018 11:57:53 -0700 Subject: [PATCH 039/118] Update .gitignore to new `dart_tool` pub cache dart-lang/sdkdart-lang/mime#32030 --- pkgs/mime/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/mime/.gitignore b/pkgs/mime/.gitignore index 4232a2f22..a433102ca 100644 --- a/pkgs/mime/.gitignore +++ b/pkgs/mime/.gitignore @@ -1,4 +1,5 @@ .packages +.dart_tool/ .pub/ packages pubspec.lock From 9d7f558d43708f73b460c70fa948892adc03a7e5 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 17 Jul 2018 13:23:40 -0700 Subject: [PATCH 040/118] Update README.md (dart-lang/mime#20) --- pkgs/mime/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index 779783e25..e2b70de8c 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://travis-ci.org/dart-lang/mime.svg?branch=master)](https://travis-ci.org/dart-lang/mime) + Package for working with MIME type definitions and for processing streams of MIME multipart media types. From 2c62d781f2209fc0f43babd935de106e9e91299a Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 20 Jul 2018 16:49:01 -0400 Subject: [PATCH 041/118] Allow SDK versions <3.0.0 (dart-lang/mime#21) --- pkgs/mime/CHANGELOG.md | 4 ++++ pkgs/mime/pubspec.yaml | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 86c37770a..9e1468574 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.6+2 + +- Set max SDK version to `<3.0.0`, and adjust other dependencies. + # 0.9.6+1 - Stop using deprecated constants from the SDK. diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index e1fe57814..97e27ef93 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,9 +1,12 @@ name: mime -version: 0.9.6+1 -author: Dart Team +version: 0.9.6+2 + description: Helper-package for working with MIME. +author: Dart Team homepage: https://www.github.com/dart-lang/mime + environment: - sdk: '>=2.0.0-dev.20.0 <2.0.0' + sdk: '>=2.0.0-dev.20.0 <3.0.0' + dev_dependencies: - test: '^0.12.0' + test: ^1.2.0 From 69a31d0d16d3f60054447b969f8cd563a953f3ef Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Sat, 21 Jul 2018 23:47:45 -0700 Subject: [PATCH 042/118] change the mime type for dart source (dart-lang/mime#19) change the mime type for dart source --- pkgs/mime/CHANGELOG.md | 10 +++++++--- pkgs/mime/lib/src/default_extension_map.dart | 2 +- pkgs/mime/pubspec.yaml | 2 +- pkgs/mime/test/mime_type_test.dart | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 9e1468574..88fd3eeac 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,16 +1,20 @@ +# 0.9.6+3 + +* Change the mime type for Dart source from `application/dart` to `text/x-dart`. + # 0.9.6+2 -- Set max SDK version to `<3.0.0`, and adjust other dependencies. +* Set max SDK version to `<3.0.0`, and adjust other dependencies. # 0.9.6+1 -- Stop using deprecated constants from the SDK. +* Stop using deprecated constants from the SDK. # 0.9.6 * Updates to support Dart 2.0 core library changes (wave 2.2). See [issue 31847][sdk#31847] for details. - + [sdk#31847]: https://github.com/dart-lang/sdk/issues/31847 # 0.9.5 diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index 2b27bef33..c7add4834 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -150,7 +150,7 @@ final Map defaultExtensionMap = { 'cxx': 'text/x-c', 'dae': 'model/vnd.collada+xml', 'daf': 'application/vnd.mobius.daf', - 'dart': 'application/dart', + 'dart': 'text/x-dart', 'dataless': 'application/vnd.fdsn.seed', 'davmount': 'application/davmount+xml', 'dbk': 'application/docbook+xml', diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 97e27ef93..eae898774 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.6+2 +version: 0.9.6+3 description: Helper-package for working with MIME. author: Dart Team diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 39365beeb..84a7ecaae 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -23,9 +23,9 @@ void _expectMimeType(String path, String expectedMimeType, void main() { group('global-lookup', () { test('by-path', () { - _expectMimeType('file.dart', 'application/dart'); + _expectMimeType('file.dart', 'text/x-dart'); // Test mixed-case - _expectMimeType('file.DaRT', 'application/dart'); + _expectMimeType('file.DaRT', 'text/x-dart'); _expectMimeType('file.html', 'text/html'); _expectMimeType('file.xhtml', 'application/xhtml+xml'); _expectMimeType('file.jpeg', 'image/jpeg'); From 0c5e1c80a6f2dafb134e6ba476da0c97534b0530 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 29 May 2019 10:41:58 -0700 Subject: [PATCH 043/118] Delete codereview.settings --- pkgs/mime/codereview.settings | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/mime/codereview.settings diff --git a/pkgs/mime/codereview.settings b/pkgs/mime/codereview.settings deleted file mode 100644 index 85f2bb59e..000000000 --- a/pkgs/mime/codereview.settings +++ /dev/null @@ -1,3 +0,0 @@ -CODE_REVIEW_SERVER: http://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/mime/commit/ -CC_LIST: reviews@dartlang.org From a4372e0e405b673767ca88acbc736ccfc5b38057 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 29 May 2019 10:43:30 -0700 Subject: [PATCH 044/118] Fix URLs Fixes https://github.com/dart-lang/mime/issues/22 --- pkgs/mime/README.md | 4 ++-- pkgs/mime/lib/mime.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index e2b70de8c..4c8f313f2 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -54,5 +54,5 @@ package for handling different content types in an HTTP request. Please file feature requests and bugs at the [issue tracker][tracker]. -[tracker]: https://github.com/dart-lang/sample/issues -[http_server]: https://pub.dartlang.org/packages/http_server +[tracker]: https://github.com/dart-lang/mime/issues +[http_server]: https://pub.dev/packages/http_server diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart index dce677488..69a9cfaf1 100644 --- a/pkgs/mime/lib/mime.dart +++ b/pkgs/mime/lib/mime.dart @@ -9,8 +9,8 @@ * More details, including a list of types, are in the Wikipedia article * [Internet media type](http://en.wikipedia.org/wiki/Internet_media_type). * For information on installing and importing this library, see the - * [mime package on pub.dartlang.org] - * (http://pub.dartlang.org/packages/mime). + * [mime package on pub.dev] + * (https://pub.dev/packages/mime). */ library mime; From 21333f3397212579f7877c49b7a5826faf7c4479 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 29 May 2019 10:46:42 -0700 Subject: [PATCH 045/118] enable and fix a number of lints --- pkgs/mime/analysis_options.yaml | 47 +++++----- pkgs/mime/lib/mime.dart | 18 ++-- pkgs/mime/lib/src/bound_multipart_stream.dart | 22 ++--- pkgs/mime/lib/src/magic_number.dart | 25 +++--- .../lib/src/mime_multipart_transformer.dart | 20 ++--- pkgs/mime/lib/src/mime_shared.dart | 6 +- pkgs/mime/lib/src/mime_type.dart | 86 ++++++++----------- pkgs/mime/pubspec.yaml | 5 +- .../test/mime_multipart_transformer_test.dart | 28 +++--- pkgs/mime/test/mime_type_test.dart | 6 +- 10 files changed, 120 insertions(+), 143 deletions(-) diff --git a/pkgs/mime/analysis_options.yaml b/pkgs/mime/analysis_options.yaml index 6ff678df9..7f965d234 100644 --- a/pkgs/mime/analysis_options.yaml +++ b/pkgs/mime/analysis_options.yaml @@ -1,40 +1,43 @@ +include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false - errors: - unused_element: error - unused_import: error - unused_local_variable: error - dead_code: error linter: rules: - # Errors - avoid_empty_else - #- comment_references - - control_flow_in_finally - - empty_statements - - hash_and_equals - - implementation_imports - - test_types_in_equals - - throw_in_finally - - unrelated_type_equality_checks - - valid_regexps - - # Style - #- annotate_overrides - avoid_init_to_null - - avoid_return_types_on_setters + - avoid_null_checks_in_equality_operators + - avoid_unused_constructor_parameters - await_only_futures - camel_case_types + - cancel_subscriptions + #- constant_identifier_names + - control_flow_in_finally - directives_ordering - empty_catches - empty_constructor_bodies + - empty_statements + - hash_and_equals + - implementation_imports + - iterable_contains_unrelated_type - library_names - library_prefixes + - list_remove_unrelated_type - non_constant_identifier_names - - only_throw_errors + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + - prefer_equal_for_default_values - prefer_final_fields + - prefer_generic_function_type_aliases - prefer_is_not_empty - #- prefer_single_quotes - #- slash_for_doc_comments + - slash_for_doc_comments + - test_types_in_equals + - throw_in_finally - type_init_formals + - unnecessary_brace_in_string_interps + - unnecessary_const + - unnecessary_new + - unrelated_type_equality_checks + - valid_regexps diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart index 69a9cfaf1..90c892108 100644 --- a/pkgs/mime/lib/mime.dart +++ b/pkgs/mime/lib/mime.dart @@ -2,16 +2,14 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -/** - * Help for working with file format identifiers - * such as `text/html` and `image/png`. - * - * More details, including a list of types, are in the Wikipedia article - * [Internet media type](http://en.wikipedia.org/wiki/Internet_media_type). - * For information on installing and importing this library, see the - * [mime package on pub.dev] - * (https://pub.dev/packages/mime). - */ +/// Help for working with file format identifiers +/// such as `text/html` and `image/png`. +/// +/// More details, including a list of types, are in the Wikipedia article +/// [Internet media type](http://en.wikipedia.org/wiki/Internet_media_type). +/// For information on installing and importing this library, see the +/// [mime package on pub.dev] +/// (https://pub.dev/packages/mime). library mime; export 'src/mime_multipart_transformer.dart'; diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index e84372731..4b32ef934 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -10,7 +10,7 @@ import 'char_code.dart'; import 'mime_shared.dart'; // Bytes for '()<>@,;:\\"/[]?={} \t'. -const _SEPARATORS = const [ +const _SEPARATORS = [ 40, 41, 60, @@ -33,7 +33,7 @@ const _SEPARATORS = const [ ]; bool _isTokenChar(int byte) { - return byte > 31 && byte < 128 && _SEPARATORS.indexOf(byte) == -1; + return byte > 31 && byte < 128 && !_SEPARATORS.contains(byte); } int _toLowerCase(int byte) { @@ -45,13 +45,13 @@ int _toLowerCase(int byte) { void _expectByteValue(int val1, int val2) { if (val1 != val2) { - throw new MimeMultipartException("Failed to parse multipart mime 1"); + throw MimeMultipartException("Failed to parse multipart mime 1"); } } void _expectWhitespace(int byte) { if (byte != CharCode.SP && byte != CharCode.HT) { - throw new MimeMultipartException("Failed to parse multipart mime 2"); + throw MimeMultipartException("Failed to parse multipart mime 2"); } } @@ -118,7 +118,7 @@ class BoundMultipartStream { List _buffer; BoundMultipartStream(this._boundary, Stream> stream) { - _controller = new StreamController( + _controller = StreamController( sync: true, onPause: _pauseStream, onResume: _resumeStream, @@ -137,7 +137,7 @@ class BoundMultipartStream { }, onDone: () { if (_state != _DONE) { _controller - .addError(new MimeMultipartException("Bad multipart ending")); + .addError(MimeMultipartException("Bad multipart ending")); } _controller.close(); }, onError: _controller.addError); @@ -168,7 +168,7 @@ class BoundMultipartStream { _subscription.cancel(); break; default: - throw new StateError("This code should never be reached."); + throw StateError("This code should never be reached."); } } } @@ -256,7 +256,7 @@ class BoundMultipartStream { break; case _HEADER_START: - _headers = new Map(); + _headers = Map(); if (byte == CharCode.CR) { _state = _HEADER_ENDING; } else { @@ -271,7 +271,7 @@ class BoundMultipartStream { _state = _HEADER_VALUE_START; } else { if (!_isTokenChar(byte)) { - throw new MimeMultipartException("Invalid header field name"); + throw MimeMultipartException("Invalid header field name"); } _headerField.add(_toLowerCase(byte)); } @@ -321,7 +321,7 @@ class BoundMultipartStream { case _HEADER_ENDING: _expectByteValue(byte, CharCode.LF); - _multipartController = new StreamController( + _multipartController = StreamController( sync: true, onListen: () { if (_subscription.isPaused) _subscription.resume(); @@ -329,7 +329,7 @@ class BoundMultipartStream { onPause: _subscription.pause, onResume: _subscription.resume); _controller - .add(new _MimeMultipart(_headers, _multipartController.stream)); + .add(_MimeMultipart(_headers, _multipartController.stream)); _headers = null; _state = _CONTENT; contentStartIndex = _index + 1; diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 7ea10fac3..d490346b5 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -28,17 +28,16 @@ class MagicNumber { const int DEFAULT_MAGIC_NUMBERS_MAX_LENGTH = 12; -const List DEFAULT_MAGIC_NUMBERS = const [ - const MagicNumber('application/pdf', const [0x25, 0x50, 0x44, 0x46]), - const MagicNumber('application/postscript', const [0x25, 0x51]), - const MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), - const MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), - const MagicNumber('image/jpeg', const [0xFF, 0xD8]), - const MagicNumber( - 'image/png', const [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), - const MagicNumber('image/tiff', const [0x49, 0x49, 0x2A, 0x00]), - const MagicNumber('image/tiff', const [0x4D, 0x4D, 0x00, 0x2A]), - const MagicNumber('video/mp4', const [ +const List DEFAULT_MAGIC_NUMBERS = [ + MagicNumber('application/pdf', [0x25, 0x50, 0x44, 0x46]), + MagicNumber('application/postscript', [0x25, 0x51]), + MagicNumber('image/gif', [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), + MagicNumber('image/gif', [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), + MagicNumber('image/jpeg', [0xFF, 0xD8]), + MagicNumber('image/png', [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), + MagicNumber('image/tiff', [0x49, 0x49, 0x2A, 0x00]), + MagicNumber('image/tiff', [0x4D, 0x4D, 0x00, 0x2A]), + MagicNumber('video/mp4', [ 0x00, 0x00, 0x00, @@ -51,7 +50,7 @@ const List DEFAULT_MAGIC_NUMBERS = const [ 0x67, 0x70, 0x35 - ], mask: const [ + ], mask: [ 0xFF, 0xFF, 0xFF, @@ -65,5 +64,5 @@ const List DEFAULT_MAGIC_NUMBERS = const [ 0xFF, 0xFF ]), - const MagicNumber('model/gltf-binary', const [0x46, 0x54, 0x6C, 0x67]), + MagicNumber('model/gltf-binary', [0x46, 0x54, 0x6C, 0x67]), ]; diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart index a71e6d9a9..5509339fc 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -13,7 +13,7 @@ import 'mime_shared.dart'; Uint8List _getBoundary(String boundary) { var charCodes = boundary.codeUnits; - var boundaryList = new Uint8List(4 + charCodes.length); + var boundaryList = Uint8List(4 + charCodes.length); // Set-up the matching boundary preceding it with CRLF and two // dashes. boundaryList[0] = CharCode.CR; @@ -24,24 +24,20 @@ Uint8List _getBoundary(String boundary) { return boundaryList; } -/** - * Parser for MIME multipart types of data as described in RFC 2046 - * section 5.1.1. The data is transformed into [MimeMultipart] objects, each - * of them streaming the multipart data. - */ +/// Parser for MIME multipart types of data as described in RFC 2046 +/// section 5.1.1. The data is transformed into [MimeMultipart] objects, each +/// of them streaming the multipart data. class MimeMultipartTransformer extends StreamTransformerBase, MimeMultipart> { final List _boundary; - /** - * Construct a new MIME multipart parser with the boundary - * [boundary]. The boundary should be as specified in the content - * type parameter, that is without the -- prefix. - */ + /// Construct a new MIME multipart parser with the boundary + /// [boundary]. The boundary should be as specified in the content + /// type parameter, that is without the -- prefix. MimeMultipartTransformer(String boundary) : _boundary = _getBoundary(boundary); Stream bind(Stream> stream) { - return new BoundMultipartStream(_boundary, stream).stream; + return BoundMultipartStream(_boundary, stream).stream; } } diff --git a/pkgs/mime/lib/src/mime_shared.dart b/pkgs/mime/lib/src/mime_shared.dart index 701fae592..5cc6a8f40 100644 --- a/pkgs/mime/lib/src/mime_shared.dart +++ b/pkgs/mime/lib/src/mime_shared.dart @@ -13,10 +13,8 @@ class MimeMultipartException implements Exception { String toString() => "MimeMultipartException: $message"; } -/** - * A Mime Multipart class representing each part parsed by - * [MimeMultipartTransformer]. The data is streamed in as it become available. - */ +/// A Mime Multipart class representing each part parsed by +/// [MimeMultipartTransformer]. The data is streamed in as it become available. abstract class MimeMultipart extends Stream> { Map get headers; } diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index b1fa8daa0..6fbe270ca 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -7,68 +7,54 @@ library mime.mime_type; import 'default_extension_map.dart'; import 'magic_number.dart'; -final MimeTypeResolver _globalResolver = new MimeTypeResolver(); +final MimeTypeResolver _globalResolver = MimeTypeResolver(); -/** - * The maximum number of bytes needed, to match all default magic-numbers. - */ +/// The maximum number of bytes needed, to match all default magic-numbers. int get defaultMagicNumbersMaxLength => _globalResolver.magicNumbersMaxLength; -/** - * Extract the extension from [path] and use that for MIME-type lookup, using - * the default extension map. - * - * If no matching MIME-type was found, `null` is returned. - * - * If [headerBytes] is present, a match for known magic-numbers will be - * performed first. This allows the correct mime-type to be found, even though - * a file have been saved using the wrong file-name extension. If less than - * [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't - * be matched against. - */ +/// Extract the extension from [path] and use that for MIME-type lookup, using +/// the default extension map. +/// +/// If no matching MIME-type was found, `null` is returned. +/// +/// If [headerBytes] is present, a match for known magic-numbers will be +/// performed first. This allows the correct mime-type to be found, even though +/// a file have been saved using the wrong file-name extension. If less than +/// [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't +/// be matched against. String lookupMimeType(String path, {List headerBytes}) => _globalResolver.lookup(path, headerBytes: headerBytes); -/** - * MIME-type resolver class, used to customize the lookup of mime-types. - */ +/// MIME-type resolver class, used to customize the lookup of mime-types. class MimeTypeResolver { final Map _extensionMap = {}; final List _magicNumbers = []; final bool _useDefault; int _magicNumbersMaxLength; - /** - * Create a new empty [MimeTypeResolver]. - */ + /// Create a new empty [MimeTypeResolver]. MimeTypeResolver.empty() : _useDefault = false, _magicNumbersMaxLength = 0; - /** - * Create a new [MimeTypeResolver] containing the default scope. - */ + /// Create a new [MimeTypeResolver] containing the default scope. MimeTypeResolver() : _useDefault = true, _magicNumbersMaxLength = DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; - /** - * Get the maximum number of bytes required to match all magic numbers, when - * performing [lookup] with headerBytes present. - */ + /// Get the maximum number of bytes required to match all magic numbers, when + /// performing [lookup] with headerBytes present. int get magicNumbersMaxLength => _magicNumbersMaxLength; - /** - * Extract the extension from [path] and use that for MIME-type lookup. - * - * If no matching MIME-type was found, `null` is returned. - * - * If [headerBytes] is present, a match for known magic-numbers will be - * performed first. This allows the correct mime-type to be found, even though - * a file have been saved using the wrong file-name extension. If less than - * [magicNumbersMaxLength] bytes was provided, some magic-numbers won't - * be matched against. - */ + /// Extract the extension from [path] and use that for MIME-type lookup. + /// + /// If no matching MIME-type was found, `null` is returned. + /// + /// If [headerBytes] is present, a match for known magic-numbers will be + /// performed first. This allows the correct mime-type to be found, even + /// though a file have been saved using the wrong file-name extension. If less + /// than [magicNumbersMaxLength] bytes was provided, some magic-numbers won't + /// be matched against. String lookup(String path, {List headerBytes}) { String result; if (headerBytes != null) { @@ -89,28 +75,24 @@ class MimeTypeResolver { return null; } - /** - * Add a new MIME-type mapping to the [MimeTypeResolver]. If the [extension] - * is already present in the [MimeTypeResolver], it'll be overwritten. - */ + /// Add a new MIME-type mapping to the [MimeTypeResolver]. If the [extension] + /// is already present in the [MimeTypeResolver], it'll be overwritten. void addExtension(String extension, String mimeType) { _extensionMap[extension] = mimeType; } - /** - * Add a new magic-number mapping to the [MimeTypeResolver]. - * - * If [mask] is present,the [mask] is used to only perform matching on - * selective bits. The [mask] must have the same length as [bytes]. - */ + /// Add a new magic-number mapping to the [MimeTypeResolver]. + /// + /// If [mask] is present,the [mask] is used to only perform matching on + /// selective bits. The [mask] must have the same length as [bytes]. void addMagicNumber(List bytes, String mimeType, {List mask}) { if (mask != null && bytes.length != mask.length) { - throw new ArgumentError('Bytes and mask are of different lengths'); + throw ArgumentError('Bytes and mask are of different lengths'); } if (bytes.length > _magicNumbersMaxLength) { _magicNumbersMaxLength = bytes.length; } - _magicNumbers.add(new MagicNumber(mimeType, bytes, mask: mask)); + _magicNumbers.add(MagicNumber(mimeType, bytes, mask: mask)); } static String _matchMagic( diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index eae898774..b1685bc70 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,12 +1,13 @@ name: mime -version: 0.9.6+3 +version: 0.9.7-dev description: Helper-package for working with MIME. author: Dart Team homepage: https://www.github.com/dart-lang/mime environment: - sdk: '>=2.0.0-dev.20.0 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dev_dependencies: + pedantic: ^1.0.0 test: ^1.2.0 diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 4a893fe7c..be8ca178c 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -25,12 +25,12 @@ enum TestMode { IMMEDIATE_LISTEN, DELAY_LISTEN, PAUSE_RESUME } void _runParseTest(String message, String boundary, TestMode mode, [List expectedHeaders, List expectedParts, bool expectError = false]) { Future testWrite(List data, [int chunkSize = -1]) { - var controller = new StreamController>(sync: true); + var controller = StreamController>(sync: true); var stream = - controller.stream.transform(new MimeMultipartTransformer(boundary)); + controller.stream.transform(MimeMultipartTransformer(boundary)); int i = 0; - var completer = new Completer(); + var completer = Completer(); var futures = []; stream.listen((multipart) { int part = i++; @@ -48,7 +48,7 @@ void _runParseTest(String message, String boundary, TestMode mode, break; case TestMode.DELAY_LISTEN: - futures.add(new Future(() { + futures.add(Future(() { return multipart .fold([], (buffer, data) => buffer..addAll(data)).then((data) { if (expectedParts[part] != null) { @@ -59,14 +59,14 @@ void _runParseTest(String message, String boundary, TestMode mode, break; case TestMode.PAUSE_RESUME: - var completer = new Completer(); + var completer = Completer(); futures.add(completer.future); var buffer = []; var subscription; subscription = multipart.listen((data) { buffer.addAll(data); subscription.pause(); - new Future(() => subscription.resume()); + Future(() => subscription.resume()); }, onDone: () { if (expectedParts[part] != null) { expect(buffer, equals(expectedParts[part].codeUnits)); @@ -90,11 +90,11 @@ void _runParseTest(String message, String boundary, TestMode mode, } Future testFirstPartOnly(List data, [int chunkSize = -1]) { - var completer = new Completer(); - var controller = new StreamController>(sync: true); + var completer = Completer(); + var controller = StreamController>(sync: true); var stream = - controller.stream.transform(new MimeMultipartTransformer(boundary)); + controller.stream.transform(MimeMultipartTransformer(boundary)); stream.first.then((multipart) { if (expectedHeaders != null) { @@ -116,10 +116,10 @@ void _runParseTest(String message, String boundary, TestMode mode, Future testCompletePartAfterCancel(List data, int parts, [int chunkSize = -1]) { - var completer = new Completer(); - var controller = new StreamController>(sync: true); + var completer = Completer(); + var controller = StreamController>(sync: true); var stream = - controller.stream.transform(new MimeMultipartTransformer(boundary)); + controller.stream.transform(MimeMultipartTransformer(boundary)); var subscription; int i = 0; var futures = []; @@ -127,7 +127,7 @@ void _runParseTest(String message, String boundary, TestMode mode, int partIndex = i; if (partIndex >= parts) { - throw new StateError('Expected no more parts, but got one.'); + throw StateError('Expected no more parts, but got one.'); } if (expectedHeaders != null) { @@ -165,7 +165,7 @@ void _runParseTest(String message, String boundary, TestMode mode, completes); }); - if (expectedParts.length > 0) { + if (expectedParts.isNotEmpty) { test('test-first-part-only', () { expect( Future.wait([ diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 84a7ecaae..9d027728f 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -92,19 +92,19 @@ void main() { group('custom-resolver', () { test('override-extension', () { - var resolver = new MimeTypeResolver(); + var resolver = MimeTypeResolver(); resolver.addExtension('jpg', 'my-mime-type'); _expectMimeType('file.jpg', 'my-mime-type', resolver: resolver); }); test('fallthrough-extension', () { - var resolver = new MimeTypeResolver(); + var resolver = MimeTypeResolver(); resolver.addExtension('jpg2', 'my-mime-type'); _expectMimeType('file.jpg', 'image/jpeg', resolver: resolver); }); test('with-mask', () { - var resolver = new MimeTypeResolver.empty(); + var resolver = MimeTypeResolver.empty(); resolver.addMagicNumber([0x01, 0x02, 0x03], 'my-mime-type', mask: [0x01, 0xFF, 0xFE]); _expectMimeType('file', 'my-mime-type', From 35be08cf39443f232616c00591ad0e4f454e7682 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 29 May 2019 10:47:31 -0700 Subject: [PATCH 046/118] Test on oldest supported SDK --- pkgs/mime/.travis.yml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/pkgs/mime/.travis.yml b/pkgs/mime/.travis.yml index 8b6048dfd..8a365297a 100644 --- a/pkgs/mime/.travis.yml +++ b/pkgs/mime/.travis.yml @@ -1,11 +1,18 @@ language: dart -sudo: false + dart: - - dev +- 2.0.0 +- dev + dart_task: - - test - - dartfmt - - dartanalyzer +- test +- dartanalyzer: --fatal-infos --fatal-warnings . + +matrix: + include: + # Only validate formatting using the dev release + - dart: dev + dart_task: dartfmt # Only building master means that we don't run two builds for each pull request. branches: @@ -13,4 +20,4 @@ branches: cache: directories: - - $HOME/.pub-cache + - $HOME/.pub-cache From 52fd1c710d82c3842cfe62382d25a63357f1d1ac Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 29 May 2019 10:51:27 -0700 Subject: [PATCH 047/118] Remove gratuitous self-link --- pkgs/mime/lib/mime.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart index 90c892108..12df281b8 100644 --- a/pkgs/mime/lib/mime.dart +++ b/pkgs/mime/lib/mime.dart @@ -7,9 +7,6 @@ /// /// More details, including a list of types, are in the Wikipedia article /// [Internet media type](http://en.wikipedia.org/wiki/Internet_media_type). -/// For information on installing and importing this library, see the -/// [mime package on pub.dev] -/// (https://pub.dev/packages/mime). library mime; export 'src/mime_multipart_transformer.dart'; From e4eccdc77b60d340d53f43e9828b179b2a68d5d8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 29 May 2019 10:51:36 -0700 Subject: [PATCH 048/118] Add more details to package description --- pkgs/mime/pubspec.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index b1685bc70..834954e22 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,7 +1,9 @@ name: mime version: 0.9.7-dev -description: Helper-package for working with MIME. +description: >- + Utilities for handling media (MIME) types, including determining a type from + a file extension and file contents. author: Dart Team homepage: https://www.github.com/dart-lang/mime From 365ac8f6a7cd7ef735a1aaf2bba499e7e641911b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 29 May 2019 10:55:28 -0700 Subject: [PATCH 049/118] Add example, fix readme --- pkgs/mime/README.md | 15 ++++++++++++--- pkgs/mime/example/example.dart | 12 ++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 pkgs/mime/example/example.dart diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index 4c8f313f2..fc82c25c4 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -14,9 +14,18 @@ the top level function `lookupMimeType`. This builtin instance has the most common file name extensions and magic bytes registered. ```dart -print(lookupMimeType('test.html')); // Will print text/html -print(lookupMimeType('test', [0xFF, 0xD8])); // Will print image/jpeg -print(lookupMimeType('test.html', [0xFF, 0xD8])); // Will print image/jpeg +import 'package:mime/mime.dart'; + +void main() { + print(lookupMimeType('test.html')); + // text/html + + print(lookupMimeType('test', headerBytes: [0xFF, 0xD8])); + // image/jpeg + + print(lookupMimeType('test.html', headerBytes: [0xFF, 0xD8])); + // image/jpeg +} ``` You can build you own resolver by creating an instance of diff --git a/pkgs/mime/example/example.dart b/pkgs/mime/example/example.dart new file mode 100644 index 000000000..af14cb08c --- /dev/null +++ b/pkgs/mime/example/example.dart @@ -0,0 +1,12 @@ +import 'package:mime/mime.dart'; + +void main() { + print(lookupMimeType('test.html')); + // text/html + + print(lookupMimeType('test', headerBytes: [0xFF, 0xD8])); + // image/jpeg + + print(lookupMimeType('test.html', headerBytes: [0xFF, 0xD8])); + // image/jpeg +} From 294b59e5b862b893a3e19a2af7ba6921ec5c8313 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 29 May 2019 10:58:04 -0700 Subject: [PATCH 050/118] Prepare to release 0.9.6+3 --- pkgs/mime/CHANGELOG.md | 2 ++ pkgs/mime/README.md | 1 + pkgs/mime/pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 88fd3eeac..ac2914747 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,6 +1,8 @@ # 0.9.6+3 * Change the mime type for Dart source from `application/dart` to `text/x-dart`. +* Add example. +* Fix links and code in README. # 0.9.6+2 diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index fc82c25c4..53abf8cf1 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -1,3 +1,4 @@ +[![Pub Package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) [![Build Status](https://travis-ci.org/dart-lang/mime.svg?branch=master)](https://travis-ci.org/dart-lang/mime) Package for working with MIME type definitions and for processing diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 834954e22..e4038a7e2 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.7-dev +version: 0.9.6+3 description: >- Utilities for handling media (MIME) types, including determining a type from From d42ee299bbbf335938ad5043129f8d326b8fcde0 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 9 Dec 2019 09:57:18 -0800 Subject: [PATCH 051/118] Fix latest lints, remove author from pubspec (dart-lang/mime#30) --- pkgs/mime/lib/src/bound_multipart_stream.dart | 28 ++-- pkgs/mime/lib/src/magic_number.dart | 2 +- .../lib/src/mime_multipart_transformer.dart | 1 + pkgs/mime/lib/src/mime_shared.dart | 5 +- pkgs/mime/lib/src/mime_type.dart | 2 +- pkgs/mime/pubspec.yaml | 3 +- .../test/mime_multipart_transformer_test.dart | 132 +++++++++--------- 7 files changed, 88 insertions(+), 85 deletions(-) diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index 4b32ef934..07418b248 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -45,24 +45,26 @@ int _toLowerCase(int byte) { void _expectByteValue(int val1, int val2) { if (val1 != val2) { - throw MimeMultipartException("Failed to parse multipart mime 1"); + throw MimeMultipartException('Failed to parse multipart mime 1'); } } void _expectWhitespace(int byte) { if (byte != CharCode.SP && byte != CharCode.HT) { - throw MimeMultipartException("Failed to parse multipart mime 2"); + throw MimeMultipartException('Failed to parse multipart mime 2'); } } class _MimeMultipart extends MimeMultipart { + @override final Map headers; final Stream> _stream; _MimeMultipart(this.headers, this._stream); - StreamSubscription> listen(void onData(List data), - {void onDone(), Function onError, bool cancelOnError}) { + @override + StreamSubscription> listen(void Function(List data) onData, + {void Function() onDone, Function onError, bool cancelOnError}) { return _stream.listen(onData, onDone: onDone, onError: onError, cancelOnError: cancelOnError); } @@ -137,7 +139,7 @@ class BoundMultipartStream { }, onDone: () { if (_state != _DONE) { _controller - .addError(MimeMultipartException("Bad multipart ending")); + .addError(MimeMultipartException('Bad multipart ending')); } _controller.close(); }, onError: _controller.addError); @@ -168,14 +170,14 @@ class BoundMultipartStream { _subscription.cancel(); break; default: - throw StateError("This code should never be reached."); + throw StateError('This code should never be reached.'); } } } void _parse() { // Number of boundary bytes to artificially place before the supplied data. - int boundaryPrefix = 0; + var boundaryPrefix = 0; // Position where content starts. Will be null if no known content // start exists. Will be negative of the content starts in the // boundary prefix. Will be zero or position if the content starts @@ -209,7 +211,7 @@ class BoundMultipartStream { } else { contentStartIndex = null; } - // The data to parse might be "artificially" prefixed with a + // The data to parse might be 'artificially' prefixed with a // partial match of the boundary. boundaryPrefix = _boundaryIndex; @@ -256,7 +258,7 @@ class BoundMultipartStream { break; case _HEADER_START: - _headers = Map(); + _headers = {}; if (byte == CharCode.CR) { _state = _HEADER_ENDING; } else { @@ -271,7 +273,7 @@ class BoundMultipartStream { _state = _HEADER_VALUE_START; } else { if (!_isTokenChar(byte)) { - throw MimeMultipartException("Invalid header field name"); + throw MimeMultipartException('Invalid header field name'); } _headerField.add(_toLowerCase(byte)); } @@ -304,8 +306,8 @@ class BoundMultipartStream { if (byte == CharCode.SP || byte == CharCode.HT) { _state = _HEADER_VALUE_START; } else { - String headerField = utf8.decode(_headerField); - String headerValue = utf8.decode(_headerValue); + var headerField = utf8.decode(_headerField); + var headerValue = utf8.decode(_headerValue); _headers[headerField.toLowerCase()] = headerValue; _headerField.clear(); _headerValue.clear(); @@ -353,7 +355,7 @@ class BoundMultipartStream { } else { // Restart matching of the boundary. _index = _index - _boundaryIndex; - if (contentStartIndex == null) contentStartIndex = _index; + contentStartIndex ??= _index; _boundaryIndex = 0; } break; diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index d490346b5..50be18a99 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -14,7 +14,7 @@ class MagicNumber { bool matches(List header) { if (header.length < numbers.length) return false; - for (int i = 0; i < numbers.length; i++) { + for (var i = 0; i < numbers.length; i++) { if (mask != null) { if ((mask[i] & numbers[i]) != (mask[i] & header[i])) return false; } else { diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart index 5509339fc..1869480a4 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -37,6 +37,7 @@ class MimeMultipartTransformer MimeMultipartTransformer(String boundary) : _boundary = _getBoundary(boundary); + @override Stream bind(Stream> stream) { return BoundMultipartStream(_boundary, stream).stream; } diff --git a/pkgs/mime/lib/src/mime_shared.dart b/pkgs/mime/lib/src/mime_shared.dart index 5cc6a8f40..00ade1daa 100644 --- a/pkgs/mime/lib/src/mime_shared.dart +++ b/pkgs/mime/lib/src/mime_shared.dart @@ -8,9 +8,10 @@ import 'dart:async'; class MimeMultipartException implements Exception { final String message; - const MimeMultipartException([this.message = ""]); + const MimeMultipartException([this.message = '']); - String toString() => "MimeMultipartException: $message"; + @override + String toString() => 'MimeMultipartException: $message'; } /// A Mime Multipart class representing each part parsed by diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index 6fbe270ca..84ac3066f 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -104,7 +104,7 @@ class MimeTypeResolver { } static String _ext(String path) { - int index = path.lastIndexOf('.'); + var index = path.lastIndexOf('.'); if (index < 0 || index + 1 >= path.length) return path; return path.substring(index + 1).toLowerCase(); } diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index e4038a7e2..b0c21b38b 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,10 +1,9 @@ name: mime -version: 0.9.6+3 +version: 0.9.7-dev description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. -author: Dart Team homepage: https://www.github.com/dart-lang/mime environment: diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index be8ca178c..fbfe2b649 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -5,16 +5,16 @@ import 'dart:async'; import 'dart:math'; -import "package:test/test.dart"; -import "package:mime/mime.dart"; +import 'package:test/test.dart'; +import 'package:mime/mime.dart'; void _writeInChunks( List data, int chunkSize, StreamController> controller) { if (chunkSize == -1) chunkSize = data.length; - for (int pos = 0; pos < data.length; pos += chunkSize) { - int remaining = data.length - pos; - int writeLength = min(chunkSize, remaining); + for (var pos = 0; pos < data.length; pos += chunkSize) { + var remaining = data.length - pos; + var writeLength = min(chunkSize, remaining); controller.add(data.sublist(pos, pos + writeLength)); } controller.close(); @@ -29,11 +29,11 @@ void _runParseTest(String message, String boundary, TestMode mode, var stream = controller.stream.transform(MimeMultipartTransformer(boundary)); - int i = 0; + var i = 0; var completer = Completer(); var futures = []; stream.listen((multipart) { - int part = i++; + var part = i++; if (expectedHeaders != null) { expect(multipart.headers, equals(expectedHeaders[part])); } @@ -121,10 +121,10 @@ void _runParseTest(String message, String boundary, TestMode mode, var stream = controller.stream.transform(MimeMultipartTransformer(boundary)); var subscription; - int i = 0; + var i = 0; var futures = []; subscription = stream.listen((multipart) { - int partIndex = i; + var partIndex = i; if (partIndex >= parts) { throw StateError('Expected no more parts, but got one.'); @@ -153,7 +153,7 @@ void _runParseTest(String message, String boundary, TestMode mode, // Test parsing the data three times delivering the data in // different chunks. - List data = message.codeUnits; + var data = message.codeUnits; test('test', () { expect( Future.wait([ @@ -178,7 +178,7 @@ void _runParseTest(String message, String boundary, TestMode mode, }); test('test-n-parts-only', () { - int numPartsExpected = expectedParts.length - 1; + var numPartsExpected = expectedParts.length - 1; if (numPartsExpected == 0) numPartsExpected = 1; expect( @@ -206,10 +206,10 @@ void _testParse(String message, String boundary, void _testParseValid() { // Empty message from Chrome form post. var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; - _testParse(message, "----WebKitFormBoundaryU3FBruSkJKG0Yor1", [], []); + _testParse(message, '----WebKitFormBoundaryU3FBruSkJKG0Yor1', [], []); // Sample from Wikipedia. - message = """ + message = ''' This is a message with multiple parts in MIME format.\r --frontier\r Content-Type: text/plain\r @@ -221,20 +221,20 @@ Content-Transfer-Encoding: base64\r \r PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\r ---frontier--\r\n"""; - var headers1 = {"content-type": "text/plain"}; +--frontier--\r\n'''; + var headers1 = {'content-type': 'text/plain'}; var headers2 = { - "content-type": "application/octet-stream", - "content-transfer-encoding": "base64" + 'content-type': 'application/octet-stream', + 'content-transfer-encoding': 'base64' }; - var body1 = "This is the body of the message."; - var body2 = """ + var body1 = 'This is the body of the message.'; + var body2 = ''' PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg -Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg="""; - _testParse(message, "frontier", [headers1, headers2], [body1, body2]); +Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg='''; + _testParse(message, 'frontier', [headers1, headers2], [body1, body2]); // Sample from HTML 4.01 Specification. - message = """ + message = ''' \r\n--AaB03x\r Content-Disposition: form-data; name=\"submit-name\"\r \r @@ -244,17 +244,17 @@ Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"\r Content-Type: text/plain\r \r ... contents of file1.txt ...\r ---AaB03x--\r\n"""; +--AaB03x--\r\n'''; headers1 = { - "content-disposition": "form-data; name=\"submit-name\"" + 'content-disposition': 'form-data; name=\"submit-name\"' }; headers2 = { - "content-type": "text/plain", - "content-disposition": "form-data; name=\"files\"; filename=\"file1.txt\"" + 'content-type': 'text/plain', + 'content-disposition': 'form-data; name=\"files\"; filename=\"file1.txt\"' }; - body1 = "Larry"; - body2 = "... contents of file1.txt ..."; - _testParse(message, "AaB03x", [headers1, headers2], [body1, body2]); + body1 = 'Larry'; + body2 = '... contents of file1.txt ...'; + _testParse(message, 'AaB03x', [headers1, headers2], [body1, body2]); // Longer form from submitting the following from Chrome. // @@ -262,19 +262,19 @@ Content-Type: text/plain\r // //
+ // method='post'> //

- // Text: - // Password: - // Checkbox: - // Radio: - // Send + // Text: + // Password: + // Checkbox: + // Radio: + // Send //

//
// // - message = """ + message = ''' \r\n------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r Content-Disposition: form-data; name=\"text_input\"\r \r @@ -291,28 +291,28 @@ on\r Content-Disposition: form-data; name=\"radio_input\"\r \r on\r -------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n"""; +------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n'''; headers1 = { - "content-disposition": "form-data; name=\"text_input\"" + 'content-disposition': 'form-data; name=\"text_input\"' }; headers2 = { - "content-disposition": "form-data; name=\"password_input\"" + 'content-disposition': 'form-data; name=\"password_input\"' }; var headers3 = { - "content-disposition": "form-data; name=\"checkbox_input\"" + 'content-disposition': 'form-data; name=\"checkbox_input\"' }; var headers4 = { - "content-disposition": "form-data; name=\"radio_input\"" + 'content-disposition': 'form-data; name=\"radio_input\"' }; - body1 = "text"; - body2 = "password"; - var body3 = "on"; - var body4 = "on"; - _testParse(message, "----WebKitFormBoundaryQ3cgYAmGRF8yOeYB", + body1 = 'text'; + body2 = 'password'; + var body3 = 'on'; + var body4 = 'on'; + _testParse(message, '----WebKitFormBoundaryQ3cgYAmGRF8yOeYB', [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); // Same form from Firefox. - message = """ + message = ''' \r\n-----------------------------52284550912143824192005403738\r Content-Disposition: form-data; name=\"text_input\"\r \r @@ -329,15 +329,15 @@ on\r Content-Disposition: form-data; name=\"radio_input\"\r \r on\r ------------------------------52284550912143824192005403738--\r\n"""; +-----------------------------52284550912143824192005403738--\r\n'''; _testParse( message, - "---------------------------52284550912143824192005403738", + '---------------------------52284550912143824192005403738', [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); // And Internet Explorer - message = """ + message = ''' \r\n-----------------------------7dc8f38c60326\r Content-Disposition: form-data; name=\"text_input\"\r \r @@ -354,12 +354,12 @@ on\r Content-Disposition: form-data; name=\"radio_input\"\r \r on\r ------------------------------7dc8f38c60326--\r\n"""; - _testParse(message, "---------------------------7dc8f38c60326", +-----------------------------7dc8f38c60326--\r\n'''; + _testParse(message, '---------------------------7dc8f38c60326', [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); // Test boundary prefix inside prefix and content. - message = """ + message = ''' -\r --\r --b\r @@ -393,9 +393,9 @@ Content-Type: text/plain\r --b\r\r\r\r --\r\r\r -\r\r ---boundary--\r\n"""; - var headers = {"content-type": "text/plain"}; - body1 = """ +--boundary--\r\n'''; + var headers = {'content-type': 'text/plain'}; + body1 = ''' -\r --\r --b\r @@ -404,8 +404,8 @@ Content-Type: text/plain\r --boun\r --bound\r\r --bounda\r\r\r ---boundar\r\r\r"""; - body2 = """ +--boundar\r\r\r'''; + body2 = ''' --boundar\r --bounda\r --bound\r @@ -414,11 +414,11 @@ Content-Type: text/plain\r --bo\r --b\r\r\r\r --\r\r\r --\r"""; - _testParse(message, "boundary", [headers, headers], [body1, body2]); +-\r'''; + _testParse(message, 'boundary', [headers, headers], [body1, body2]); // Without initial CRLF. - message = """ + message = ''' --xxx\r \r \r @@ -427,13 +427,13 @@ Body 1\r \r \r Body2\r ---xxx--\r\n"""; - _testParse(message, "xxx", null, ["\r\nBody 1", "\r\nBody2"]); +--xxx--\r\n'''; + _testParse(message, 'xxx', null, ['\r\nBody 1', '\r\nBody2']); } void _testParseInvalid() { // Missing end boundary. - var message = """ + var message = ''' \r --xxx\r \r @@ -443,8 +443,8 @@ Body 1\r \r \r Body2\r ---xxx\r\n"""; - _testParse(message, "xxx", null, [null, null], true); +--xxx\r\n'''; + _testParse(message, 'xxx', null, [null, null], true); } void main() { From f0d744b86519b45192207b82b3ca9455f305982f Mon Sep 17 00:00:00 2001 From: Kenzie Schmoll Date: Mon, 10 Aug 2020 14:50:24 -0700 Subject: [PATCH 052/118] Add `extensionFromMime` utility. --- pkgs/mime/CHANGELOG.md | 3 +++ pkgs/mime/lib/src/default_extension_map.dart | 3 +-- pkgs/mime/lib/src/mime_type.dart | 13 +++++++++++++ pkgs/mime/pubspec.yaml | 2 +- pkgs/mime/test/mime_type_test.dart | 18 ++++++++++++++++++ 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index ac2914747..a0ca55232 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,6 @@ +# 0.9.7 +* Add `extensionFromMime` utility function. + # 0.9.6+3 * Change the mime type for Dart source from `application/dart` to `text/x-dart`. diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index c7add4834..d951b23b5 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -4,8 +4,7 @@ library mime.extension_map; -// TODO(ajohnsen): Use const map once Issue 7559 is fixed. -final Map defaultExtensionMap = { +const Map defaultExtensionMap = { '123': 'application/vnd.lotus-1-2-3', '3dml': 'text/vnd.in3d.3dml', '3ds': 'image/x-3ds', diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index 84ac3066f..2894052dc 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -25,6 +25,19 @@ int get defaultMagicNumbersMaxLength => _globalResolver.magicNumbersMaxLength; String lookupMimeType(String path, {List headerBytes}) => _globalResolver.lookup(path, headerBytes: headerBytes); +/// Returns the extension for the given MIME type. +/// +/// If there are multiple extensions for [mime], return the first occurrence in +/// the map. If there are no extensions for [mime], return [mime]. +String extensionFromMime(String mime) { + for (final key in defaultExtensionMap.keys) { + if (defaultExtensionMap[key].toLowerCase() == mime.toLowerCase()) { + return key; + } + } + return mime; +} + /// MIME-type resolver class, used to customize the lookup of mime-types. class MimeTypeResolver { final Map _extensionMap = {}; diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index b0c21b38b..16c6876a0 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.7-dev +version: 0.9.7 description: >- Utilities for handling media (MIME) types, including determining a type from diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 9d027728f..7f9169cb7 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -123,4 +123,22 @@ void main() { expect(defaultMagicNumbersMaxLength, actualMaxBytes); }); + + group('extensionFromMime', () { + test('returns match for mime with single extension', () { + expect(extensionFromMime('application/json'), equals('json')); + expect(extensionFromMime('application/java-archive'), equals('jar')); + }); + + test('returns first match for mime with multiple extensions', () { + expect(extensionFromMime('text/html'), equals('htm')); + expect(extensionFromMime('application/x-cbr'), equals('cb7')); + }); + + test('returns inputted string for unrecognized mime', () { + expect( + extensionFromMime('unrecognized_mime'), equals('unrecognized_mime')); + expect(extensionFromMime('i/am/not/a/mime'), equals('i/am/not/a/mime')); + }); + }); } From d7ac049aa66200f9f562dcf4f4508f83f6860484 Mon Sep 17 00:00:00 2001 From: Kenzie Schmoll Date: Mon, 10 Aug 2020 16:30:55 -0700 Subject: [PATCH 053/118] review comments --- pkgs/mime/lib/src/mime_type.dart | 7 ++++--- pkgs/mime/test/default_extension_map_test.dart | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 pkgs/mime/test/default_extension_map_test.dart diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index 2894052dc..3b220e709 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -30,9 +30,10 @@ String lookupMimeType(String path, {List headerBytes}) => /// If there are multiple extensions for [mime], return the first occurrence in /// the map. If there are no extensions for [mime], return [mime]. String extensionFromMime(String mime) { - for (final key in defaultExtensionMap.keys) { - if (defaultExtensionMap[key].toLowerCase() == mime.toLowerCase()) { - return key; + mime = mime.toLowerCase(); + for (final entry in defaultExtensionMap.entries) { + if (defaultExtensionMap[entry.key] == mime) { + return entry.key; } } return mime; diff --git a/pkgs/mime/test/default_extension_map_test.dart b/pkgs/mime/test/default_extension_map_test.dart new file mode 100644 index 000000000..b5539dd48 --- /dev/null +++ b/pkgs/mime/test/default_extension_map_test.dart @@ -0,0 +1,16 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:mime/src/default_extension_map.dart'; +import 'package:test/test.dart'; + +void main() { + group('defaultExtensionMap', () { + test('keys are lowercase', () { + for (final key in defaultExtensionMap.keys) { + expect(key, equals(key.toLowerCase())); + } + }); + }); +} From c5507487bcb085793c39344e1620d2b2b72844f8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 15 Sep 2020 10:03:36 -0700 Subject: [PATCH 054/118] pubspec.yaml: fix homepage --- pkgs/mime/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 16c6876a0..0cc27aafc 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,10 +1,10 @@ name: mime -version: 0.9.7 +version: 0.9.8-dev description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. -homepage: https://www.github.com/dart-lang/mime +homepage: https://github.com/dart-lang/mime environment: sdk: '>=2.0.0 <3.0.0' From 77c343605a6df2d1f3c123e021f1db3c5bb496c5 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 22 Sep 2020 13:18:49 -0700 Subject: [PATCH 055/118] Remove unneeded dart:async import Since Dart 2.1, Future and Stream have been exported from dart:core. Alternatively, if for some reason this package needs to continue to support Dart 2.0, an exception can be made for this internally. --- pkgs/mime/.travis.yml | 2 +- pkgs/mime/lib/src/mime_shared.dart | 2 -- pkgs/mime/pubspec.yaml | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pkgs/mime/.travis.yml b/pkgs/mime/.travis.yml index 8a365297a..e1bb9d981 100644 --- a/pkgs/mime/.travis.yml +++ b/pkgs/mime/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: -- 2.0.0 +- 2.1.0 - dev dart_task: diff --git a/pkgs/mime/lib/src/mime_shared.dart b/pkgs/mime/lib/src/mime_shared.dart index 00ade1daa..61e81f247 100644 --- a/pkgs/mime/lib/src/mime_shared.dart +++ b/pkgs/mime/lib/src/mime_shared.dart @@ -3,8 +3,6 @@ // BSD-style license that can be found in the LICENSE file. library mime.shared; -import 'dart:async'; - class MimeMultipartException implements Exception { final String message; diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 0cc27aafc..17d31e1c9 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -7,7 +7,7 @@ description: >- homepage: https://github.com/dart-lang/mime environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.1.0 <3.0.0' dev_dependencies: pedantic: ^1.0.0 From 87aa2cc038f31e3e93b7c2d604855b66b512adc7 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 12 Nov 2020 18:39:49 -0800 Subject: [PATCH 056/118] Cleanup in BoundMultipartStream (dart-lang/mime#35) Start to make the code a little easier to understand, and fix some style. - Initialize the `_controller` field in place and make it final. Set the callbacks in the constructor rather than instantiate in the constructor. This will prevent it from needing to be `late`. - Assign `boundaryPrefix`, `contentStartIndex`, and `byte` variables where they are declared rather than separate the declaration and initialization. Style fixes: - Use doc comments. - Remove unnecessary parens in while loop condition. - Remove unnecessary library directive. --- pkgs/mime/lib/src/bound_multipart_stream.dart | 84 ++++++++----------- 1 file changed, 37 insertions(+), 47 deletions(-) diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index 07418b248..71c77f97d 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -1,7 +1,6 @@ // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library mime.bound_multipart_stream; import 'dart:async'; import 'dart:convert'; @@ -9,7 +8,7 @@ import 'dart:convert'; import 'char_code.dart'; import 'mime_shared.dart'; -// Bytes for '()<>@,;:\\"/[]?={} \t'. +/// Bytes for '()<>@,;:\\"/[]?={} \t'. const _SEPARATORS = [ 40, 41, @@ -102,7 +101,7 @@ class BoundMultipartStream { int _controllerState = _CONTROLLER_STATE_IDLE; - StreamController _controller; + final _controller = StreamController(sync: true); Stream get stream => _controller.stream; @@ -114,36 +113,37 @@ class BoundMultipartStream { int _state = _START; int _boundaryIndex = 2; - // Current index in the data buffer. If index is negative then it - // is the index into the artificial prefix of the boundary string. + /// Current index into [_buffer]. + /// + /// If index is negative then it is the index into the artificial prefix of + /// the boundary string. int _index; List _buffer; BoundMultipartStream(this._boundary, Stream> stream) { - _controller = StreamController( - sync: true, - onPause: _pauseStream, - onResume: _resumeStream, - onCancel: () { - _controllerState = _CONTROLLER_STATE_CANCELED; - _tryPropagateControllerState(); - }, - onListen: () { - _controllerState = _CONTROLLER_STATE_ACTIVE; - _subscription = stream.listen((data) { - assert(_buffer == null); - _subscription.pause(); - _buffer = data; - _index = 0; - _parse(); - }, onDone: () { - if (_state != _DONE) { - _controller - .addError(MimeMultipartException('Bad multipart ending')); - } - _controller.close(); - }, onError: _controller.addError); - }); + _controller + ..onPause = _pauseStream + ..onResume = _resumeStream + ..onCancel = () { + _controllerState = _CONTROLLER_STATE_CANCELED; + _tryPropagateControllerState(); + } + ..onListen = () { + _controllerState = _CONTROLLER_STATE_ACTIVE; + _subscription = stream.listen((data) { + assert(_buffer == null); + _subscription.pause(); + _buffer = data; + _index = 0; + _parse(); + }, onDone: () { + if (_state != _DONE) { + _controller + .addError(MimeMultipartException('Bad multipart ending')); + } + _controller.close(); + }, onError: _controller.addError); + }; } void _resumeStream() { @@ -177,12 +177,15 @@ class BoundMultipartStream { void _parse() { // Number of boundary bytes to artificially place before the supplied data. - var boundaryPrefix = 0; + // The data to parse might be 'artificially' prefixed with a + // partial match of the boundary. + var boundaryPrefix = _boundaryIndex; // Position where content starts. Will be null if no known content // start exists. Will be negative of the content starts in the // boundary prefix. Will be zero or position if the content starts // in the current buffer. - int contentStartIndex; + var contentStartIndex = + _state == _CONTENT && _boundaryIndex == 0 ? 0 : null; // Function to report content data for the current part. The data // reported is from the current content start index up til the @@ -206,22 +209,9 @@ class BoundMultipartStream { } } - if (_state == _CONTENT && _boundaryIndex == 0) { - contentStartIndex = 0; - } else { - contentStartIndex = null; - } - // The data to parse might be 'artificially' prefixed with a - // partial match of the boundary. - boundaryPrefix = _boundaryIndex; - - while ((_index < _buffer.length) && _state != _FAIL && _state != _DONE) { - int byte; - if (_index < 0) { - byte = _boundary[boundaryPrefix + _index]; - } else { - byte = _buffer[_index]; - } + while (_index < _buffer.length && _state != _FAIL && _state != _DONE) { + var byte = + _index < 0 ? _boundary[boundaryPrefix + _index] : _buffer[_index]; switch (_state) { case _START: if (byte == _boundary[_boundaryIndex]) { From 387d5d2a056a3a77cb685e8a32b520bef07a194a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 12 Nov 2020 20:22:33 -0800 Subject: [PATCH 057/118] Delete .test_config --- pkgs/mime/.test_config | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/mime/.test_config diff --git a/pkgs/mime/.test_config b/pkgs/mime/.test_config deleted file mode 100644 index 412fc5c5c..000000000 --- a/pkgs/mime/.test_config +++ /dev/null @@ -1,3 +0,0 @@ -{ - "test_package": true -} \ No newline at end of file From e40a10362fd2bcfb939710dd6e8dea959651a0b6 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 8 Dec 2020 12:05:29 -0800 Subject: [PATCH 058/118] migrate to null safety (dart-lang/mime#37) --- pkgs/mime/.travis.yml | 1 - pkgs/mime/CHANGELOG.md | 5 +++ pkgs/mime/lib/src/bound_multipart_stream.dart | 43 ++++++++++--------- pkgs/mime/lib/src/magic_number.dart | 4 +- pkgs/mime/lib/src/mime_type.dart | 10 ++--- pkgs/mime/pubspec.yaml | 12 ++++-- .../test/mime_multipart_transformer_test.dart | 38 +++++++++------- pkgs/mime/test/mime_type_test.dart | 6 +-- 8 files changed, 68 insertions(+), 51 deletions(-) diff --git a/pkgs/mime/.travis.yml b/pkgs/mime/.travis.yml index e1bb9d981..2acf002e7 100644 --- a/pkgs/mime/.travis.yml +++ b/pkgs/mime/.travis.yml @@ -1,7 +1,6 @@ language: dart dart: -- 2.1.0 - dev dart_task: diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index a0ca55232..648f9d5ef 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,4 +1,9 @@ +# 1.0.0-nullsafety.0 + +* Update to null safety + # 0.9.7 + * Add `extensionFromMime` utility function. # 0.9.6+3 diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index 71c77f97d..73bc49560 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -62,8 +62,8 @@ class _MimeMultipart extends MimeMultipart { _MimeMultipart(this.headers, this._stream); @override - StreamSubscription> listen(void Function(List data) onData, - {void Function() onDone, Function onError, bool cancelOnError}) { + StreamSubscription> listen(void Function(List data)? onData, + {void Function()? onDone, Function? onError, bool? cancelOnError}) { return _stream.listen(onData, onDone: onDone, onError: onError, cancelOnError: cancelOnError); } @@ -105,10 +105,10 @@ class BoundMultipartStream { Stream get stream => _controller.stream; - StreamSubscription _subscription; + late StreamSubscription _subscription; - StreamController> _multipartController; - Map _headers; + StreamController>? _multipartController; + Map? _headers; int _state = _START; int _boundaryIndex = 2; @@ -117,8 +117,8 @@ class BoundMultipartStream { /// /// If index is negative then it is the index into the artificial prefix of /// the boundary string. - int _index; - List _buffer; + int _index = 0; + List _buffer = _placeholderBuffer; BoundMultipartStream(this._boundary, Stream> stream) { _controller @@ -131,7 +131,7 @@ class BoundMultipartStream { ..onListen = () { _controllerState = _CONTROLLER_STATE_ACTIVE; _subscription = stream.listen((data) { - assert(_buffer == null); + assert(_buffer == _placeholderBuffer); _subscription.pause(); _buffer = data; _index = 0; @@ -193,18 +193,18 @@ class BoundMultipartStream { // prefix of the boundary both the content start index and index // can be negative. void reportData() { - if (contentStartIndex < 0) { + if (contentStartIndex! < 0) { var contentLength = boundaryPrefix + _index - _boundaryIndex; if (contentLength <= boundaryPrefix) { - _multipartController.add(_boundary.sublist(0, contentLength)); + _multipartController!.add(_boundary.sublist(0, contentLength)); } else { - _multipartController.add(_boundary.sublist(0, boundaryPrefix)); - _multipartController + _multipartController!.add(_boundary.sublist(0, boundaryPrefix)); + _multipartController! .add(_buffer.sublist(0, contentLength - boundaryPrefix)); } } else { var contentEndIndex = _index - _boundaryIndex; - _multipartController + _multipartController! .add(_buffer.sublist(contentStartIndex, contentEndIndex)); } } @@ -239,8 +239,8 @@ class BoundMultipartStream { case _BOUNDARY_END: _expectByteValue(byte, CharCode.LF); + _multipartController?.close(); if (_multipartController != null) { - _multipartController.close(); _multipartController = null; _tryPropagateControllerState(); } @@ -298,7 +298,7 @@ class BoundMultipartStream { } else { var headerField = utf8.decode(_headerField); var headerValue = utf8.decode(_headerValue); - _headers[headerField.toLowerCase()] = headerValue; + _headers![headerField.toLowerCase()] = headerValue; _headerField.clear(); _headerValue.clear(); if (byte == CharCode.CR) { @@ -321,7 +321,7 @@ class BoundMultipartStream { onPause: _subscription.pause, onResume: _subscription.resume); _controller - .add(_MimeMultipart(_headers, _multipartController.stream)); + .add(_MimeMultipart(_headers!, _multipartController!.stream)); _headers = null; _state = _CONTENT; contentStartIndex = _index + 1; @@ -336,7 +336,7 @@ class BoundMultipartStream { reportData(); _index--; } - _multipartController.close(); + _multipartController!.close(); _multipartController = null; _tryPropagateControllerState(); _boundaryIndex = 0; @@ -365,8 +365,8 @@ class BoundMultipartStream { case _LAST_BOUNDARY_END: _expectByteValue(byte, CharCode.LF); + _multipartController?.close(); if (_multipartController != null) { - _multipartController.close(); _multipartController = null; _tryPropagateControllerState(); } @@ -390,9 +390,12 @@ class BoundMultipartStream { // Resume if at end. if (_index == _buffer.length) { - _buffer = null; - _index = null; + _buffer = _placeholderBuffer; + _index = 0; _subscription.resume(); } } } + +// Used as a placeholder instead of having a nullable buffer. +const _placeholderBuffer = []; diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 50be18a99..89336775c 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -7,7 +7,7 @@ library mime.magic_number; class MagicNumber { final String mimeType; final List numbers; - final List mask; + final List? mask; const MagicNumber(this.mimeType, this.numbers, {this.mask}); @@ -16,7 +16,7 @@ class MagicNumber { for (var i = 0; i < numbers.length; i++) { if (mask != null) { - if ((mask[i] & numbers[i]) != (mask[i] & header[i])) return false; + if ((mask![i] & numbers[i]) != (mask![i] & header[i])) return false; } else { if (numbers[i] != header[i]) return false; } diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index 3b220e709..14db94233 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -22,7 +22,7 @@ int get defaultMagicNumbersMaxLength => _globalResolver.magicNumbersMaxLength; /// a file have been saved using the wrong file-name extension. If less than /// [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't /// be matched against. -String lookupMimeType(String path, {List headerBytes}) => +String? lookupMimeType(String path, {List? headerBytes}) => _globalResolver.lookup(path, headerBytes: headerBytes); /// Returns the extension for the given MIME type. @@ -69,8 +69,8 @@ class MimeTypeResolver { /// though a file have been saved using the wrong file-name extension. If less /// than [magicNumbersMaxLength] bytes was provided, some magic-numbers won't /// be matched against. - String lookup(String path, {List headerBytes}) { - String result; + String? lookup(String path, {List? headerBytes}) { + String? result; if (headerBytes != null) { result = _matchMagic(headerBytes, _magicNumbers); if (result != null) return result; @@ -99,7 +99,7 @@ class MimeTypeResolver { /// /// If [mask] is present,the [mask] is used to only perform matching on /// selective bits. The [mask] must have the same length as [bytes]. - void addMagicNumber(List bytes, String mimeType, {List mask}) { + void addMagicNumber(List bytes, String mimeType, {List? mask}) { if (mask != null && bytes.length != mask.length) { throw ArgumentError('Bytes and mask are of different lengths'); } @@ -109,7 +109,7 @@ class MimeTypeResolver { _magicNumbers.add(MagicNumber(mimeType, bytes, mask: mask)); } - static String _matchMagic( + static String? _matchMagic( List headerBytes, List magicNumbers) { for (var mn in magicNumbers) { if (mn.matches(headerBytes)) return mn.mimeType; diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 17d31e1c9..6840fa957 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 0.9.8-dev +version: 1.0.0-nullsafety.0 description: >- Utilities for handling media (MIME) types, including determining a type from @@ -7,8 +7,12 @@ description: >- homepage: https://github.com/dart-lang/mime environment: - sdk: '>=2.1.0 <3.0.0' + sdk: '>=2.12.0-0 <3.0.0' dev_dependencies: - pedantic: ^1.0.0 - test: ^1.2.0 + pedantic: ^1.10.0-nullsafety + test: ^1.16.0-nullsafety + +dependency_overrides: + # Required due to package:test cycle. + shelf_static: ^0.2.8 diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index fbfe2b649..6043d604a 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -23,7 +23,9 @@ void _writeInChunks( enum TestMode { IMMEDIATE_LISTEN, DELAY_LISTEN, PAUSE_RESUME } void _runParseTest(String message, String boundary, TestMode mode, - [List expectedHeaders, List expectedParts, bool expectError = false]) { + [List? expectedHeaders, + List? expectedParts, + bool expectError = false]) { Future testWrite(List data, [int chunkSize = -1]) { var controller = StreamController>(sync: true); @@ -39,20 +41,20 @@ void _runParseTest(String message, String boundary, TestMode mode, } switch (mode) { case TestMode.IMMEDIATE_LISTEN: - futures.add(multipart - .fold([], (buffer, data) => buffer..addAll(data)).then((data) { - if (expectedParts[part] != null) { - expect(data, equals(expectedParts[part].codeUnits)); + futures.add(multipart.fold>( + [], (buffer, data) => buffer..addAll(data)).then((data) { + if (expectedParts?[part] != null) { + expect(data, equals(expectedParts?[part].codeUnits)); } })); break; case TestMode.DELAY_LISTEN: futures.add(Future(() { - return multipart - .fold([], (buffer, data) => buffer..addAll(data)).then((data) { - if (expectedParts[part] != null) { - expect(data, equals(expectedParts[part].codeUnits)); + return multipart.fold>( + [], (buffer, data) => buffer..addAll(data)).then((data) { + if (expectedParts?[part] != null) { + expect(data, equals(expectedParts?[part].codeUnits)); } }); })); @@ -68,14 +70,14 @@ void _runParseTest(String message, String boundary, TestMode mode, subscription.pause(); Future(() => subscription.resume()); }, onDone: () { - if (expectedParts[part] != null) { - expect(buffer, equals(expectedParts[part].codeUnits)); + if (expectedParts?[part] != null) { + expect(buffer, equals(expectedParts?[part].codeUnits)); } completer.complete(); }); break; } - }, onError: (error) { + }, onError: (Object error) { if (!expectError) throw error; }, onDone: () { if (expectedParts != null) { @@ -100,7 +102,8 @@ void _runParseTest(String message, String boundary, TestMode mode, if (expectedHeaders != null) { expect(multipart.headers, equals(expectedHeaders[0])); } - return (multipart.fold([], (b, d) => b..addAll(d)).then((data) { + return (multipart + .fold>([], (b, d) => b..addAll(d)).then((data) { if (expectedParts != null && expectedParts[0] != null) { expect(data, equals(expectedParts[0].codeUnits)); } @@ -133,7 +136,8 @@ void _runParseTest(String message, String boundary, TestMode mode, if (expectedHeaders != null) { expect(multipart.headers, equals(expectedHeaders[partIndex])); } - futures.add((multipart.fold([], (b, d) => b..addAll(d)).then((data) { + futures.add( + (multipart.fold>([], (b, d) => b..addAll(d)).then((data) { if (expectedParts != null && expectedParts[partIndex] != null) { expect(data, equals(expectedParts[partIndex].codeUnits)); } @@ -165,7 +169,7 @@ void _runParseTest(String message, String boundary, TestMode mode, completes); }); - if (expectedParts.isNotEmpty) { + if (expectedParts!.isNotEmpty) { test('test-first-part-only', () { expect( Future.wait([ @@ -194,7 +198,9 @@ void _runParseTest(String message, String boundary, TestMode mode, } void _testParse(String message, String boundary, - [List expectedHeaders, List expectedParts, bool expectError = false]) { + [List? expectedHeaders, + List? expectedParts, + bool expectError = false]) { _runParseTest(message, boundary, TestMode.IMMEDIATE_LISTEN, expectedHeaders, expectedParts, expectError); _runParseTest(message, boundary, TestMode.DELAY_LISTEN, expectedHeaders, diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 7f9169cb7..992b73d20 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -8,9 +8,9 @@ import 'package:test/test.dart'; import 'package:mime/mime.dart'; import 'package:mime/src/magic_number.dart'; -void _expectMimeType(String path, String expectedMimeType, - {List headerBytes, MimeTypeResolver resolver}) { - String mimeType; +void _expectMimeType(String path, String? expectedMimeType, + {List? headerBytes, MimeTypeResolver? resolver}) { + String? mimeType; if (resolver == null) { mimeType = lookupMimeType(path, headerBytes: headerBytes); } else { From 2d741bfea03bc00d3485c3608d6531527466e7cc Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Mon, 1 Feb 2021 17:45:37 +0100 Subject: [PATCH 059/118] Migrate to GitHub Actions (dart-lang/mime#40) * Migrate to GitHub Actions * Delete .travis.yml * Replace Travis badge --- pkgs/mime/.github/workflows/test-package.yml | 61 ++++++++++++++++++++ pkgs/mime/.travis.yml | 22 ------- pkgs/mime/README.md | 2 +- 3 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 pkgs/mime/.github/workflows/test-package.yml delete mode 100644 pkgs/mime/.travis.yml diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml new file mode 100644 index 000000000..21a3c50b6 --- /dev/null +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -0,0 +1,61 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/mime/.travis.yml b/pkgs/mime/.travis.yml deleted file mode 100644 index 2acf002e7..000000000 --- a/pkgs/mime/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: dart - -dart: -- dev - -dart_task: -- test -- dartanalyzer: --fatal-infos --fatal-warnings . - -matrix: - include: - # Only validate formatting using the dev release - - dart: dev - dart_task: dartfmt - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index 53abf8cf1..3eeecd170 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -1,5 +1,5 @@ [![Pub Package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) -[![Build Status](https://travis-ci.org/dart-lang/mime.svg?branch=master)](https://travis-ci.org/dart-lang/mime) +[![Build Status](https://github.com/dart-lang/mime/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/mime/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) Package for working with MIME type definitions and for processing streams of MIME multipart media types. From 30c3847e6d728f4b94bf3380e00fcb42bc84742e Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 5 Feb 2021 11:05:08 -0800 Subject: [PATCH 060/118] stable null safety release (dart-lang/mime#41) --- pkgs/mime/CHANGELOG.md | 6 +++++- pkgs/mime/pubspec.yaml | 8 ++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 648f9d5ef..b77b2acec 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,6 +1,10 @@ +# 1.0.0 + +* Stable null safety release. + # 1.0.0-nullsafety.0 -* Update to null safety +* Update to null safety. # 0.9.7 diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 6840fa957..5d796ae2d 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 1.0.0-nullsafety.0 +version: 1.0.0 description: >- Utilities for handling media (MIME) types, including determining a type from @@ -10,9 +10,5 @@ environment: sdk: '>=2.12.0-0 <3.0.0' dev_dependencies: - pedantic: ^1.10.0-nullsafety + pedantic: ^1.10.0 test: ^1.16.0-nullsafety - -dependency_overrides: - # Required due to package:test cycle. - shelf_static: ^0.2.8 From 715561f6a4b663878d76882df2848787f4dc33d1 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Tue, 30 Mar 2021 16:14:12 -0700 Subject: [PATCH 061/118] Small change to LICENSE Changes to comply with open source review --- pkgs/mime/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/mime/LICENSE b/pkgs/mime/LICENSE index de31e1a0a..dbd2843a0 100644 --- a/pkgs/mime/LICENSE +++ b/pkgs/mime/LICENSE @@ -1,4 +1,5 @@ -Copyright 2015, the Dart project authors. All rights reserved. +Copyright 2015, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From 81be76b3be8826025f5a7e454a504fa5a96d031e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 20 Apr 2021 08:51:05 -0700 Subject: [PATCH 062/118] CI: latest setup, test oldest supported (dart-lang/mime#45) --- pkgs/mime/.github/workflows/test-package.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 21a3c50b6..e47bf6600 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,10 +47,10 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: ${{ matrix.sdk }} - id: install From ed4d6786b69972b885912e86d9425990197eeaee Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 26 Apr 2021 10:49:21 -0700 Subject: [PATCH 063/118] Fix newly enforced lint (dart-lang/mime#46) --- pkgs/mime/test/mime_multipart_transformer_test.dart | 2 +- pkgs/mime/test/mime_type_test.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 6043d604a..d503bcb71 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -5,8 +5,8 @@ import 'dart:async'; import 'dart:math'; -import 'package:test/test.dart'; import 'package:mime/mime.dart'; +import 'package:test/test.dart'; void _writeInChunks( List data, int chunkSize, StreamController> controller) { diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 992b73d20..a116bf3ca 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -4,9 +4,9 @@ import 'dart:math' as math; -import 'package:test/test.dart'; import 'package:mime/mime.dart'; import 'package:mime/src/magic_number.dart'; +import 'package:test/test.dart'; void _expectMimeType(String path, String? expectedMimeType, {List? headerBytes, MimeTypeResolver? resolver}) { From 3ee07cc115285d535eff904f8ebd575a06d79c92 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 21 Jun 2021 08:49:29 -0700 Subject: [PATCH 064/118] Enable and fix a number of lints (dart-lang/mime#49) - moved char codes to top-level fields - removed gratuitous library directives Co-authored-by: Jacob MacDonald --- pkgs/mime/analysis_options.yaml | 6 +- pkgs/mime/lib/src/bound_multipart_stream.dart | 221 +++++++++--------- pkgs/mime/lib/src/char_code.dart | 21 +- pkgs/mime/lib/src/default_extension_map.dart | 2 - pkgs/mime/lib/src/magic_number.dart | 4 +- .../lib/src/mime_multipart_transformer.dart | 16 +- pkgs/mime/lib/src/mime_shared.dart | 1 - pkgs/mime/lib/src/mime_type.dart | 6 +- .../test/mime_multipart_transformer_test.dart | 80 ++++--- pkgs/mime/test/mime_type_test.dart | 9 +- 10 files changed, 181 insertions(+), 185 deletions(-) diff --git a/pkgs/mime/analysis_options.yaml b/pkgs/mime/analysis_options.yaml index 7f965d234..7d7abe2c9 100644 --- a/pkgs/mime/analysis_options.yaml +++ b/pkgs/mime/analysis_options.yaml @@ -4,6 +4,7 @@ analyzer: implicit-casts: false linter: rules: + - avoid_dynamic_calls - avoid_empty_else - avoid_init_to_null - avoid_null_checks_in_equality_operators @@ -11,8 +12,9 @@ linter: - await_only_futures - camel_case_types - cancel_subscriptions - #- constant_identifier_names - control_flow_in_finally + - constant_identifier_names + - depend_on_referenced_packages - directives_ordering - empty_catches - empty_constructor_bodies @@ -29,6 +31,7 @@ linter: - package_names - package_prefixed_library_names - prefer_equal_for_default_values + - prefer_expression_function_bodies - prefer_final_fields - prefer_generic_function_type_aliases - prefer_is_not_empty @@ -39,5 +42,6 @@ linter: - unnecessary_brace_in_string_interps - unnecessary_const - unnecessary_new + - unnecessary_parenthesis - unrelated_type_equality_checks - valid_regexps diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index 73bc49560..ae46499b9 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -5,39 +5,20 @@ import 'dart:async'; import 'dart:convert'; -import 'char_code.dart'; +import 'char_code.dart' as char_code; import 'mime_shared.dart'; /// Bytes for '()<>@,;:\\"/[]?={} \t'. -const _SEPARATORS = [ - 40, - 41, - 60, - 62, - 64, - 44, - 59, - 58, - 92, - 34, - 47, - 91, - 93, - 63, - 61, - 123, - 125, - 32, - 9 -]; - -bool _isTokenChar(int byte) { - return byte > 31 && byte < 128 && !_SEPARATORS.contains(byte); -} +const _separators = { + 40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, 91, 93, 63, 61, 123, 125, 32, 9 // +}; + +bool _isTokenChar(int byte) => + byte > 31 && byte < 128 && !_separators.contains(byte); int _toLowerCase(int byte) { - const delta = CharCode.LOWER_A - CharCode.UPPER_A; - return (CharCode.UPPER_A <= byte && byte <= CharCode.UPPER_Z) + const delta = char_code.lowerA - char_code.upperA; + return (char_code.upperA <= byte && byte <= char_code.upperZ) ? byte + delta : byte; } @@ -49,7 +30,7 @@ void _expectByteValue(int val1, int val2) { } void _expectWhitespace(int byte) { - if (byte != CharCode.SP && byte != CharCode.HT) { + if (byte != char_code.sp && byte != char_code.ht) { throw MimeMultipartException('Failed to parse multipart mime 2'); } } @@ -62,30 +43,37 @@ class _MimeMultipart extends MimeMultipart { _MimeMultipart(this.headers, this._stream); @override - StreamSubscription> listen(void Function(List data)? onData, - {void Function()? onDone, Function? onError, bool? cancelOnError}) { - return _stream.listen(onData, - onDone: onDone, onError: onError, cancelOnError: cancelOnError); - } + StreamSubscription> listen( + void Function(List data)? onData, { + void Function()? onDone, + Function? onError, + bool? cancelOnError, + }) => + _stream.listen( + onData, + onDone: onDone, + onError: onError, + cancelOnError: cancelOnError, + ); } class BoundMultipartStream { - static const int _START = 0; - static const int _BOUNDARY_ENDING = 1; - static const int _BOUNDARY_END = 2; - static const int _HEADER_START = 3; - static const int _HEADER_FIELD = 4; - static const int _HEADER_VALUE_START = 5; - static const int _HEADER_VALUE = 6; - static const int _HEADER_VALUE_FOLDING_OR_ENDING = 7; - static const int _HEADER_VALUE_FOLD_OR_END = 8; - static const int _HEADER_ENDING = 9; - static const int _CONTENT = 10; - static const int _LAST_BOUNDARY_DASH2 = 11; - static const int _LAST_BOUNDARY_ENDING = 12; - static const int _LAST_BOUNDARY_END = 13; - static const int _DONE = 14; - static const int _FAIL = 15; + static const int _startCode = 0; + static const int _boundaryEndingCode = 1; + static const int _boundaryEndCode = 2; + static const int _headerStartCode = 3; + static const int _headerFieldCode = 4; + static const int _headerValueStartCode = 5; + static const int _headerValueCode = 6; + static const int _headerValueFoldingOrEndingCode = 7; + static const int _headerValueFoldOrEndCode = 8; + static const int _headerEndingCode = 9; + static const int _contentCode = 10; + static const int _lastBoundaryDash2Code = 11; + static const int _lastBoundaryEndingCode = 12; + static const int _lastBoundaryEndCode = 13; + static const int _doneCode = 14; + static const int _failCode = 15; final List _boundary; final List _headerField = []; @@ -94,12 +82,12 @@ class BoundMultipartStream { // The following states belong to `_controller`, state changes will not be // immediately acted upon but rather only after the current // `_multipartController` is done. - static const int _CONTROLLER_STATE_IDLE = 0; - static const int _CONTROLLER_STATE_ACTIVE = 1; - static const int _CONTROLLER_STATE_PAUSED = 2; - static const int _CONTROLLER_STATE_CANCELED = 3; + static const int _controllerStateIdle = 0; + static const int _controllerStateActive = 1; + static const int _controllerStatePaused = 2; + static const int _controllerStateCanceled = 3; - int _controllerState = _CONTROLLER_STATE_IDLE; + int _controllerState = _controllerStateIdle; final _controller = StreamController(sync: true); @@ -110,7 +98,7 @@ class BoundMultipartStream { StreamController>? _multipartController; Map? _headers; - int _state = _START; + int _state = _startCode; int _boundaryIndex = 2; /// Current index into [_buffer]. @@ -125,11 +113,11 @@ class BoundMultipartStream { ..onPause = _pauseStream ..onResume = _resumeStream ..onCancel = () { - _controllerState = _CONTROLLER_STATE_CANCELED; + _controllerState = _controllerStateCanceled; _tryPropagateControllerState(); } ..onListen = () { - _controllerState = _CONTROLLER_STATE_ACTIVE; + _controllerState = _controllerStateActive; _subscription = stream.listen((data) { assert(_buffer == _placeholderBuffer); _subscription.pause(); @@ -137,7 +125,7 @@ class BoundMultipartStream { _index = 0; _parse(); }, onDone: () { - if (_state != _DONE) { + if (_state != _doneCode) { _controller .addError(MimeMultipartException('Bad multipart ending')); } @@ -147,26 +135,26 @@ class BoundMultipartStream { } void _resumeStream() { - assert(_controllerState == _CONTROLLER_STATE_PAUSED); - _controllerState = _CONTROLLER_STATE_ACTIVE; + assert(_controllerState == _controllerStatePaused); + _controllerState = _controllerStateActive; _tryPropagateControllerState(); } void _pauseStream() { - _controllerState = _CONTROLLER_STATE_PAUSED; + _controllerState = _controllerStatePaused; _tryPropagateControllerState(); } void _tryPropagateControllerState() { if (_multipartController == null) { switch (_controllerState) { - case _CONTROLLER_STATE_ACTIVE: + case _controllerStateActive: if (_subscription.isPaused) _subscription.resume(); break; - case _CONTROLLER_STATE_PAUSED: + case _controllerStatePaused: if (!_subscription.isPaused) _subscription.pause(); break; - case _CONTROLLER_STATE_CANCELED: + case _controllerStateCanceled: _subscription.cancel(); break; default: @@ -185,7 +173,7 @@ class BoundMultipartStream { // boundary prefix. Will be zero or position if the content starts // in the current buffer. var contentStartIndex = - _state == _CONTENT && _boundaryIndex == 0 ? 0 : null; + _state == _contentCode && _boundaryIndex == 0 ? 0 : null; // Function to report content data for the current part. The data // reported is from the current content start index up til the @@ -209,15 +197,16 @@ class BoundMultipartStream { } } - while (_index < _buffer.length && _state != _FAIL && _state != _DONE) { + while ( + _index < _buffer.length && _state != _failCode && _state != _doneCode) { var byte = _index < 0 ? _boundary[boundaryPrefix + _index] : _buffer[_index]; switch (_state) { - case _START: + case _startCode: if (byte == _boundary[_boundaryIndex]) { _boundaryIndex++; if (_boundaryIndex == _boundary.length) { - _state = _BOUNDARY_ENDING; + _state = _boundaryEndingCode; _boundaryIndex = 0; } } else { @@ -227,40 +216,40 @@ class BoundMultipartStream { } break; - case _BOUNDARY_ENDING: - if (byte == CharCode.CR) { - _state = _BOUNDARY_END; - } else if (byte == CharCode.DASH) { - _state = _LAST_BOUNDARY_DASH2; + case _boundaryEndingCode: + if (byte == char_code.cr) { + _state = _boundaryEndCode; + } else if (byte == char_code.dash) { + _state = _lastBoundaryDash2Code; } else { _expectWhitespace(byte); } break; - case _BOUNDARY_END: - _expectByteValue(byte, CharCode.LF); + case _boundaryEndCode: + _expectByteValue(byte, char_code.lf); _multipartController?.close(); if (_multipartController != null) { _multipartController = null; _tryPropagateControllerState(); } - _state = _HEADER_START; + _state = _headerStartCode; break; - case _HEADER_START: + case _headerStartCode: _headers = {}; - if (byte == CharCode.CR) { - _state = _HEADER_ENDING; + if (byte == char_code.cr) { + _state = _headerEndingCode; } else { // Start of new header field. _headerField.add(_toLowerCase(byte)); - _state = _HEADER_FIELD; + _state = _headerFieldCode; } break; - case _HEADER_FIELD: - if (byte == CharCode.COLON) { - _state = _HEADER_VALUE_START; + case _headerFieldCode: + if (byte == char_code.colon) { + _state = _headerValueStartCode; } else { if (!_isTokenChar(byte)) { throw MimeMultipartException('Invalid header field name'); @@ -269,50 +258,50 @@ class BoundMultipartStream { } break; - case _HEADER_VALUE_START: - if (byte == CharCode.CR) { - _state = _HEADER_VALUE_FOLDING_OR_ENDING; - } else if (byte != CharCode.SP && byte != CharCode.HT) { + case _headerValueStartCode: + if (byte == char_code.cr) { + _state = _headerValueFoldingOrEndingCode; + } else if (byte != char_code.sp && byte != char_code.ht) { // Start of new header value. _headerValue.add(byte); - _state = _HEADER_VALUE; + _state = _headerValueCode; } break; - case _HEADER_VALUE: - if (byte == CharCode.CR) { - _state = _HEADER_VALUE_FOLDING_OR_ENDING; + case _headerValueCode: + if (byte == char_code.cr) { + _state = _headerValueFoldingOrEndingCode; } else { _headerValue.add(byte); } break; - case _HEADER_VALUE_FOLDING_OR_ENDING: - _expectByteValue(byte, CharCode.LF); - _state = _HEADER_VALUE_FOLD_OR_END; + case _headerValueFoldingOrEndingCode: + _expectByteValue(byte, char_code.lf); + _state = _headerValueFoldOrEndCode; break; - case _HEADER_VALUE_FOLD_OR_END: - if (byte == CharCode.SP || byte == CharCode.HT) { - _state = _HEADER_VALUE_START; + case _headerValueFoldOrEndCode: + if (byte == char_code.sp || byte == char_code.ht) { + _state = _headerValueStartCode; } else { var headerField = utf8.decode(_headerField); var headerValue = utf8.decode(_headerValue); _headers![headerField.toLowerCase()] = headerValue; _headerField.clear(); _headerValue.clear(); - if (byte == CharCode.CR) { - _state = _HEADER_ENDING; + if (byte == char_code.cr) { + _state = _headerEndingCode; } else { // Start of new header field. _headerField.add(_toLowerCase(byte)); - _state = _HEADER_FIELD; + _state = _headerFieldCode; } } break; - case _HEADER_ENDING: - _expectByteValue(byte, CharCode.LF); + case _headerEndingCode: + _expectByteValue(byte, char_code.lf); _multipartController = StreamController( sync: true, onListen: () { @@ -323,11 +312,11 @@ class BoundMultipartStream { _controller .add(_MimeMultipart(_headers!, _multipartController!.stream)); _headers = null; - _state = _CONTENT; + _state = _contentCode; contentStartIndex = _index + 1; break; - case _CONTENT: + case _contentCode: if (byte == _boundary[_boundaryIndex]) { _boundaryIndex++; if (_boundaryIndex == _boundary.length) { @@ -340,7 +329,7 @@ class BoundMultipartStream { _multipartController = null; _tryPropagateControllerState(); _boundaryIndex = 0; - _state = _BOUNDARY_ENDING; + _state = _boundaryEndingCode; } } else { // Restart matching of the boundary. @@ -350,27 +339,27 @@ class BoundMultipartStream { } break; - case _LAST_BOUNDARY_DASH2: - _expectByteValue(byte, CharCode.DASH); - _state = _LAST_BOUNDARY_ENDING; + case _lastBoundaryDash2Code: + _expectByteValue(byte, char_code.dash); + _state = _lastBoundaryEndingCode; break; - case _LAST_BOUNDARY_ENDING: - if (byte == CharCode.CR) { - _state = _LAST_BOUNDARY_END; + case _lastBoundaryEndingCode: + if (byte == char_code.cr) { + _state = _lastBoundaryEndCode; } else { _expectWhitespace(byte); } break; - case _LAST_BOUNDARY_END: - _expectByteValue(byte, CharCode.LF); + case _lastBoundaryEndCode: + _expectByteValue(byte, char_code.lf); _multipartController?.close(); if (_multipartController != null) { _multipartController = null; _tryPropagateControllerState(); } - _state = _DONE; + _state = _doneCode; break; default: @@ -384,7 +373,7 @@ class BoundMultipartStream { } // Report any known content. - if (_state == _CONTENT && contentStartIndex != null) { + if (_state == _contentCode && contentStartIndex != null) { reportData(); } diff --git a/pkgs/mime/lib/src/char_code.dart b/pkgs/mime/lib/src/char_code.dart index f455e681a..4cca1b19c 100644 --- a/pkgs/mime/lib/src/char_code.dart +++ b/pkgs/mime/lib/src/char_code.dart @@ -1,16 +1,13 @@ // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library mime.char_code; -class CharCode { - static const int HT = 9; - static const int LF = 10; - static const int CR = 13; - static const int SP = 32; - static const int DASH = 45; - static const int COLON = 58; - static const int UPPER_A = 65; - static const int UPPER_Z = 90; - static const int LOWER_A = 97; -} +const int ht = 9; +const int lf = 10; +const int cr = 13; +const int sp = 32; +const int dash = 45; +const int colon = 58; +const int upperA = 65; +const int upperZ = 90; +const int lowerA = 97; diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index d951b23b5..fa5c99a45 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library mime.extension_map; - const Map defaultExtensionMap = { '123': 'application/vnd.lotus-1-2-3', '3dml': 'text/vnd.in3d.3dml', diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 89336775c..9db370fa9 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -26,9 +26,9 @@ class MagicNumber { } } -const int DEFAULT_MAGIC_NUMBERS_MAX_LENGTH = 12; +const int initialMagicNumbersMaxLength = 12; -const List DEFAULT_MAGIC_NUMBERS = [ +const List initialMagicNumbers = [ MagicNumber('application/pdf', [0x25, 0x50, 0x44, 0x46]), MagicNumber('application/postscript', [0x25, 0x51]), MagicNumber('image/gif', [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart index 1869480a4..a3da85755 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -1,13 +1,12 @@ // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library mime.multipart_transformer; import 'dart:async'; import 'dart:typed_data'; import 'bound_multipart_stream.dart'; -import 'char_code.dart'; +import 'char_code.dart' as char_code; import 'mime_shared.dart'; Uint8List _getBoundary(String boundary) { @@ -16,10 +15,10 @@ Uint8List _getBoundary(String boundary) { var boundaryList = Uint8List(4 + charCodes.length); // Set-up the matching boundary preceding it with CRLF and two // dashes. - boundaryList[0] = CharCode.CR; - boundaryList[1] = CharCode.LF; - boundaryList[2] = CharCode.DASH; - boundaryList[3] = CharCode.DASH; + boundaryList[0] = char_code.cr; + boundaryList[1] = char_code.lf; + boundaryList[2] = char_code.dash; + boundaryList[3] = char_code.dash; boundaryList.setRange(4, 4 + charCodes.length, charCodes); return boundaryList; } @@ -38,7 +37,6 @@ class MimeMultipartTransformer : _boundary = _getBoundary(boundary); @override - Stream bind(Stream> stream) { - return BoundMultipartStream(_boundary, stream).stream; - } + Stream bind(Stream> stream) => + BoundMultipartStream(_boundary, stream).stream; } diff --git a/pkgs/mime/lib/src/mime_shared.dart b/pkgs/mime/lib/src/mime_shared.dart index 61e81f247..2a29ae07e 100644 --- a/pkgs/mime/lib/src/mime_shared.dart +++ b/pkgs/mime/lib/src/mime_shared.dart @@ -1,7 +1,6 @@ // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library mime.shared; class MimeMultipartException implements Exception { final String message; diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index 14db94233..e72806e0c 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library mime.mime_type; - import 'default_extension_map.dart'; import 'magic_number.dart'; @@ -54,7 +52,7 @@ class MimeTypeResolver { /// Create a new [MimeTypeResolver] containing the default scope. MimeTypeResolver() : _useDefault = true, - _magicNumbersMaxLength = DEFAULT_MAGIC_NUMBERS_MAX_LENGTH; + _magicNumbersMaxLength = initialMagicNumbersMaxLength; /// Get the maximum number of bytes required to match all magic numbers, when /// performing [lookup] with headerBytes present. @@ -75,7 +73,7 @@ class MimeTypeResolver { result = _matchMagic(headerBytes, _magicNumbers); if (result != null) return result; if (_useDefault) { - result = _matchMagic(headerBytes, DEFAULT_MAGIC_NUMBERS); + result = _matchMagic(headerBytes, initialMagicNumbers); if (result != null) return result; } } diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index d503bcb71..4e5ed04e3 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -20,12 +20,16 @@ void _writeInChunks( controller.close(); } -enum TestMode { IMMEDIATE_LISTEN, DELAY_LISTEN, PAUSE_RESUME } - -void _runParseTest(String message, String boundary, TestMode mode, - [List? expectedHeaders, - List? expectedParts, - bool expectError = false]) { +enum TestMode { immediateListen, delayListen, pauseResume } + +void _runParseTest( + String message, + String boundary, + TestMode mode, [ + List? expectedHeaders, + List? expectedParts, + bool expectError = false, +]) { Future testWrite(List data, [int chunkSize = -1]) { var controller = StreamController>(sync: true); @@ -40,41 +44,48 @@ void _runParseTest(String message, String boundary, TestMode mode, expect(multipart.headers, equals(expectedHeaders[part])); } switch (mode) { - case TestMode.IMMEDIATE_LISTEN: + case TestMode.immediateListen: futures.add(multipart.fold>( [], (buffer, data) => buffer..addAll(data)).then((data) { if (expectedParts?[part] != null) { - expect(data, equals(expectedParts?[part].codeUnits)); + expect(data, equals(expectedParts?[part]!.codeUnits)); } })); break; - case TestMode.DELAY_LISTEN: - futures.add(Future(() { - return multipart.fold>( - [], (buffer, data) => buffer..addAll(data)).then((data) { - if (expectedParts?[part] != null) { - expect(data, equals(expectedParts?[part].codeUnits)); - } - }); - })); + case TestMode.delayListen: + futures.add( + Future( + () => multipart.fold>( + [], + (buffer, data) => buffer..addAll(data), + ).then( + (data) { + if (expectedParts?[part] != null) { + expect(data, equals(expectedParts?[part]!.codeUnits)); + } + }, + ), + ), + ); break; - case TestMode.PAUSE_RESUME: + case TestMode.pauseResume: var completer = Completer(); futures.add(completer.future); var buffer = []; - var subscription; + late StreamSubscription subscription; subscription = multipart.listen((data) { buffer.addAll(data); subscription.pause(); Future(() => subscription.resume()); }, onDone: () { if (expectedParts?[part] != null) { - expect(buffer, equals(expectedParts?[part].codeUnits)); + expect(buffer, equals(expectedParts?[part]!.codeUnits)); } completer.complete(); }); + addTearDown(subscription.cancel); break; } }, onError: (Object error) { @@ -102,12 +113,13 @@ void _runParseTest(String message, String boundary, TestMode mode, if (expectedHeaders != null) { expect(multipart.headers, equals(expectedHeaders[0])); } - return (multipart - .fold>([], (b, d) => b..addAll(d)).then((data) { - if (expectedParts != null && expectedParts[0] != null) { - expect(data, equals(expectedParts[0].codeUnits)); - } - })); + return multipart.fold>([], (b, d) => b..addAll(d)).then( + (data) { + if (expectedParts != null && expectedParts[0] != null) { + expect(data, equals(expectedParts[0]!.codeUnits)); + } + }, + ); }).then((_) { completer.complete(); }); @@ -123,7 +135,7 @@ void _runParseTest(String message, String boundary, TestMode mode, var controller = StreamController>(sync: true); var stream = controller.stream.transform(MimeMultipartTransformer(boundary)); - var subscription; + late StreamSubscription subscription; var i = 0; var futures = []; subscription = stream.listen((multipart) { @@ -137,11 +149,11 @@ void _runParseTest(String message, String boundary, TestMode mode, expect(multipart.headers, equals(expectedHeaders[partIndex])); } futures.add( - (multipart.fold>([], (b, d) => b..addAll(d)).then((data) { + multipart.fold>([], (b, d) => b..addAll(d)).then((data) { if (expectedParts != null && expectedParts[partIndex] != null) { - expect(data, equals(expectedParts[partIndex].codeUnits)); + expect(data, equals(expectedParts[partIndex]!.codeUnits)); } - }))); + })); if (partIndex == (parts - 1)) { subscription.cancel(); @@ -199,13 +211,13 @@ void _runParseTest(String message, String boundary, TestMode mode, void _testParse(String message, String boundary, [List? expectedHeaders, - List? expectedParts, + List? expectedParts, bool expectError = false]) { - _runParseTest(message, boundary, TestMode.IMMEDIATE_LISTEN, expectedHeaders, + _runParseTest(message, boundary, TestMode.immediateListen, expectedHeaders, expectedParts, expectError); - _runParseTest(message, boundary, TestMode.DELAY_LISTEN, expectedHeaders, + _runParseTest(message, boundary, TestMode.delayListen, expectedHeaders, expectedParts, expectError); - _runParseTest(message, boundary, TestMode.PAUSE_RESUME, expectedHeaders, + _runParseTest(message, boundary, TestMode.pauseResume, expectedHeaders, expectedParts, expectError); } diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index a116bf3ca..4dfdb1320 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -117,11 +117,12 @@ void main() { }); test('default magic number', () { - var actualMaxBytes = DEFAULT_MAGIC_NUMBERS.fold(0, (num previous, magic) { - return math.max(previous, magic.numbers.length); - }); + var actualMaxBytes = initialMagicNumbers.fold( + 0, + (previous, magic) => math.max(previous, magic.numbers.length), + ); - expect(defaultMagicNumbersMaxLength, actualMaxBytes); + expect(initialMagicNumbersMaxLength, actualMaxBytes); }); group('extensionFromMime', () { From 72f41e8a558e6919e2ac53a9f7859fd4cf287827 Mon Sep 17 00:00:00 2001 From: Rodinei Fagundes Date: Mon, 18 Oct 2021 11:09:39 -0300 Subject: [PATCH 065/118] Add magic numbers for WebP (dart-lang/mime#54) --- pkgs/mime/CHANGELOG.md | 4 ++++ pkgs/mime/lib/src/magic_number.dart | 33 +++++++++++++++++++++++++++++ pkgs/mime/pubspec.yaml | 2 +- pkgs/mime/test/mime_type_test.dart | 15 +++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index b77b2acec..52c625f3f 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,7 @@ +# 1.0.1 + +* Add image/webp mimeType lookup by header bytes. + # 1.0.0 * Stable null safety release. diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 9db370fa9..78255c505 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -65,4 +65,37 @@ const List initialMagicNumbers = [ 0xFF ]), MagicNumber('model/gltf-binary', [0x46, 0x54, 0x6C, 0x67]), + + /// The WebP file format is based on the RIFF document format. + /// -> 4 bytes have the ASCII characters 'R' 'I' 'F' 'F'. + /// -> 4 bytes indicating the size of the file + /// -> 4 bytes have the ASCII characters 'W' 'E' 'B' 'P'. + /// https://developers.google.com/speed/webp/docs/riff_container + MagicNumber('image/webp', [ + 0x52, + 0x49, + 0x46, + 0x46, + 0x00, + 0x00, + 0x00, + 0x00, + 0x57, + 0x45, + 0x42, + 0x50 + ], mask: [ + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]) ]; diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 5d796ae2d..d1b843073 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 1.0.0 +version: 1.0.1 description: >- Utilities for handling media (MIME) types, including determining a type from diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 4dfdb1320..e02e0af1e 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -40,6 +40,7 @@ void main() { _expectMimeType('file.pdf', 'application/pdf'); _expectMimeType('file.tiff', 'image/tiff'); _expectMimeType('file.tif', 'image/tiff'); + _expectMimeType('file.webp', 'image/webp'); }); test('unknown-mime-type', () { @@ -87,6 +88,20 @@ void main() { 0x70, 0x35 ]); + _expectMimeType('file', 'image/webp', headerBytes: [ + 0x52, + 0x49, + 0x46, + 0x46, + 0xE2, + 0x4A, + 0x01, + 0x00, + 0x57, + 0x45, + 0x42, + 0x50 + ]); }); }); From 50caca47625aa0130cc6266bd0d3f12ed8b25981 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 18 Oct 2021 07:15:44 -0700 Subject: [PATCH 066/118] Move to pkg:lints, tiny bumps in deps (dart-lang/mime#56) --- pkgs/mime/analysis_options.yaml | 35 ++-------------- pkgs/mime/pubspec.yaml | 6 +-- .../test/mime_multipart_transformer_test.dart | 40 +++++++++---------- 3 files changed, 26 insertions(+), 55 deletions(-) diff --git a/pkgs/mime/analysis_options.yaml b/pkgs/mime/analysis_options.yaml index 7d7abe2c9..28eed4ced 100644 --- a/pkgs/mime/analysis_options.yaml +++ b/pkgs/mime/analysis_options.yaml @@ -1,47 +1,18 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml + analyzer: strong-mode: implicit-casts: false + linter: rules: - avoid_dynamic_calls - - avoid_empty_else - - avoid_init_to_null - - avoid_null_checks_in_equality_operators - avoid_unused_constructor_parameters - - await_only_futures - - camel_case_types - cancel_subscriptions - - control_flow_in_finally - - constant_identifier_names - depend_on_referenced_packages - directives_ordering - - empty_catches - - empty_constructor_bodies - - empty_statements - - hash_and_equals - - implementation_imports - - iterable_contains_unrelated_type - - library_names - - library_prefixes - - list_remove_unrelated_type - - non_constant_identifier_names - - overridden_fields - package_api_docs - - package_names - - package_prefixed_library_names - - prefer_equal_for_default_values - prefer_expression_function_bodies - - prefer_final_fields - - prefer_generic_function_type_aliases - - prefer_is_not_empty - - slash_for_doc_comments - test_types_in_equals - throw_in_finally - - type_init_formals - - unnecessary_brace_in_string_interps - - unnecessary_const - - unnecessary_new - unnecessary_parenthesis - - unrelated_type_equality_checks - - valid_regexps diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index d1b843073..1aca7a030 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -7,8 +7,8 @@ description: >- homepage: https://github.com/dart-lang/mime environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dev_dependencies: - pedantic: ^1.10.0 - test: ^1.16.0-nullsafety + lints: ^1.0.0 + test: ^1.16.0 diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 4e5ed04e3..6a4437226 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -254,21 +254,21 @@ Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg='''; // Sample from HTML 4.01 Specification. message = ''' \r\n--AaB03x\r -Content-Disposition: form-data; name=\"submit-name\"\r +Content-Disposition: form-data; name="submit-name"\r \r Larry\r --AaB03x\r -Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"\r +Content-Disposition: form-data; name="files"; filename="file1.txt"\r Content-Type: text/plain\r \r ... contents of file1.txt ...\r --AaB03x--\r\n'''; headers1 = { - 'content-disposition': 'form-data; name=\"submit-name\"' + 'content-disposition': 'form-data; name="submit-name"' }; headers2 = { 'content-type': 'text/plain', - 'content-disposition': 'form-data; name=\"files\"; filename=\"file1.txt\"' + 'content-disposition': 'form-data; name="files"; filename="file1.txt"' }; body1 = 'Larry'; body2 = '... contents of file1.txt ...'; @@ -294,33 +294,33 @@ Content-Type: text/plain\r message = ''' \r\n------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r -Content-Disposition: form-data; name=\"text_input\"\r +Content-Disposition: form-data; name="text_input"\r \r text\r ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r -Content-Disposition: form-data; name=\"password_input\"\r +Content-Disposition: form-data; name="password_input"\r \r password\r ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r -Content-Disposition: form-data; name=\"checkbox_input\"\r +Content-Disposition: form-data; name="checkbox_input"\r \r on\r ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r -Content-Disposition: form-data; name=\"radio_input\"\r +Content-Disposition: form-data; name="radio_input"\r \r on\r ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n'''; headers1 = { - 'content-disposition': 'form-data; name=\"text_input\"' + 'content-disposition': 'form-data; name="text_input"' }; headers2 = { - 'content-disposition': 'form-data; name=\"password_input\"' + 'content-disposition': 'form-data; name="password_input"' }; var headers3 = { - 'content-disposition': 'form-data; name=\"checkbox_input\"' + 'content-disposition': 'form-data; name="checkbox_input"' }; var headers4 = { - 'content-disposition': 'form-data; name=\"radio_input\"' + 'content-disposition': 'form-data; name="radio_input"' }; body1 = 'text'; body2 = 'password'; @@ -332,19 +332,19 @@ on\r // Same form from Firefox. message = ''' \r\n-----------------------------52284550912143824192005403738\r -Content-Disposition: form-data; name=\"text_input\"\r +Content-Disposition: form-data; name="text_input"\r \r text\r -----------------------------52284550912143824192005403738\r -Content-Disposition: form-data; name=\"password_input\"\r +Content-Disposition: form-data; name="password_input"\r \r password\r -----------------------------52284550912143824192005403738\r -Content-Disposition: form-data; name=\"checkbox_input\"\r +Content-Disposition: form-data; name="checkbox_input"\r \r on\r -----------------------------52284550912143824192005403738\r -Content-Disposition: form-data; name=\"radio_input\"\r +Content-Disposition: form-data; name="radio_input"\r \r on\r -----------------------------52284550912143824192005403738--\r\n'''; @@ -357,19 +357,19 @@ on\r // And Internet Explorer message = ''' \r\n-----------------------------7dc8f38c60326\r -Content-Disposition: form-data; name=\"text_input\"\r +Content-Disposition: form-data; name="text_input"\r \r text\r -----------------------------7dc8f38c60326\r -Content-Disposition: form-data; name=\"password_input\"\r +Content-Disposition: form-data; name="password_input"\r \r password\r -----------------------------7dc8f38c60326\r -Content-Disposition: form-data; name=\"checkbox_input\"\r +Content-Disposition: form-data; name="checkbox_input"\r \r on\r -----------------------------7dc8f38c60326\r -Content-Disposition: form-data; name=\"radio_input\"\r +Content-Disposition: form-data; name="radio_input"\r \r on\r -----------------------------7dc8f38c60326--\r\n'''; From ff1b881729e04c27265bdcf025e292be98414d85 Mon Sep 17 00:00:00 2001 From: Hannes Braun Date: Thu, 10 Feb 2022 19:26:22 +0100 Subject: [PATCH 067/118] Add magic numbers for AIFF, WAVE and FLAC files (dart-lang/mime#53) --- pkgs/mime/CHANGELOG.md | 6 +++ pkgs/mime/lib/src/magic_number.dart | 70 +++++++++++++++++++++++++++++ pkgs/mime/pubspec.yaml | 2 +- pkgs/mime/test/mime_type_test.dart | 31 +++++++++++++ 4 files changed, 108 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 52c625f3f..3a3eb5d16 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,9 @@ +# 1.0.2 + +* Add audio/x-aiff mimeType lookup by header bytes. +* Add audio/x-flac mimeType lookup by header bytes. +* Add audio/x-wav mimeType lookup by header bytes. + # 1.0.1 * Add image/webp mimeType lookup by header bytes. diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 78255c505..0cb5a8d12 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -31,6 +31,76 @@ const int initialMagicNumbersMaxLength = 12; const List initialMagicNumbers = [ MagicNumber('application/pdf', [0x25, 0x50, 0x44, 0x46]), MagicNumber('application/postscript', [0x25, 0x51]), + + /// AIFF is based on the EA IFF 85 Standard for Interchange Format Files. + /// -> 4 bytes have the ASCII characters 'F' 'O' 'R' 'M'. + /// -> 4 bytes indicating the size of the file + /// -> 4 bytes have the ASCII characters 'A' 'I' 'F' 'F'. + /// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/Docs/AIFF-1.3.pdf + MagicNumber('audio/x-aiff', [ + 0x46, + 0x4F, + 0x52, + 0x4D, + 0x00, + 0x00, + 0x00, + 0x00, + 0x41, + 0x49, + 0x46, + 0x46 + ], mask: [ + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + + /// -> 4 bytes have the ASCII characters 'f' 'L' 'a' 'C'. + /// https://xiph.org/flac/format.html + MagicNumber('audio/x-flac', [0x66, 0x4C, 0x61, 0x43]), + + /// The WAVE file format is based on the RIFF document format. + /// -> 4 bytes have the ASCII characters 'R' 'I' 'F' 'F'. + /// -> 4 bytes indicating the size of the file + /// -> 4 bytes have the ASCII characters 'W' 'A' 'V' 'E'. + /// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/riffmci.pdf + MagicNumber('audio/x-wav', [ + 0x52, + 0x49, + 0x46, + 0x46, + 0x00, + 0x00, + 0x00, + 0x00, + 0x57, + 0x41, + 0x56, + 0x45 + ], mask: [ + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), MagicNumber('image/gif', [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]), MagicNumber('image/gif', [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), MagicNumber('image/jpeg', [0xFF, 0xD8]), diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 1aca7a030..f0c92f15f 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 1.0.1 +version: 1.0.2 description: >- Utilities for handling media (MIME) types, including determining a type from diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index e02e0af1e..ac0db0131 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -41,6 +41,7 @@ void main() { _expectMimeType('file.tiff', 'image/tiff'); _expectMimeType('file.tif', 'image/tiff'); _expectMimeType('file.webp', 'image/webp'); + _expectMimeType('file.aiff', 'audio/x-aiff'); }); test('unknown-mime-type', () { @@ -102,6 +103,36 @@ void main() { 0x42, 0x50 ]); + _expectMimeType('file', 'audio/x-aiff', headerBytes: [ + 0x46, + 0x4F, + 0x52, + 0x4D, + 0x04, + 0x0B, + 0xEF, + 0xF4, + 0x41, + 0x49, + 0x46, + 0x46 + ]); + _expectMimeType('file', 'audio/x-flac', + headerBytes: [0x66, 0x4C, 0x61, 0x43]); + _expectMimeType('file', 'audio/x-wav', headerBytes: [ + 0x52, + 0x49, + 0x46, + 0x46, + 0xA6, + 0x4E, + 0x70, + 0x03, + 0x57, + 0x41, + 0x56, + 0x45 + ]); }); }); From b9e1938ea249a8f88f5d97284b8a68fed4076659 Mon Sep 17 00:00:00 2001 From: Nils Reichardt Date: Tue, 22 Mar 2022 20:50:06 +0100 Subject: [PATCH 068/118] Add `audio/m4p` mimeType lookup by file path (dart-lang/mime#62) Closes https://github.com/dart-lang/mime/issues/25 --- pkgs/mime/CHANGELOG.md | 1 + pkgs/mime/lib/src/default_extension_map.dart | 2 ++ pkgs/mime/test/mime_type_test.dart | 1 + 3 files changed, 4 insertions(+) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 3a3eb5d16..8b671c56d 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -3,6 +3,7 @@ * Add audio/x-aiff mimeType lookup by header bytes. * Add audio/x-flac mimeType lookup by header bytes. * Add audio/x-wav mimeType lookup by header bytes. +* Add audio/mp4 mimeType lookup by file path. # 1.0.1 diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index fa5c99a45..84aa9ae6c 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -413,6 +413,8 @@ const Map defaultExtensionMap = { 'm3a': 'audio/mpeg', 'm3u': 'audio/x-mpegurl', 'm3u8': 'application/vnd.apple.mpegurl', + // Source: https://www.rfc-editor.org/rfc/rfc4337#page-3 + 'm4a': 'audio/mp4', 'm4u': 'video/vnd.mpegurl', 'm4v': 'video/x-m4v', 'ma': 'application/mathematica', diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index ac0db0131..b5f037d7e 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -42,6 +42,7 @@ void main() { _expectMimeType('file.tif', 'image/tiff'); _expectMimeType('file.webp', 'image/webp'); _expectMimeType('file.aiff', 'audio/x-aiff'); + _expectMimeType('file.m4a', 'audio/mp4'); }); test('unknown-mime-type', () { From 4cdf69fa6758620dd0047b33350870a293ed69cf Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 2 May 2022 13:46:53 -0700 Subject: [PATCH 069/118] Add repository to pubspec (dart-lang/mime#63) --- pkgs/mime/pubspec.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index f0c92f15f..af9210b8c 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,10 +1,9 @@ name: mime version: 1.0.2 - description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. -homepage: https://github.com/dart-lang/mime +repository: https://github.com/dart-lang/mime environment: sdk: '>=2.12.0 <3.0.0' From 17f989730754a1755c64eb7c754ff9bfd9876bba Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 26 Sep 2022 09:57:06 -0700 Subject: [PATCH 070/118] update action versions; add dependabot config (dart-lang/mime#69) * update action versions; add dependabot config * fix the main branch name --- pkgs/mime/.github/dependabot.yaml | 8 +++ pkgs/mime/.github/workflows/test-package.yml | 63 ++++++-------------- pkgs/mime/README.md | 3 +- 3 files changed, 29 insertions(+), 45 deletions(-) create mode 100644 pkgs/mime/.github/dependabot.yaml diff --git a/pkgs/mime/.github/dependabot.yaml b/pkgs/mime/.github/dependabot.yaml new file mode 100644 index 000000000..214481934 --- /dev/null +++ b/pkgs/mime/.github/dependabot.yaml @@ -0,0 +1,8 @@ +# Dependabot configuration file. +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index e47bf6600..c2f9dd759 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -1,61 +1,36 @@ name: Dart CI on: - # Run on PRs and pushes to the default branch. + schedule: + # “At 00:00 (UTC) on Sunday.” + - cron: '0 0 * * 0' push: branches: [ master ] pull_request: branches: [ master ] - schedule: - - cron: "0 0 * * 0" - -env: - PUB_ENVIRONMENT: bot.github jobs: - # Check code formatting and static analysis on a single OS (linux) - # against Dart dev. - analyze: + build: runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - sdk: [dev] - steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 - with: - sdk: ${{ matrix.sdk }} - - id: install - name: Install dependencies - run: dart pub get - - name: Check formatting - run: dart format --output=none --set-exit-if-changed . - if: always() && steps.install.outcome == 'success' - - name: Analyze code - run: dart analyze --fatal-infos - if: always() && steps.install.outcome == 'success' - # Run tests on a matrix consisting of two dimensions: - # 1. OS: ubuntu-latest, (macos-latest, windows-latest) - # 2. release channel: dev - test: - needs: analyze - runs-on: ${{ matrix.os }} strategy: - fail-fast: false matrix: - # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 - with: - sdk: ${{ matrix.sdk }} - - id: install - name: Install dependencies + # These are the latest versions of the github actions; dependabot will + # send PRs to keep these up-to-date. + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + + - name: Install dependencies run: dart pub get - - name: Run VM tests - run: dart test --platform vm - if: always() && steps.install.outcome == 'success' + + - name: Verify formatting + run: dart format --output=none --set-exit-if-changed . + + - name: Analyze project source + run: dart analyze --fatal-infos + + - name: Run tests + run: dart test diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index 3eeecd170..a107306b8 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -1,5 +1,6 @@ -[![Pub Package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) [![Build Status](https://github.com/dart-lang/mime/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/mime/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) +[![Pub Package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) +[![package publisher](https://img.shields.io/pub/publisher/mime.svg)](https://pub.dev/packages/mime/publisher) Package for working with MIME type definitions and for processing streams of MIME multipart media types. From 72658a5842f2025dcd216978680501004fee3c37 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Nov 2022 08:02:00 -0700 Subject: [PATCH 071/118] Bump actions/checkout from 3.0.2 to 3.1.0 (dart-lang/mime#72) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.0.2 to 3.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/2541b1294d2704b0964813337f33b291d3f8596b...93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index c2f9dd759..13160c1f4 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d - name: Install dependencies From ebb7caca8f6f3c1b317a92ce348bbbc814c3d510 Mon Sep 17 00:00:00 2001 From: Liu YuanYuan Date: Wed, 2 Nov 2022 23:36:34 +0800 Subject: [PATCH 072/118] Add .avif to extension map (dart-lang/mime#70) https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types --- pkgs/mime/CHANGELOG.md | 4 ++++ pkgs/mime/lib/src/default_extension_map.dart | 1 + pkgs/mime/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 8b671c56d..16d411b2f 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,7 @@ +# 1.0.3 + +* Add image/avif mimeType lookup by extension. + # 1.0.2 * Add audio/x-aiff mimeType lookup by header bytes. diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index 84aa9ae6c..f40bb12d4 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -48,6 +48,7 @@ const Map defaultExtensionMap = { 'atx': 'application/vnd.antix.game-component', 'au': 'audio/basic', 'avi': 'video/x-msvideo', + 'avif': 'image/avif', 'aw': 'application/applixware', 'azf': 'application/vnd.airzip.filesecure.azf', 'azs': 'application/vnd.airzip.filesecure.azs', diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index af9210b8c..b675981a1 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 1.0.2 +version: 1.0.3 description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. From d6aa206080c6980252ebed71fb10b35e1672c51c Mon Sep 17 00:00:00 2001 From: Aliasgar Murtaza Date: Wed, 16 Nov 2022 02:08:40 +0400 Subject: [PATCH 073/118] Add `image/heic` mime type (dart-lang/mime#58) --- pkgs/mime/CHANGELOG.md | 1 + pkgs/mime/lib/src/default_extension_map.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 16d411b2f..f2f953d5d 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,6 +1,7 @@ # 1.0.3 * Add image/avif mimeType lookup by extension. +* Add image/heic mimeType lookup by extension. # 1.0.2 diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index f40bb12d4..6639bb396 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -309,6 +309,7 @@ const Map defaultExtensionMap = { 'hal': 'application/vnd.hal+xml', 'hbci': 'application/vnd.hbci', 'hdf': 'application/x-hdf', + 'heic': 'image/heic', 'hh': 'text/x-c', 'hlp': 'application/winhlp', 'hpgl': 'application/vnd.hp-hpgl', From 90f5cc270d3c89e119eb667ea103a1d8701edc71 Mon Sep 17 00:00:00 2001 From: Hannes Braun Date: Tue, 15 Nov 2022 23:12:43 +0100 Subject: [PATCH 074/118] Add application/toml mimeType lookup by file path (dart-lang/mime#64) --- pkgs/mime/CHANGELOG.md | 1 + pkgs/mime/lib/src/default_extension_map.dart | 2 ++ pkgs/mime/test/mime_type_test.dart | 1 + 3 files changed, 4 insertions(+) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index f2f953d5d..06a889bba 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,5 +1,6 @@ # 1.0.3 +* Add application/toml mimeType lookup by extension. * Add image/avif mimeType lookup by extension. * Add image/heic mimeType lookup by extension. diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index 6639bb396..4135a9f41 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -805,6 +805,8 @@ const Map defaultExtensionMap = { 'tif': 'image/tiff', 'tiff': 'image/tiff', 'tmo': 'application/vnd.tmobile-livetv', + // Source: https://toml.io/en/v1.0.0#mime-type + 'toml': 'application/toml', 'torrent': 'application/x-bittorrent', 'tpl': 'application/vnd.groove-tool-template', 'tpt': 'application/vnd.trid.tpt', diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index b5f037d7e..d1833f543 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -43,6 +43,7 @@ void main() { _expectMimeType('file.webp', 'image/webp'); _expectMimeType('file.aiff', 'audio/x-aiff'); _expectMimeType('file.m4a', 'audio/mp4'); + _expectMimeType('file.toml', 'application/toml'); }); test('unknown-mime-type', () { From 176f964edee50c884b7eeb91e34fe86596d612de Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Tue, 15 Nov 2022 23:21:08 +0100 Subject: [PATCH 075/118] Add woff2 mime type (dart-lang/mime#43) --- pkgs/mime/CHANGELOG.md | 1 + pkgs/mime/lib/src/default_extension_map.dart | 1 + pkgs/mime/lib/src/magic_number.dart | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 06a889bba..fd8ad5ce9 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,6 +1,7 @@ # 1.0.3 * Add application/toml mimeType lookup by extension. +* Add font/woff2 lookup by extension and header bytes. * Add image/avif mimeType lookup by extension. * Add image/heic mimeType lookup by extension. diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index 4135a9f41..e9f5ad432 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -913,6 +913,7 @@ const Map defaultExtensionMap = { 'wmx': 'video/x-ms-wmx', 'wmz': 'application/x-ms-wmz', 'woff': 'application/x-font-woff', + 'woff2': 'font/woff2', 'wpd': 'application/vnd.wordperfect', 'wpl': 'application/vnd.ms-wpl', 'wps': 'application/vnd.ms-works', diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 0cb5a8d12..299df422d 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -167,5 +167,7 @@ const List initialMagicNumbers = [ 0xFF, 0xFF, 0xFF - ]) + ]), + + MagicNumber('font/woff2', [0x77, 0x4f, 0x46, 0x32]), ]; From e0fb5cc138b19a38b78aaa41340d9a0ce4ebd2ed Mon Sep 17 00:00:00 2001 From: zi6xuan Date: Wed, 16 Nov 2022 07:26:01 +0900 Subject: [PATCH 076/118] Add image/heif to extension map (dart-lang/mime#52) --- pkgs/mime/CHANGELOG.md | 1 + pkgs/mime/lib/src/default_extension_map.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index fd8ad5ce9..80d8b17d2 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -4,6 +4,7 @@ * Add font/woff2 lookup by extension and header bytes. * Add image/avif mimeType lookup by extension. * Add image/heic mimeType lookup by extension. +* Add image/heif mimeType lookup by extension. # 1.0.2 diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index e9f5ad432..64e364b4c 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -310,6 +310,7 @@ const Map defaultExtensionMap = { 'hbci': 'application/vnd.hbci', 'hdf': 'application/x-hdf', 'heic': 'image/heic', + 'heif': 'image/heif', 'hh': 'text/x-c', 'hlp': 'application/winhlp', 'hpgl': 'application/vnd.hp-hpgl', From 9031027a17cb1bc8b329bfc0bc11c4638feddea2 Mon Sep 17 00:00:00 2001 From: cedvdb Date: Tue, 15 Nov 2022 23:48:07 +0100 Subject: [PATCH 077/118] Improve handling for audio: aac, mp3, ogg, webm (dart-lang/mime#57) - Update mime type for aac from `audio/x-aac` to `audio-aac`. https://www.iana.org/assignments/media-types/audio/aac - Add header byte detection for aac, mpeg audio, webm, and ogg. --- pkgs/mime/CHANGELOG.md | 5 +++++ pkgs/mime/lib/src/default_extension_map.dart | 2 +- pkgs/mime/lib/src/magic_number.dart | 6 ++++++ pkgs/mime/test/mime_type_test.dart | 9 +++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 80d8b17d2..e82ae09d3 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,10 +1,15 @@ # 1.0.3 * Add application/toml mimeType lookup by extension. +* Add audio/aac mimeType lookup by header bytes. +* Add audio/mpeg mimeType lookup by header bytes. +* Add audio/ogg mimeType lookup by header bytes. +* Add audio/weba mimeType lookup by header bytes. * Add font/woff2 lookup by extension and header bytes. * Add image/avif mimeType lookup by extension. * Add image/heic mimeType lookup by extension. * Add image/heif mimeType lookup by extension. +* Change audio/x-aac to audio/aac when detected by extension. # 1.0.2 diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index 64e364b4c..64f407422 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -10,7 +10,7 @@ const Map defaultExtensionMap = { '3gp': 'video/3gpp', '7z': 'application/x-7z-compressed', 'aab': 'application/x-authorware-bin', - 'aac': 'audio/x-aac', + 'aac': 'audio/aac', 'aam': 'application/x-authorware-map', 'aas': 'application/x-authorware-seg', 'abw': 'application/x-abiword', diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 299df422d..ee3de3143 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -107,6 +107,12 @@ const List initialMagicNumbers = [ MagicNumber('image/png', [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), MagicNumber('image/tiff', [0x49, 0x49, 0x2A, 0x00]), MagicNumber('image/tiff', [0x4D, 0x4D, 0x00, 0x2A]), + MagicNumber('audio/aac', [0xFF, 0xF1]), + MagicNumber('audio/aac', [0xFF, 0xF9]), + MagicNumber('audio/weba', [0x1A, 0x45, 0xDF, 0xA3]), + MagicNumber('audio/mpeg', [0x49, 0x44, 0x33]), + MagicNumber('audio/mpeg', [0xFF, 0xFB]), + MagicNumber('audio/ogg', [0x4F, 0x70, 0x75]), MagicNumber('video/mp4', [ 0x00, 0x00, diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index d1833f543..e99214a33 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -41,6 +41,9 @@ void main() { _expectMimeType('file.tiff', 'image/tiff'); _expectMimeType('file.tif', 'image/tiff'); _expectMimeType('file.webp', 'image/webp'); + _expectMimeType('file.mp3', 'audio/mpeg'); + _expectMimeType('file.aac', 'audio/aac'); + _expectMimeType('file.ogg', 'audio/ogg'); _expectMimeType('file.aiff', 'audio/x-aiff'); _expectMimeType('file.m4a', 'audio/mp4'); _expectMimeType('file.toml', 'application/toml'); @@ -105,6 +108,12 @@ void main() { 0x42, 0x50 ]); + _expectMimeType('file', 'audio/mpeg', + headerBytes: [0x49, 0x44, 0x33, 0x0D, 0x0A, 0x1A, 0x0A]); + _expectMimeType('file', 'audio/aac', + headerBytes: [0xFF, 0xF1, 0x0D, 0x0A, 0x1A, 0x0A]); + _expectMimeType('file', 'audio/ogg', + headerBytes: [0x4F, 0x70, 0x75, 0x0D, 0x0A, 0x1A, 0x0A]); _expectMimeType('file', 'audio/x-aiff', headerBytes: [ 0x46, 0x4F, From a9cede8c41d5d4b1cb59551c6d33bc0c6eab4317 Mon Sep 17 00:00:00 2001 From: Jack D Date: Tue, 15 Nov 2022 17:53:02 -0500 Subject: [PATCH 078/118] Add .webmanifest to extension map (dart-lang/mime#29) --- pkgs/mime/CHANGELOG.md | 1 + pkgs/mime/lib/src/default_extension_map.dart | 2 ++ 2 files changed, 3 insertions(+) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index e82ae09d3..d58625e82 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,5 +1,6 @@ # 1.0.3 +* Add application/manifest+json lookup by extension. * Add application/toml mimeType lookup by extension. * Add audio/aac mimeType lookup by header bytes. * Add audio/mpeg mimeType lookup by header bytes. diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index 64f407422..e66733fce 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -898,6 +898,8 @@ const Map defaultExtensionMap = { 'wdp': 'image/vnd.ms-photo', 'weba': 'audio/webm', 'webm': 'video/webm', + // Source: https://w3c.github.io/manifest/#media-type-registration + 'webmanifest': 'application/manifest+json', 'webp': 'image/webp', 'wg': 'application/vnd.pmi.widget', 'wgt': 'application/widget', From cd28ae2c7d3ba8c0998fcbce430e72fb72e8ebee Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 12 Dec 2022 10:56:46 -0800 Subject: [PATCH 079/118] Add .msj (and change .js) to text/javascript (dart-lang/mime#76) --- pkgs/mime/CHANGELOG.md | 6 ++++++ pkgs/mime/lib/src/default_extension_map.dart | 3 ++- pkgs/mime/pubspec.yaml | 2 +- pkgs/mime/test/mime_type_test.dart | 3 ++- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index d58625e82..a5864eeb7 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,9 @@ +# 1.0.4-dev + +* Changed `.js` to `text/javascript` per + https://datatracker.ietf.org/doc/html/rfc9239. +* Added `.mjs` as `text/javascript`. + # 1.0.3 * Add application/manifest+json lookup by extension. diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index e66733fce..c2de6b9f6 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -367,7 +367,7 @@ const Map defaultExtensionMap = { 'jpgm': 'video/jpm', 'jpgv': 'video/jpeg', 'jpm': 'video/jpm', - 'js': 'application/javascript', + 'js': 'text/javascript', 'json': 'application/json', 'jsonml': 'application/jsonml+json', 'kar': 'audio/midi', @@ -451,6 +451,7 @@ const Map defaultExtensionMap = { 'mime': 'message/rfc822', 'mj2': 'video/mj2', 'mjp2': 'video/mj2', + 'mjs': 'text/javascript', 'mk3d': 'video/x-matroska', 'mka': 'audio/x-matroska', 'mks': 'video/x-matroska', diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index b675981a1..144d0e6a8 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 1.0.3 +version: 1.0.4-dev description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index e99214a33..264f18ccb 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -35,7 +35,8 @@ void main() { _expectMimeType('file.cc', 'text/x-c'); _expectMimeType('file.c', 'text/x-c'); _expectMimeType('file.css', 'text/css'); - _expectMimeType('file.js', 'application/javascript'); + _expectMimeType('file.js', 'text/javascript'); + _expectMimeType('file.mjs', 'text/javascript'); _expectMimeType('file.ps', 'application/postscript'); _expectMimeType('file.pdf', 'application/pdf'); _expectMimeType('file.tiff', 'image/tiff'); From 62e5f508af685715f6344f7b7568a6f835af2659 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 12 Dec 2022 13:44:22 -0800 Subject: [PATCH 080/118] blast_repo fixes (dart-lang/mime#79) GitHub Action No Response --- pkgs/mime/.github/workflows/no-response.yml | 34 ++++++++++++++++++++ pkgs/mime/.github/workflows/test-package.yml | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 pkgs/mime/.github/workflows/no-response.yml diff --git a/pkgs/mime/.github/workflows/no-response.yml b/pkgs/mime/.github/workflows/no-response.yml new file mode 100644 index 000000000..fdc1c6aa1 --- /dev/null +++ b/pkgs/mime/.github/workflows/no-response.yml @@ -0,0 +1,34 @@ +# A workflow to close issues where the author hasn't responded to a request for +# more information; see https://github.com/godofredoc/no-response for docs. + +name: No Response + +# Both `issue_comment` and `scheduled` event types are required. +on: + issue_comment: + types: [created] + schedule: + # Schedule for five minutes after the hour, every hour + - cron: '5 * * * *' + +# All permissions not specified are set to 'none'. +permissions: + issues: write + +jobs: + noResponse: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'dart-lang' }} + steps: + - uses: godofredoc/no-response@0ce2dc0e63e1c7d2b87752ceed091f6d32c9df09 + with: + responseRequiredLabel: "needs-info" + responseRequiredColor: 4774bc + daysUntilClose: 14 + # Comment to post when closing an Issue for lack of response. + closeComment: > + Without additional information we're not able to resolve this + issue, so it will be closed at this time. You're still free to add + more info and respond to any questions above, though. We'll reopen + the case if you do. Thanks for your contribution! + token: ${{ github.token }} diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 13160c1f4..6be45cb52 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d - name: Install dependencies From 7a65624ad1536d8e4d8b07a9bc033af606fc8fc1 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 12 Dec 2022 13:58:43 -0800 Subject: [PATCH 081/118] Update to latest lints, bump min SDK to 2.18 (dart-lang/mime#77) Also drop reference to deprecated pkg:http_server --- pkgs/mime/.github/workflows/test-package.yml | 2 +- pkgs/mime/CHANGELOG.md | 1 + pkgs/mime/README.md | 10 --- pkgs/mime/analysis_options.yaml | 43 ++++++++++++- pkgs/mime/lib/src/bound_multipart_stream.dart | 22 +++---- .../lib/src/mime_multipart_transformer.dart | 4 +- pkgs/mime/lib/src/mime_shared.dart | 2 + pkgs/mime/lib/src/mime_type.dart | 4 +- pkgs/mime/pubspec.yaml | 4 +- .../test/mime_multipart_transformer_test.dart | 63 ++++++++++--------- pkgs/mime/test/mime_type_test.dart | 8 +-- 11 files changed, 97 insertions(+), 66 deletions(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 6be45cb52..9beaf806d 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.18.0, dev] steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index a5864eeb7..41bda0c5b 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -3,6 +3,7 @@ * Changed `.js` to `text/javascript` per https://datatracker.ietf.org/doc/html/rfc9239. * Added `.mjs` as `text/javascript`. +* Require Dart 2.18. # 1.0.3 diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index a107306b8..4cd060ce7 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -57,13 +57,3 @@ request .map((part) => part.fold(0, (p, d) => p + d)) .listen((length) => print('Part with length $length')); ``` - -Take a look at the `HttpBodyHandler` in the [http_server][http_server] -package for handling different content types in an HTTP request. - -## Features and bugs - -Please file feature requests and bugs at the [issue tracker][tracker]. - -[tracker]: https://github.com/dart-lang/mime/issues -[http_server]: https://pub.dev/packages/http_server diff --git a/pkgs/mime/analysis_options.yaml b/pkgs/mime/analysis_options.yaml index 28eed4ced..b507c06db 100644 --- a/pkgs/mime/analysis_options.yaml +++ b/pkgs/mime/analysis_options.yaml @@ -1,18 +1,55 @@ +# https://dart.dev/guides/language/analysis-options include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true + strict-inference: true + strict-raw-types: true linter: rules: + - always_declare_return_types + - avoid_bool_literals_in_conditional_expressions + - avoid_catching_errors + - avoid_classes_with_only_static_members - avoid_dynamic_calls + - avoid_private_typedef_functions + - avoid_redundant_argument_values + - avoid_returning_null_for_future + - avoid_returning_this - avoid_unused_constructor_parameters + - avoid_void_async - cancel_subscriptions - - depend_on_referenced_packages + - comment_references - directives_ordering + - join_return_with_assignment + - lines_longer_than_80_chars + - literal_only_boolean_expressions + - missing_whitespace_between_adjacent_strings + - no_adjacent_strings_in_list + - no_runtimeType_toString + - omit_local_variable_types + - only_throw_errors - package_api_docs + - prefer_asserts_in_initializer_lists + - prefer_const_constructors + - prefer_const_declarations - prefer_expression_function_bodies + - prefer_final_locals + - prefer_relative_imports + - prefer_single_quotes + - sort_pub_dependencies - test_types_in_equals - throw_in_finally + - type_annotate_public_apis + - unawaited_futures + - unnecessary_await_in_return + - unnecessary_lambdas - unnecessary_parenthesis + - unnecessary_raw_strings + - unnecessary_statements + - use_if_null_to_convert_nulls_to_bools + - use_raw_strings + - use_string_buffers + - use_super_parameters diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index ae46499b9..6202017fc 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -25,13 +25,13 @@ int _toLowerCase(int byte) { void _expectByteValue(int val1, int val2) { if (val1 != val2) { - throw MimeMultipartException('Failed to parse multipart mime 1'); + throw const MimeMultipartException('Failed to parse multipart mime 1'); } } void _expectWhitespace(int byte) { if (byte != char_code.sp && byte != char_code.ht) { - throw MimeMultipartException('Failed to parse multipart mime 2'); + throw const MimeMultipartException('Failed to parse multipart mime 2'); } } @@ -93,7 +93,7 @@ class BoundMultipartStream { Stream get stream => _controller.stream; - late StreamSubscription _subscription; + late StreamSubscription _subscription; StreamController>? _multipartController; Map? _headers; @@ -127,7 +127,7 @@ class BoundMultipartStream { }, onDone: () { if (_state != _doneCode) { _controller - .addError(MimeMultipartException('Bad multipart ending')); + .addError(const MimeMultipartException('Bad multipart ending')); } _controller.close(); }, onError: _controller.addError); @@ -167,7 +167,7 @@ class BoundMultipartStream { // Number of boundary bytes to artificially place before the supplied data. // The data to parse might be 'artificially' prefixed with a // partial match of the boundary. - var boundaryPrefix = _boundaryIndex; + final boundaryPrefix = _boundaryIndex; // Position where content starts. Will be null if no known content // start exists. Will be negative of the content starts in the // boundary prefix. Will be zero or position if the content starts @@ -182,7 +182,7 @@ class BoundMultipartStream { // can be negative. void reportData() { if (contentStartIndex! < 0) { - var contentLength = boundaryPrefix + _index - _boundaryIndex; + final contentLength = boundaryPrefix + _index - _boundaryIndex; if (contentLength <= boundaryPrefix) { _multipartController!.add(_boundary.sublist(0, contentLength)); } else { @@ -191,7 +191,7 @@ class BoundMultipartStream { .add(_buffer.sublist(0, contentLength - boundaryPrefix)); } } else { - var contentEndIndex = _index - _boundaryIndex; + final contentEndIndex = _index - _boundaryIndex; _multipartController! .add(_buffer.sublist(contentStartIndex, contentEndIndex)); } @@ -199,7 +199,7 @@ class BoundMultipartStream { while ( _index < _buffer.length && _state != _failCode && _state != _doneCode) { - var byte = + final byte = _index < 0 ? _boundary[boundaryPrefix + _index] : _buffer[_index]; switch (_state) { case _startCode: @@ -252,7 +252,7 @@ class BoundMultipartStream { _state = _headerValueStartCode; } else { if (!_isTokenChar(byte)) { - throw MimeMultipartException('Invalid header field name'); + throw const MimeMultipartException('Invalid header field name'); } _headerField.add(_toLowerCase(byte)); } @@ -285,8 +285,8 @@ class BoundMultipartStream { if (byte == char_code.sp || byte == char_code.ht) { _state = _headerValueStartCode; } else { - var headerField = utf8.decode(_headerField); - var headerValue = utf8.decode(_headerValue); + final headerField = utf8.decode(_headerField); + final headerValue = utf8.decode(_headerValue); _headers![headerField.toLowerCase()] = headerValue; _headerField.clear(); _headerValue.clear(); diff --git a/pkgs/mime/lib/src/mime_multipart_transformer.dart b/pkgs/mime/lib/src/mime_multipart_transformer.dart index a3da85755..2648d7d88 100644 --- a/pkgs/mime/lib/src/mime_multipart_transformer.dart +++ b/pkgs/mime/lib/src/mime_multipart_transformer.dart @@ -10,9 +10,9 @@ import 'char_code.dart' as char_code; import 'mime_shared.dart'; Uint8List _getBoundary(String boundary) { - var charCodes = boundary.codeUnits; + final charCodes = boundary.codeUnits; - var boundaryList = Uint8List(4 + charCodes.length); + final boundaryList = Uint8List(4 + charCodes.length); // Set-up the matching boundary preceding it with CRLF and two // dashes. boundaryList[0] = char_code.cr; diff --git a/pkgs/mime/lib/src/mime_shared.dart b/pkgs/mime/lib/src/mime_shared.dart index 2a29ae07e..1c98971e9 100644 --- a/pkgs/mime/lib/src/mime_shared.dart +++ b/pkgs/mime/lib/src/mime_shared.dart @@ -2,6 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'mime_multipart_transformer.dart'; + class MimeMultipartException implements Exception { final String message; diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index e72806e0c..03121c97b 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -77,7 +77,7 @@ class MimeTypeResolver { if (result != null) return result; } } - var ext = _ext(path); + final ext = _ext(path); result = _extensionMap[ext]; if (result != null) return result; if (_useDefault) { @@ -116,7 +116,7 @@ class MimeTypeResolver { } static String _ext(String path) { - var index = path.lastIndexOf('.'); + final index = path.lastIndexOf('.'); if (index < 0 || index + 1 >= path.length) return path; return path.substring(index + 1).toLowerCase(); } diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 144d0e6a8..186f2880f 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -6,8 +6,8 @@ description: >- repository: https://github.com/dart-lang/mime environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.18.0 <3.0.0' dev_dependencies: - lints: ^1.0.0 + lints: ^2.0.0 test: ^1.16.0 diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 6a4437226..551bf55c1 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -13,8 +13,8 @@ void _writeInChunks( if (chunkSize == -1) chunkSize = data.length; for (var pos = 0; pos < data.length; pos += chunkSize) { - var remaining = data.length - pos; - var writeLength = min(chunkSize, remaining); + final remaining = data.length - pos; + final writeLength = min(chunkSize, remaining); controller.add(data.sublist(pos, pos + writeLength)); } controller.close(); @@ -26,20 +26,20 @@ void _runParseTest( String message, String boundary, TestMode mode, [ - List? expectedHeaders, + List>? expectedHeaders, List? expectedParts, bool expectError = false, ]) { - Future testWrite(List data, [int chunkSize = -1]) { - var controller = StreamController>(sync: true); + Future testWrite(List data, [int chunkSize = -1]) { + final controller = StreamController>(sync: true); - var stream = + final stream = controller.stream.transform(MimeMultipartTransformer(boundary)); var i = 0; - var completer = Completer(); - var futures = []; + final completer = Completer(); + final futures = >[]; stream.listen((multipart) { - var part = i++; + final part = i++; if (expectedHeaders != null) { expect(multipart.headers, equals(expectedHeaders[part])); } @@ -71,10 +71,10 @@ void _runParseTest( break; case TestMode.pauseResume: - var completer = Completer(); + final completer = Completer(); futures.add(completer.future); - var buffer = []; - late StreamSubscription subscription; + final buffer = []; + late StreamSubscription> subscription; subscription = multipart.listen((data) { buffer.addAll(data); subscription.pause(); @@ -89,6 +89,7 @@ void _runParseTest( break; } }, onError: (Object error) { + // ignore: only_throw_errors if (!expectError) throw error; }, onDone: () { if (expectedParts != null) { @@ -102,11 +103,11 @@ void _runParseTest( return completer.future; } - Future testFirstPartOnly(List data, [int chunkSize = -1]) { - var completer = Completer(); - var controller = StreamController>(sync: true); + Future testFirstPartOnly(List data, [int chunkSize = -1]) { + final completer = Completer(); + final controller = StreamController>(sync: true); - var stream = + final stream = controller.stream.transform(MimeMultipartTransformer(boundary)); stream.first.then((multipart) { @@ -129,17 +130,17 @@ void _runParseTest( return completer.future; } - Future testCompletePartAfterCancel(List data, int parts, + Future testCompletePartAfterCancel(List data, int parts, [int chunkSize = -1]) { - var completer = Completer(); - var controller = StreamController>(sync: true); - var stream = + final completer = Completer(); + final controller = StreamController>(sync: true); + final stream = controller.stream.transform(MimeMultipartTransformer(boundary)); - late StreamSubscription subscription; + late StreamSubscription subscription; var i = 0; - var futures = []; + final futures = >[]; subscription = stream.listen((multipart) { - var partIndex = i; + final partIndex = i; if (partIndex >= parts) { throw StateError('Expected no more parts, but got one.'); @@ -169,7 +170,7 @@ void _runParseTest( // Test parsing the data three times delivering the data in // different chunks. - var data = message.codeUnits; + final data = message.codeUnits; test('test', () { expect( Future.wait([ @@ -210,7 +211,7 @@ void _runParseTest( } void _testParse(String message, String boundary, - [List? expectedHeaders, + [List>? expectedHeaders, List? expectedParts, bool expectError = false]) { _runParseTest(message, boundary, TestMode.immediateListen, expectedHeaders, @@ -316,16 +317,16 @@ on\r headers2 = { 'content-disposition': 'form-data; name="password_input"' }; - var headers3 = { + final headers3 = { 'content-disposition': 'form-data; name="checkbox_input"' }; - var headers4 = { + final headers4 = { 'content-disposition': 'form-data; name="radio_input"' }; body1 = 'text'; body2 = 'password'; - var body3 = 'on'; - var body4 = 'on'; + const body3 = 'on'; + const body4 = 'on'; _testParse(message, '----WebKitFormBoundaryQ3cgYAmGRF8yOeYB', [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); @@ -412,7 +413,7 @@ Content-Type: text/plain\r --\r\r\r -\r\r --boundary--\r\n'''; - var headers = {'content-type': 'text/plain'}; + final headers = {'content-type': 'text/plain'}; body1 = ''' -\r --\r @@ -451,7 +452,7 @@ Body2\r void _testParseInvalid() { // Missing end boundary. - var message = ''' + const message = ''' \r --xxx\r \r diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 264f18ccb..342912581 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -150,19 +150,19 @@ void main() { group('custom-resolver', () { test('override-extension', () { - var resolver = MimeTypeResolver(); + final resolver = MimeTypeResolver(); resolver.addExtension('jpg', 'my-mime-type'); _expectMimeType('file.jpg', 'my-mime-type', resolver: resolver); }); test('fallthrough-extension', () { - var resolver = MimeTypeResolver(); + final resolver = MimeTypeResolver(); resolver.addExtension('jpg2', 'my-mime-type'); _expectMimeType('file.jpg', 'image/jpeg', resolver: resolver); }); test('with-mask', () { - var resolver = MimeTypeResolver.empty(); + final resolver = MimeTypeResolver.empty(); resolver.addMagicNumber([0x01, 0x02, 0x03], 'my-mime-type', mask: [0x01, 0xFF, 0xFE]); _expectMimeType('file', 'my-mime-type', @@ -175,7 +175,7 @@ void main() { }); test('default magic number', () { - var actualMaxBytes = initialMagicNumbers.fold( + final actualMaxBytes = initialMagicNumbers.fold( 0, (previous, magic) => math.max(previous, magic.numbers.length), ); From 374e194c8b8d94d347d33821b863a6d052f22669 Mon Sep 17 00:00:00 2001 From: tomk9 Date: Tue, 13 Dec 2022 16:49:04 +0100 Subject: [PATCH 082/118] Add .dcm to extension map (dart-lang/mime#74) --- pkgs/mime/CHANGELOG.md | 1 + pkgs/mime/lib/src/default_extension_map.dart | 1 + pkgs/mime/test/mime_type_test.dart | 1 + 3 files changed, 3 insertions(+) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 41bda0c5b..43104733c 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -3,6 +3,7 @@ * Changed `.js` to `text/javascript` per https://datatracker.ietf.org/doc/html/rfc9239. * Added `.mjs` as `text/javascript`. +* Add `application/dicom` mimeType lookup by extension. * Require Dart 2.18. # 1.0.3 diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index c2de6b9f6..c3ad00529 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -152,6 +152,7 @@ const Map defaultExtensionMap = { 'dataless': 'application/vnd.fdsn.seed', 'davmount': 'application/davmount+xml', 'dbk': 'application/docbook+xml', + 'dcm': 'application/dicom', 'dcr': 'application/x-director', 'dcurl': 'text/vnd.curl.dcurl', 'dd2': 'application/vnd.oma.dd2+xml', diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 342912581..5e444e2f7 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -26,6 +26,7 @@ void main() { _expectMimeType('file.dart', 'text/x-dart'); // Test mixed-case _expectMimeType('file.DaRT', 'text/x-dart'); + _expectMimeType('file.dcm', 'application/dicom'); _expectMimeType('file.html', 'text/html'); _expectMimeType('file.xhtml', 'application/xhtml+xml'); _expectMimeType('file.jpeg', 'image/jpeg'); From bc8dc4542dea47a3ed59af1d214600343e4eb4da Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 11 Jan 2023 16:32:10 -0800 Subject: [PATCH 083/118] Prepare to release v1.0.4 (dart-lang/mime#80) --- pkgs/mime/CHANGELOG.md | 2 +- pkgs/mime/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 43104733c..c6fec4250 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,4 +1,4 @@ -# 1.0.4-dev +# 1.0.4 * Changed `.js` to `text/javascript` per https://datatracker.ietf.org/doc/html/rfc9239. diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 186f2880f..46be106f7 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 1.0.4-dev +version: 1.0.4 description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. From 0e76b39799ed1d752d82db555114052ba24ec197 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 08:35:44 -0800 Subject: [PATCH 084/118] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/mime#83) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 9beaf806d..4ccbbb809 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -21,7 +21,7 @@ jobs: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 - name: Install dependencies run: dart pub get From 58bc283dce166919fa1a57365ad86e5bc1e1c1f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 08:38:31 -0800 Subject: [PATCH 085/118] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/mime#82) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 4ccbbb809..377de0eb4 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 - name: Install dependencies From 29639370644fb6bb38a4ffcfcae303e775d8a626 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:40:20 -0700 Subject: [PATCH 086/118] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/mime#91) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 377de0eb4..dfe7499df 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 - name: Install dependencies From c8089ada89b283adf5ddd5235076542021c25cd4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:57:29 -0700 Subject: [PATCH 087/118] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/mime#90) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index dfe7499df..8ec3c8d2c 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -21,7 +21,7 @@ jobs: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f - name: Install dependencies run: dart pub get From 5cae2dd3ddd191d31b1477e9250a98601b699a14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:27:36 -0700 Subject: [PATCH 088/118] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/mime#93) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 8ec3c8d2c..68acfa70d 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f - name: Install dependencies From 4e5bf5a8ef076698b41cafc01c0540b009dadc5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lara=20Sch=C3=BCtt?= Date: Tue, 9 May 2023 02:32:45 +0200 Subject: [PATCH 089/118] Add `text/markdown` mimeType lookup by extension (dart-lang/mime#85) Add `.md` and `.markdown` extensions. --- pkgs/mime/CHANGELOG.md | 4 ++++ pkgs/mime/lib/src/default_extension_map.dart | 3 +++ pkgs/mime/pubspec.yaml | 2 +- pkgs/mime/test/mime_type_test.dart | 2 ++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index c6fec4250..404af3c54 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,7 @@ +# 1.0.5 + +* Add `text/markdown` mimeType lookup by extension. + # 1.0.4 * Changed `.js` to `text/javascript` per diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index c3ad00529..2d28b46ec 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -434,6 +434,9 @@ const Map defaultExtensionMap = { 'mc1': 'application/vnd.medcalcdata', 'mcd': 'application/vnd.mcd', 'mcurl': 'text/vnd.curl.mcurl', + // https://www.rfc-editor.org/rfc/rfc7763 + 'md': 'text/markdown', + 'markdown': 'text/markdown', 'mdb': 'application/x-msaccess', 'mdi': 'image/vnd.ms-modi', 'me': 'text/troff', diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 46be106f7..2f83e46af 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 1.0.4 +version: 1.0.5 description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 5e444e2f7..2d8a75bc7 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -49,6 +49,8 @@ void main() { _expectMimeType('file.aiff', 'audio/x-aiff'); _expectMimeType('file.m4a', 'audio/mp4'); _expectMimeType('file.toml', 'application/toml'); + _expectMimeType('file.md', 'text/markdown'); + _expectMimeType('file.markdown', 'text/markdown'); }); test('unknown-mime-type', () { From 2307b6dfc16995752aab0e7bfb16b9dd12bbdea1 Mon Sep 17 00:00:00 2001 From: Dimitar Petrov Date: Tue, 9 May 2023 19:16:55 +0100 Subject: [PATCH 090/118] Add m4b mime type (dart-lang/mime#92) --- pkgs/mime/CHANGELOG.md | 3 ++- pkgs/mime/lib/src/default_extension_map.dart | 3 ++- pkgs/mime/pubspec.yaml | 2 +- pkgs/mime/test/mime_type_test.dart | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 404af3c54..d44ddfe61 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,5 +1,6 @@ -# 1.0.5 +# 1.0.5-wip +* Add m4b mimeType lookup by extension. * Add `text/markdown` mimeType lookup by extension. # 1.0.4 diff --git a/pkgs/mime/lib/src/default_extension_map.dart b/pkgs/mime/lib/src/default_extension_map.dart index 2d28b46ec..287c957dc 100644 --- a/pkgs/mime/lib/src/default_extension_map.dart +++ b/pkgs/mime/lib/src/default_extension_map.dart @@ -417,8 +417,9 @@ const Map defaultExtensionMap = { 'm3a': 'audio/mpeg', 'm3u': 'audio/x-mpegurl', 'm3u8': 'application/vnd.apple.mpegurl', - // Source: https://www.rfc-editor.org/rfc/rfc4337#page-3 + // Source: https://datatracker.ietf.org/doc/html/rfc4337#section-2 'm4a': 'audio/mp4', + 'm4b': 'audio/mp4', 'm4u': 'video/vnd.mpegurl', 'm4v': 'video/x-m4v', 'ma': 'application/mathematica', diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 2f83e46af..e94727a24 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 1.0.5 +version: 1.0.5-wip description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 2d8a75bc7..099d5e8fe 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -48,6 +48,7 @@ void main() { _expectMimeType('file.ogg', 'audio/ogg'); _expectMimeType('file.aiff', 'audio/x-aiff'); _expectMimeType('file.m4a', 'audio/mp4'); + _expectMimeType('file.m4b', 'audio/mp4'); _expectMimeType('file.toml', 'application/toml'); _expectMimeType('file.md', 'text/markdown'); _expectMimeType('file.markdown', 'text/markdown'); From 0d93a1608c988fa692550d914ace0366bf64fbb1 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 10 May 2023 14:41:17 -0700 Subject: [PATCH 091/118] blast_repo fixes (dart-lang/mime#95) no-response --- pkgs/mime/.github/workflows/no-response.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/mime/.github/workflows/no-response.yml b/pkgs/mime/.github/workflows/no-response.yml index fdc1c6aa1..ac3e456ec 100644 --- a/pkgs/mime/.github/workflows/no-response.yml +++ b/pkgs/mime/.github/workflows/no-response.yml @@ -8,8 +8,8 @@ on: issue_comment: types: [created] schedule: - # Schedule for five minutes after the hour, every hour - - cron: '5 * * * *' + # Every day at 8am + - cron: '0 8 * * *' # All permissions not specified are set to 'none'. permissions: @@ -27,8 +27,8 @@ jobs: daysUntilClose: 14 # Comment to post when closing an Issue for lack of response. closeComment: > - Without additional information we're not able to resolve this - issue, so it will be closed at this time. You're still free to add - more info and respond to any questions above, though. We'll reopen - the case if you do. Thanks for your contribution! + Without additional information we're not able to resolve this issue, + so it will be closed at this time. You're still free to add more + info and respond to any questions above, though. We'll reopen the + issue if you do. Thanks for your contribution! token: ${{ github.token }} From d8bcb85e5b02decdab344399eb0b3e0865e1acbf Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 23 May 2023 10:10:25 -0700 Subject: [PATCH 092/118] blast_repo fixes (dart-lang/mime#97) dependabot --- pkgs/mime/.github/dependabot.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/mime/.github/dependabot.yaml b/pkgs/mime/.github/dependabot.yaml index 214481934..439e796b4 100644 --- a/pkgs/mime/.github/dependabot.yaml +++ b/pkgs/mime/.github/dependabot.yaml @@ -2,7 +2,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From 3e3071e21711eeba57ddd6502f3ebfbb435c2bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD=20=D0=93=D0=BE=D0=BB=D1=83=D0=B1?= =?UTF-8?q?=D1=8B=D1=85?= Date: Fri, 26 May 2023 20:43:55 +0400 Subject: [PATCH 093/118] Improve the detection of mp4 types dart-lang/mime#86 (dart-lang/mime#98) Add more byte patterns for the values that can follow `ftyp` in an mp4 file. --- pkgs/mime/CHANGELOG.md | 1 + pkgs/mime/lib/src/magic_number.dart | 137 +++++++++++++++++++++++++++- pkgs/mime/test/mime_type_test.dart | 86 ++++++++++++++++- 3 files changed, 222 insertions(+), 2 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index d44ddfe61..d52b8da74 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,5 +1,6 @@ # 1.0.5-wip +* Update video/mp4 mimeType lookup by header bytes. * Add m4b mimeType lookup by extension. * Add `text/markdown` mimeType lookup by extension. diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index ee3de3143..5de7d87ab 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -113,7 +113,7 @@ const List initialMagicNumbers = [ MagicNumber('audio/mpeg', [0x49, 0x44, 0x33]), MagicNumber('audio/mpeg', [0xFF, 0xFB]), MagicNumber('audio/ogg', [0x4F, 0x70, 0x75]), - MagicNumber('video/mp4', [ + MagicNumber('video/3gpp', [ 0x00, 0x00, 0x00, @@ -140,6 +140,141 @@ const List initialMagicNumbers = [ 0xFF, 0xFF ]), + MagicNumber('video/mp4', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x61, + 0x76, + 0x63, + 0x31 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + MagicNumber('video/mp4', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x69, + 0x73, + 0x6F, + 0x32 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + MagicNumber('video/mp4', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x69, + 0x73, + 0x6F, + 0x6D + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + MagicNumber('video/mp4', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x70, + 0x34, + 0x31 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + MagicNumber('video/mp4', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x70, + 0x34, + 0x32 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), MagicNumber('model/gltf-binary', [0x46, 0x54, 0x6C, 0x67]), /// The WebP file format is based on the RIFF document format. diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 099d5e8fe..f10d84724 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -85,7 +85,7 @@ void main() { 0x1A, 0x0A ]); - _expectMimeType('file.mp4', 'video/mp4', headerBytes: [ + _expectMimeType('file', 'video/3gpp', headerBytes: [ 0x00, 0x00, 0x00, @@ -99,6 +99,90 @@ void main() { 0x70, 0x35 ]); + _expectMimeType('file.mp4', 'video/mp4', headerBytes: [ + 0x00, + 0x00, + 0x00, + 0x04, + 0x66, + 0x74, + 0x79, + 0x70, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]); + _expectMimeType('file', 'video/mp4', headerBytes: [ + 0x00, + 0xF0, + 0xF0, + 0xF0, + 0x66, + 0x74, + 0x79, + 0x70, + 0x61, + 0x76, + 0x63, + 0x31 + ]); + _expectMimeType('file', 'video/mp4', headerBytes: [ + 0x00, + 0xF0, + 0xF0, + 0xF0, + 0x66, + 0x74, + 0x79, + 0x70, + 0x69, + 0x73, + 0x6F, + 0x32 + ]); + _expectMimeType('file', 'video/mp4', headerBytes: [ + 0x00, + 0xF0, + 0xF0, + 0xF0, + 0x66, + 0x74, + 0x79, + 0x70, + 0x69, + 0x73, + 0x6F, + 0x6D + ]); + _expectMimeType('file', 'video/mp4', headerBytes: [ + 0x00, + 0xF0, + 0xF0, + 0xF0, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x70, + 0x34, + 0x31 + ]); + _expectMimeType('file', 'video/mp4', headerBytes: [ + 0x00, + 0xF0, + 0xF0, + 0xF0, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x70, + 0x34, + 0x32 + ]); _expectMimeType('file', 'image/webp', headerBytes: [ 0x52, 0x49, From 268153c9c2ed924e2f503a23e67a58c1f8a8113b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 08:48:27 +0000 Subject: [PATCH 094/118] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/mime#99) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 68acfa70d..342f3a9d7 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f - name: Install dependencies From 45678cad1f4c9064dfc2ef87352f4322409ca071 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 18 Jul 2023 11:12:39 -0700 Subject: [PATCH 095/118] blast_repo fixes (dart-lang/mime#100) auto-publish, no-response --- pkgs/mime/.github/workflows/no-response.yml | 35 +++++++++++---------- pkgs/mime/.github/workflows/publish.yaml | 17 ++++++++++ pkgs/mime/CHANGELOG.md | 34 ++++++++++---------- 3 files changed, 53 insertions(+), 33 deletions(-) create mode 100644 pkgs/mime/.github/workflows/publish.yaml diff --git a/pkgs/mime/.github/workflows/no-response.yml b/pkgs/mime/.github/workflows/no-response.yml index ac3e456ec..8e5ed57cd 100644 --- a/pkgs/mime/.github/workflows/no-response.yml +++ b/pkgs/mime/.github/workflows/no-response.yml @@ -1,12 +1,10 @@ # A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/godofredoc/no-response for docs. +# more information; see https://github.com/actions/stale. name: No Response -# Both `issue_comment` and `scheduled` event types are required. +# Run as a daily cron. on: - issue_comment: - types: [created] schedule: # Every day at 8am - cron: '0 8 * * *' @@ -14,21 +12,26 @@ on: # All permissions not specified are set to 'none'. permissions: issues: write + pull-requests: write jobs: - noResponse: + no-response: runs-on: ubuntu-latest if: ${{ github.repository_owner == 'dart-lang' }} steps: - - uses: godofredoc/no-response@0ce2dc0e63e1c7d2b87752ceed091f6d32c9df09 + - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 with: - responseRequiredLabel: "needs-info" - responseRequiredColor: 4774bc - daysUntilClose: 14 - # Comment to post when closing an Issue for lack of response. - closeComment: > - Without additional information we're not able to resolve this issue, - so it will be closed at this time. You're still free to add more - info and respond to any questions above, though. We'll reopen the - issue if you do. Thanks for your contribution! - token: ${{ github.token }} + # Don't automatically mark inactive issues+PRs as stale. + days-before-stale: -1 + # Close needs-info issues and PRs after 14 days of inactivity. + days-before-close: 14 + stale-issue-label: "needs-info" + close-issue-message: > + Without additional information we're not able to resolve this issue. + Feel free to add more info or respond to any questions above and we + can reopen the case. Thanks for your contribution! + stale-pr-label: "needs-info" + close-pr-message: > + Without additional information we're not able to resolve this PR. + Feel free to add more info or respond to any questions above. + Thanks for your contribution! diff --git a/pkgs/mime/.github/workflows/publish.yaml b/pkgs/mime/.github/workflows/publish.yaml new file mode 100644 index 000000000..27157a046 --- /dev/null +++ b/pkgs/mime/.github/workflows/publish.yaml @@ -0,0 +1,17 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ master ] + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + permissions: + id-token: write # Required for authentication using OIDC + pull-requests: write # Required for writing the pull request note diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index d52b8da74..0f9e68634 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,10 +1,10 @@ -# 1.0.5-wip +## 1.0.5-wip * Update video/mp4 mimeType lookup by header bytes. * Add m4b mimeType lookup by extension. * Add `text/markdown` mimeType lookup by extension. -# 1.0.4 +## 1.0.4 * Changed `.js` to `text/javascript` per https://datatracker.ietf.org/doc/html/rfc9239. @@ -12,7 +12,7 @@ * Add `application/dicom` mimeType lookup by extension. * Require Dart 2.18. -# 1.0.3 +## 1.0.3 * Add application/manifest+json lookup by extension. * Add application/toml mimeType lookup by extension. @@ -26,55 +26,55 @@ * Add image/heif mimeType lookup by extension. * Change audio/x-aac to audio/aac when detected by extension. -# 1.0.2 +## 1.0.2 * Add audio/x-aiff mimeType lookup by header bytes. * Add audio/x-flac mimeType lookup by header bytes. * Add audio/x-wav mimeType lookup by header bytes. * Add audio/mp4 mimeType lookup by file path. -# 1.0.1 +## 1.0.1 * Add image/webp mimeType lookup by header bytes. -# 1.0.0 +## 1.0.0 * Stable null safety release. -# 1.0.0-nullsafety.0 +## 1.0.0-nullsafety.0 * Update to null safety. -# 0.9.7 +## 0.9.7 * Add `extensionFromMime` utility function. -# 0.9.6+3 +## 0.9.6+3 * Change the mime type for Dart source from `application/dart` to `text/x-dart`. * Add example. * Fix links and code in README. -# 0.9.6+2 +## 0.9.6+2 * Set max SDK version to `<3.0.0`, and adjust other dependencies. -# 0.9.6+1 +## 0.9.6+1 * Stop using deprecated constants from the SDK. -# 0.9.6 +## 0.9.6 * Updates to support Dart 2.0 core library changes (wave 2.2). See [issue 31847][sdk#31847] for details. [sdk#31847]: https://github.com/dart-lang/sdk/issues/31847 -# 0.9.5 +## 0.9.5 * Add support for the WebAssembly format. -# 0.9.4 +## 0.9.4 * Updated Dart SDK requirement to `>= 1.8.3 <2.0.0` @@ -82,16 +82,16 @@ * Added support for glTF text and binary formats. -# 0.9.3 +## 0.9.3 * Fixed erroneous behavior for listening and when pausing/resuming stream of parts. -# 0.9.2 +## 0.9.2 * Fixed erroneous behavior when pausing/canceling stream of parts but already listened to one part. -# 0.9.1 +## 0.9.1 * Handle parsing of MIME multipart content with no parts. From 3a363b2ba9ea7e8ea81dcbd203c6f861ab4bdaab Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 18 Jul 2023 12:28:12 -0700 Subject: [PATCH 096/118] update lints, require Dart 3 (dart-lang/mime#101) --- pkgs/mime/.github/workflows/test-package.yml | 2 +- pkgs/mime/CHANGELOG.md | 1 + pkgs/mime/analysis_options.yaml | 19 ++----------------- pkgs/mime/lib/src/bound_multipart_stream.dart | 17 ----------------- pkgs/mime/lib/src/magic_number.dart | 2 -- pkgs/mime/pubspec.yaml | 4 ++-- .../test/mime_multipart_transformer_test.dart | 3 --- 7 files changed, 6 insertions(+), 42 deletions(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 342f3a9d7..69bb65747 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - sdk: [2.18.0, dev] + sdk: [3.0.0, dev] steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 0f9e68634..23be73156 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -3,6 +3,7 @@ * Update video/mp4 mimeType lookup by header bytes. * Add m4b mimeType lookup by extension. * Add `text/markdown` mimeType lookup by extension. +* Require Dart 3.0.0. ## 1.0.4 diff --git a/pkgs/mime/analysis_options.yaml b/pkgs/mime/analysis_options.yaml index b507c06db..41195572c 100644 --- a/pkgs/mime/analysis_options.yaml +++ b/pkgs/mime/analysis_options.yaml @@ -1,5 +1,5 @@ # https://dart.dev/guides/language/analysis-options -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: @@ -9,11 +9,8 @@ analyzer: linter: rules: - - always_declare_return_types - avoid_bool_literals_in_conditional_expressions - - avoid_catching_errors - avoid_classes_with_only_static_members - - avoid_dynamic_calls - avoid_private_typedef_functions - avoid_redundant_argument_values - avoid_returning_null_for_future @@ -22,33 +19,21 @@ linter: - avoid_void_async - cancel_subscriptions - comment_references - - directives_ordering - join_return_with_assignment - - lines_longer_than_80_chars - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - omit_local_variable_types - - only_throw_errors - package_api_docs - - prefer_asserts_in_initializer_lists - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - prefer_relative_imports - - prefer_single_quotes - - sort_pub_dependencies - test_types_in_equals - - throw_in_finally - - type_annotate_public_apis - - unawaited_futures - unnecessary_await_in_return - - unnecessary_lambdas - - unnecessary_parenthesis + - unnecessary_breaks - unnecessary_raw_strings - - unnecessary_statements - use_if_null_to_convert_nulls_to_bools - use_raw_strings - use_string_buffers diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index 6202017fc..cc01fd5b0 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -150,13 +150,10 @@ class BoundMultipartStream { switch (_controllerState) { case _controllerStateActive: if (_subscription.isPaused) _subscription.resume(); - break; case _controllerStatePaused: if (!_subscription.isPaused) _subscription.pause(); - break; case _controllerStateCanceled: _subscription.cancel(); - break; default: throw StateError('This code should never be reached.'); } @@ -214,7 +211,6 @@ class BoundMultipartStream { _index = _index - _boundaryIndex; _boundaryIndex = 0; } - break; case _boundaryEndingCode: if (byte == char_code.cr) { @@ -224,7 +220,6 @@ class BoundMultipartStream { } else { _expectWhitespace(byte); } - break; case _boundaryEndCode: _expectByteValue(byte, char_code.lf); @@ -234,7 +229,6 @@ class BoundMultipartStream { _tryPropagateControllerState(); } _state = _headerStartCode; - break; case _headerStartCode: _headers = {}; @@ -245,7 +239,6 @@ class BoundMultipartStream { _headerField.add(_toLowerCase(byte)); _state = _headerFieldCode; } - break; case _headerFieldCode: if (byte == char_code.colon) { @@ -256,7 +249,6 @@ class BoundMultipartStream { } _headerField.add(_toLowerCase(byte)); } - break; case _headerValueStartCode: if (byte == char_code.cr) { @@ -266,7 +258,6 @@ class BoundMultipartStream { _headerValue.add(byte); _state = _headerValueCode; } - break; case _headerValueCode: if (byte == char_code.cr) { @@ -274,12 +265,10 @@ class BoundMultipartStream { } else { _headerValue.add(byte); } - break; case _headerValueFoldingOrEndingCode: _expectByteValue(byte, char_code.lf); _state = _headerValueFoldOrEndCode; - break; case _headerValueFoldOrEndCode: if (byte == char_code.sp || byte == char_code.ht) { @@ -298,7 +287,6 @@ class BoundMultipartStream { _state = _headerFieldCode; } } - break; case _headerEndingCode: _expectByteValue(byte, char_code.lf); @@ -314,7 +302,6 @@ class BoundMultipartStream { _headers = null; _state = _contentCode; contentStartIndex = _index + 1; - break; case _contentCode: if (byte == _boundary[_boundaryIndex]) { @@ -337,12 +324,10 @@ class BoundMultipartStream { contentStartIndex ??= _index; _boundaryIndex = 0; } - break; case _lastBoundaryDash2Code: _expectByteValue(byte, char_code.dash); _state = _lastBoundaryEndingCode; - break; case _lastBoundaryEndingCode: if (byte == char_code.cr) { @@ -350,7 +335,6 @@ class BoundMultipartStream { } else { _expectWhitespace(byte); } - break; case _lastBoundaryEndCode: _expectByteValue(byte, char_code.lf); @@ -360,7 +344,6 @@ class BoundMultipartStream { _tryPropagateControllerState(); } _state = _doneCode; - break; default: // Should be unreachable. diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index 5de7d87ab..cf735f80e 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library mime.magic_number; - class MagicNumber { final String mimeType; final List numbers; diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index e94727a24..3dd77f9bb 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -6,8 +6,8 @@ description: >- repository: https://github.com/dart-lang/mime environment: - sdk: '>=2.18.0 <3.0.0' + sdk: ^3.0.0 dev_dependencies: - lints: ^2.0.0 + dart_flutter_team_lints: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/mime/test/mime_multipart_transformer_test.dart b/pkgs/mime/test/mime_multipart_transformer_test.dart index 551bf55c1..109a9bcd8 100644 --- a/pkgs/mime/test/mime_multipart_transformer_test.dart +++ b/pkgs/mime/test/mime_multipart_transformer_test.dart @@ -51,7 +51,6 @@ void _runParseTest( expect(data, equals(expectedParts?[part]!.codeUnits)); } })); - break; case TestMode.delayListen: futures.add( @@ -68,7 +67,6 @@ void _runParseTest( ), ), ); - break; case TestMode.pauseResume: final completer = Completer(); @@ -86,7 +84,6 @@ void _runParseTest( completer.complete(); }); addTearDown(subscription.cancel); - break; } }, onError: (Object error) { // ignore: only_throw_errors From 7acfa88b81ee4a3fec5993ac8bb46add7e4c9fa5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 08:49:04 +0000 Subject: [PATCH 097/118] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/mime#104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 69bb65747..4ffff9ff9 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f - name: Install dependencies From 0e23c58eba5e82262f63d92e0bb8441a61de8a97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 08:12:13 +0000 Subject: [PATCH 098/118] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/mime#105) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0.
Release notes

Sourced from actions/checkout's releases.

v4.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.0.0...v4.1.0

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 4ffff9ff9..b4328e671 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f - name: Install dependencies From 100efb562a061b1ad0072323dac6c3bb8d69c03b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 07:12:37 -0700 Subject: [PATCH 099/118] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/mime#106) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/d6a63dab3335f427404425de0fbfed4686d93c4f...8a4b97ea2017cc079571daec46542f76189836b1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index b4328e671..f2066e5ba 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -21,7 +21,7 @@ jobs: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 - name: Install dependencies run: dart pub get From 76392962b9973373a81bfa8b8782f73ef563d597 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 08:45:21 +0000 Subject: [PATCH 100/118] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/mime#107) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index f2066e5ba..d16e9868e 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 - name: Install dependencies From def44d57d747fa7b263c8239b9c22a639535933b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 14:57:57 +0000 Subject: [PATCH 101/118] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/mime#108) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/mime#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/mime#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index d16e9868e..9a52ddb41 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -21,7 +21,7 @@ jobs: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d - name: Install dependencies run: dart pub get From 82608bc71b1f6f2e1d766893ed79da0d76678728 Mon Sep 17 00:00:00 2001 From: Yoshihiro Tanaka Date: Tue, 5 Dec 2023 02:34:52 +0900 Subject: [PATCH 102/118] Detect HEIC/HEIF format by checking header bytes (dart-lang/mime#109) --- pkgs/mime/CHANGELOG.md | 2 + pkgs/mime/lib/src/magic_number.dart | 95 +++++++++++++++++++++++++++++ pkgs/mime/test/mime_type_test.dart | 47 ++++++++++++++ 3 files changed, 144 insertions(+) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 23be73156..070034938 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,6 +1,8 @@ ## 1.0.5-wip * Update video/mp4 mimeType lookup by header bytes. +* Add image/heic mimeType lookup by header bytes. +* Add image/heif mimeType lookup by header bytes. * Add m4b mimeType lookup by extension. * Add `text/markdown` mimeType lookup by extension. * Require Dart 3.0.0. diff --git a/pkgs/mime/lib/src/magic_number.dart b/pkgs/mime/lib/src/magic_number.dart index cf735f80e..c8b5c3be1 100644 --- a/pkgs/mime/lib/src/magic_number.dart +++ b/pkgs/mime/lib/src/magic_number.dart @@ -309,4 +309,99 @@ const List initialMagicNumbers = [ ]), MagicNumber('font/woff2', [0x77, 0x4f, 0x46, 0x32]), + + /// High Efficiency Image File Format (ISO/IEC 23008-12). + /// -> 4 bytes indicating the ftyp box length. + /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. + /// -> 4 bytes have the ASCII characters 'h' 'e' 'i' 'c'. + /// https://www.iana.org/assignments/media-types/image/heic + MagicNumber('image/heic', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x68, + 0x65, + 0x69, + 0x63 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + + /// -> 4 bytes indicating the ftyp box length. + /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. + /// -> 4 bytes have the ASCII characters 'h' 'e' 'i' 'x'. + MagicNumber('image/heic', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x68, + 0x65, + 0x69, + 0x78 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), + + /// -> 4 bytes indicating the ftyp box length. + /// -> 4 bytes have the ASCII characters 'f' 't' 'y' 'p'. + /// -> 4 bytes have the ASCII characters 'm' 'i' 'f' '1'. + MagicNumber('image/heif', [ + 0x00, + 0x00, + 0x00, + 0x00, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x69, + 0x66, + 0x31 + ], mask: [ + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF + ]), ]; diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index f10d84724..f7388ff34 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -52,6 +52,8 @@ void main() { _expectMimeType('file.toml', 'application/toml'); _expectMimeType('file.md', 'text/markdown'); _expectMimeType('file.markdown', 'text/markdown'); + _expectMimeType('file.heif', 'image/heif'); + _expectMimeType('file.heic', 'image/heic'); }); test('unknown-mime-type', () { @@ -233,6 +235,51 @@ void main() { 0x56, 0x45 ]); + _expectMimeType('file', 'image/heic', headerBytes: [ + 0x00, + 0x00, + 0x00, + 0x18, + 0x66, + 0x74, + 0x79, + 0x70, + 0x68, + 0x65, + 0x69, + 0x63, + 0x00 + ]); + _expectMimeType('file', 'image/heic', headerBytes: [ + 0x00, + 0x00, + 0x00, + 0x18, + 0x66, + 0x74, + 0x79, + 0x70, + 0x68, + 0x65, + 0x69, + 0x78, + 0x00 + ]); + _expectMimeType('file', 'image/heif', headerBytes: [ + 0x00, + 0x00, + 0x00, + 0x18, + 0x66, + 0x74, + 0x79, + 0x70, + 0x6D, + 0x69, + 0x66, + 0x31, + 0x00 + ]); }); }); From a1ed7476aee887cd01c6f16925f64d4b4d43c1b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 08:03:27 +0000 Subject: [PATCH 103/118] Bump actions/stale from 8.0.0 to 9.0.0 (dart-lang/mime#111) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/stale](https://github.com/actions/stale) from 8.0.0 to 9.0.0.
Release notes

Sourced from actions/stale's releases.

v9.0.0

Breaking Changes

  1. Action is now stateful: If the action ends because of operations-per-run then the next run will start from the first unprocessed issue skipping the issues processed during the previous run(s). The state is reset when all the issues are processed. This should be considered for scheduling workflow runs.
  2. Version 9 of this action updated the runtime to Node.js 20. All scripts are now run with Node.js 20 instead of Node.js 16 and are affected by any breaking changes between Node.js 16 and 20.

What Else Changed

  1. Performance optimization that removes unnecessary API calls by @​dsame dart-lang/mime#1033 fixes dart-lang/mime#792
  2. Logs displaying current github API rate limit by @​dsame dart-lang/mime#1032 addresses dart-lang/mime#1029

For more information, please read the action documentation and its section about statefulness

New Contributors

Full Changelog: https://github.com/actions/stale/compare/v8...v9.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/stale&package-manager=github_actions&previous-version=8.0.0&new-version=9.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/no-response.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/no-response.yml b/pkgs/mime/.github/workflows/no-response.yml index 8e5ed57cd..ab1ac4984 100644 --- a/pkgs/mime/.github/workflows/no-response.yml +++ b/pkgs/mime/.github/workflows/no-response.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.repository_owner == 'dart-lang' }} steps: - - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e with: # Don't automatically mark inactive issues+PRs as stale. days-before-stale: -1 From 4a5d04bd24811e8375fc988985b95fa338c3abda Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 24 Jan 2024 14:12:32 -0800 Subject: [PATCH 104/118] Update to latest lints, require Dart 3.2 (dart-lang/mime#114) * and prepare to publish --- pkgs/mime/.github/workflows/test-package.yml | 2 +- pkgs/mime/CHANGELOG.md | 10 +++++----- pkgs/mime/analysis_options.yaml | 8 +------- pkgs/mime/pubspec.yaml | 6 +++--- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 9a52ddb41..e3f985f1b 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - sdk: [3.0.0, dev] + sdk: [3.2, dev] steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 070034938..2e2c1311a 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,11 +1,11 @@ -## 1.0.5-wip +## 1.0.5 -* Update video/mp4 mimeType lookup by header bytes. -* Add image/heic mimeType lookup by header bytes. -* Add image/heif mimeType lookup by header bytes. +* Update `video/mp4` mimeType lookup by header bytes. +* Add `image/heic` mimeType lookup by header bytes. +* Add `image/heif` mimeType lookup by header bytes. * Add m4b mimeType lookup by extension. * Add `text/markdown` mimeType lookup by extension. -* Require Dart 3.0.0. +* Require Dart 3.2.0. ## 1.0.4 diff --git a/pkgs/mime/analysis_options.yaml b/pkgs/mime/analysis_options.yaml index 41195572c..44b61cfdc 100644 --- a/pkgs/mime/analysis_options.yaml +++ b/pkgs/mime/analysis_options.yaml @@ -1,4 +1,4 @@ -# https://dart.dev/guides/language/analysis-options +# https://dart.dev/tools/analysis#the-analysis-options-file include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: @@ -13,28 +13,22 @@ linter: - avoid_classes_with_only_static_members - avoid_private_typedef_functions - avoid_redundant_argument_values - - avoid_returning_null_for_future - avoid_returning_this - avoid_unused_constructor_parameters - avoid_void_async - cancel_subscriptions - - comment_references - join_return_with_assignment - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - package_api_docs - - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - - prefer_relative_imports - - test_types_in_equals - unnecessary_await_in_return - unnecessary_breaks - unnecessary_raw_strings - use_if_null_to_convert_nulls_to_bools - use_raw_strings - use_string_buffers - - use_super_parameters diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 3dd77f9bb..c09f00ec3 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,13 +1,13 @@ name: mime -version: 1.0.5-wip +version: 1.0.5 description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. repository: https://github.com/dart-lang/mime environment: - sdk: ^3.0.0 + sdk: ^3.2.0 dev_dependencies: - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 test: ^1.16.0 From 9928e0e9bcf8b9df13390635b1f292304722c94f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 08:06:26 +0000 Subject: [PATCH 105/118] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/mime#115) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/mime#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/mime#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index e3f985f1b..0651f6149 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -21,7 +21,7 @@ jobs: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 - name: Install dependencies run: dart pub get From b4522c52d1ee80ebc64d2358342b019bfc7f3130 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 08:52:16 +0000 Subject: [PATCH 106/118] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/mime#117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 0651f6149..0a5aa83c4 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 - name: Install dependencies From 33195d799d8f4c88c5fc4fe8b8229b1b7fa900e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 08:14:58 +0000 Subject: [PATCH 107/118] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/mime#119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 0a5aa83c4..0aa6db1b5 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 - name: Install dependencies From 3bdb27e9a6cb3278df94ca84566f2c014ba64b65 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 15:17:52 +0000 Subject: [PATCH 108/118] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/mime#120) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 0aa6db1b5..fe665d7f8 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -21,7 +21,7 @@ jobs: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 - name: Install dependencies run: dart pub get From ede85945f7ae9174b9e9ee074bd6b3a109929061 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 08:13:20 +0000 Subject: [PATCH 109/118] Bump actions/checkout from 4.1.4 to 4.1.6 (dart-lang/mime#124) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.4 to 4.1.6.
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index fe665d7f8..4bbb22c4c 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 - name: Install dependencies From c77409b705840913e4eb1c80616680e986bc6740 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Mon, 10 Jun 2024 09:46:29 +0200 Subject: [PATCH 110/118] Add `topics` to `pubspec.yaml` (dart-lang/mime#126) --- pkgs/mime/CHANGELOG.md | 4 ++++ pkgs/mime/pubspec.yaml | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 2e2c1311a..347e55d30 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.6-wip + +* Add `topics` section to `pubspec.yaml`. + ## 1.0.5 * Update `video/mp4` mimeType lookup by header bytes. diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index c09f00ec3..72f9b0325 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,10 +1,14 @@ name: mime -version: 1.0.5 +version: 1.0.6-wip description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. repository: https://github.com/dart-lang/mime +topics: + - mime + - magic-numbers + environment: sdk: ^3.2.0 From 7386496d2ec9c6520f2f8d4e2534353492d01711 Mon Sep 17 00:00:00 2001 From: Jonas Finnemann Jensen Date: Mon, 24 Jun 2024 19:48:15 +0200 Subject: [PATCH 111/118] Add `topics` to `pubspec.yaml` (dart-lang/mime#121) --- pkgs/mime/pubspec.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 72f9b0325..c06ec92a5 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -4,6 +4,10 @@ description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. repository: https://github.com/dart-lang/mime +topics: + - mimetype + - magic-numbers + - multipart-form topics: - mime From 97391b11ea193532d510a83c459816c267227612 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 24 Jun 2024 11:19:16 -0700 Subject: [PATCH 112/118] bump lints (dart-lang/mime#127) --- pkgs/mime/lib/mime.dart | 2 +- pkgs/mime/pubspec.yaml | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart index 12df281b8..f2c446403 100644 --- a/pkgs/mime/lib/mime.dart +++ b/pkgs/mime/lib/mime.dart @@ -7,7 +7,7 @@ /// /// More details, including a list of types, are in the Wikipedia article /// [Internet media type](http://en.wikipedia.org/wiki/Internet_media_type). -library mime; +library; export 'src/mime_multipart_transformer.dart'; export 'src/mime_shared.dart'; diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index c06ec92a5..9e20caa9c 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -5,17 +5,14 @@ description: >- a file extension and file contents. repository: https://github.com/dart-lang/mime topics: - - mimetype - magic-numbers - - multipart-form - -topics: - mime - - magic-numbers + - mimetype + - multipart-form environment: sdk: ^3.2.0 dev_dependencies: - dart_flutter_team_lints: ^2.0.0 + dart_flutter_team_lints: ^3.0.0 test: ^1.16.0 From 39fc5078ec778bdedd8565cf7913c5ee69851f8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:44:53 +0000 Subject: [PATCH 113/118] Bump actions/checkout from 4.1.6 to 4.1.7 (dart-lang/mime#129) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7.
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.6&new-version=4.1.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/mime/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 4bbb22c4c..5b16393bc 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: steps: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 - name: Install dependencies From 4dd459a6a39c0f23c04a02be24bc7a748f6e007c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 1 Jul 2024 09:49:39 -0700 Subject: [PATCH 114/118] blast_repo fixes (dart-lang/mime#131) dependabot, github-actions, no-response --- pkgs/mime/.github/dependabot.yaml | 4 ++++ pkgs/mime/.github/workflows/test-package.yml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/.github/dependabot.yaml b/pkgs/mime/.github/dependabot.yaml index 439e796b4..bf6b38a4d 100644 --- a/pkgs/mime/.github/dependabot.yaml +++ b/pkgs/mime/.github/dependabot.yaml @@ -8,3 +8,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" diff --git a/pkgs/mime/.github/workflows/test-package.yml b/pkgs/mime/.github/workflows/test-package.yml index 5b16393bc..13b1dd517 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/pkgs/mime/.github/workflows/test-package.yml @@ -21,7 +21,7 @@ jobs: # These are the latest versions of the github actions; dependabot will # send PRs to keep these up-to-date. - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 - name: Install dependencies run: dart pub get From e40be87aa7a573cb7d2abfbff37891dce5814ad7 Mon Sep 17 00:00:00 2001 From: Moritz Date: Mon, 26 Aug 2024 16:04:38 +0200 Subject: [PATCH 115/118] Fixes for merging mime --- .../workflows/mime.yml | 13 ++++++- README.md | 1 + pkgs/mime/.github/dependabot.yaml | 14 ------- pkgs/mime/.github/workflows/no-response.yml | 37 ------------------- pkgs/mime/.github/workflows/publish.yaml | 17 --------- pkgs/mime/README.md | 2 +- pkgs/mime/pubspec.yaml | 2 +- 7 files changed, 14 insertions(+), 72 deletions(-) rename pkgs/mime/.github/workflows/test-package.yml => .github/workflows/mime.yml (76%) delete mode 100644 pkgs/mime/.github/dependabot.yaml delete mode 100644 pkgs/mime/.github/workflows/no-response.yml delete mode 100644 pkgs/mime/.github/workflows/publish.yaml diff --git a/pkgs/mime/.github/workflows/test-package.yml b/.github/workflows/mime.yml similarity index 76% rename from pkgs/mime/.github/workflows/test-package.yml rename to .github/workflows/mime.yml index 13b1dd517..04bce0660 100644 --- a/pkgs/mime/.github/workflows/test-package.yml +++ b/.github/workflows/mime.yml @@ -5,13 +5,22 @@ on: # “At 00:00 (UTC) on Sunday.” - cron: '0 0 * * 0' push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/mime.yml' + - 'pkgs/mime/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/mime.yml' + - 'pkgs/mime/**' jobs: build: runs-on: ubuntu-latest + defaults: + run: + working-directory: pkgs/mime/ strategy: matrix: diff --git a/README.md b/README.md index 5847cf74b..2c1dec749 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ don't naturally belong to other topic monorepos (like | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | | [source_map_stack_trace](pkgs/source_map_stack_trace/) | A package for applying source maps to stack traces. | [![pub package](https://img.shields.io/pub/v/source_map_stack_trace.svg)](https://pub.dev/packages/source_map_stack_trace) | | [oauth2](pkgs/oauth2/) | A client library for authenticatingand making requests via OAuth2. | [![pub package](https://img.shields.io/pub/v/oauth2.svg)](https://pub.dev/packages/oauth2) | +| [mime](pkgs/mime/) | Utilities for handling media (MIME) types. | [![pub package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) | ## Publishing automation diff --git a/pkgs/mime/.github/dependabot.yaml b/pkgs/mime/.github/dependabot.yaml deleted file mode 100644 index bf6b38a4d..000000000 --- a/pkgs/mime/.github/dependabot.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# Dependabot configuration file. -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/mime/.github/workflows/no-response.yml b/pkgs/mime/.github/workflows/no-response.yml deleted file mode 100644 index ab1ac4984..000000000 --- a/pkgs/mime/.github/workflows/no-response.yml +++ /dev/null @@ -1,37 +0,0 @@ -# A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/actions/stale. - -name: No Response - -# Run as a daily cron. -on: - schedule: - # Every day at 8am - - cron: '0 8 * * *' - -# All permissions not specified are set to 'none'. -permissions: - issues: write - pull-requests: write - -jobs: - no-response: - runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'dart-lang' }} - steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e - with: - # Don't automatically mark inactive issues+PRs as stale. - days-before-stale: -1 - # Close needs-info issues and PRs after 14 days of inactivity. - days-before-close: 14 - stale-issue-label: "needs-info" - close-issue-message: > - Without additional information we're not able to resolve this issue. - Feel free to add more info or respond to any questions above and we - can reopen the case. Thanks for your contribution! - stale-pr-label: "needs-info" - close-pr-message: > - Without additional information we're not able to resolve this PR. - Feel free to add more info or respond to any questions above. - Thanks for your contribution! diff --git a/pkgs/mime/.github/workflows/publish.yaml b/pkgs/mime/.github/workflows/publish.yaml deleted file mode 100644 index 27157a046..000000000 --- a/pkgs/mime/.github/workflows/publish.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# A CI configuration to auto-publish pub packages. - -name: Publish - -on: - pull_request: - branches: [ master ] - push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] - -jobs: - publish: - if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main - permissions: - id-token: write # Required for authentication using OIDC - pull-requests: write # Required for writing the pull request note diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index 4cd060ce7..8a814150c 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://github.com/dart-lang/mime/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/mime/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/mime.yml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/mime.yml) [![Pub Package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) [![package publisher](https://img.shields.io/pub/publisher/mime.svg)](https://pub.dev/packages/mime/publisher) diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 9e20caa9c..45db6a55b 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -3,7 +3,7 @@ version: 1.0.6-wip description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. -repository: https://github.com/dart-lang/mime +repository: https://github.com/dart-lang/tools/tree/main/pkgs/mime topics: - magic-numbers - mime From 86c7592179ab17957b722d582418c7afdfa3e8dd Mon Sep 17 00:00:00 2001 From: Moritz Date: Mon, 26 Aug 2024 16:05:18 +0200 Subject: [PATCH 116/118] Ready for publish --- pkgs/mime/CHANGELOG.md | 3 ++- pkgs/mime/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 347e55d30..50f243306 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,6 +1,7 @@ -## 1.0.6-wip +## 1.0.6 * Add `topics` section to `pubspec.yaml`. +* Move to `dart-lang/tools` monorepo. ## 1.0.5 diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 45db6a55b..8d3c49823 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 1.0.6-wip +version: 1.0.6 description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. From 350cb179e953920a55fa4f02be65990b4b2f7b04 Mon Sep 17 00:00:00 2001 From: Moritz Date: Mon, 26 Aug 2024 16:05:45 +0200 Subject: [PATCH 117/118] Add license header --- pkgs/mime/example/example.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/mime/example/example.dart b/pkgs/mime/example/example.dart index af14cb08c..b54f8e72c 100644 --- a/pkgs/mime/example/example.dart +++ b/pkgs/mime/example/example.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + import 'package:mime/mime.dart'; void main() { From 49acd7880e0f55b4f9f53ce6472d8012b0878a15 Mon Sep 17 00:00:00 2001 From: Moritz Date: Mon, 26 Aug 2024 16:07:41 +0200 Subject: [PATCH 118/118] Fix analysis issue --- pkgs/mime/lib/src/bound_multipart_stream.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/lib/src/bound_multipart_stream.dart b/pkgs/mime/lib/src/bound_multipart_stream.dart index cc01fd5b0..0830a610e 100644 --- a/pkgs/mime/lib/src/bound_multipart_stream.dart +++ b/pkgs/mime/lib/src/bound_multipart_stream.dart @@ -8,7 +8,7 @@ import 'dart:convert'; import 'char_code.dart' as char_code; import 'mime_shared.dart'; -/// Bytes for '()<>@,;:\\"/[]?={} \t'. +/// Bytes for `()<>@,;:\\"/[]?={} \t`. const _separators = { 40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47, 91, 93, 63, 61, 123, 125, 32, 9 // };