    {- arch-tag: MIME Types main file
    Copyright (c) 2004-2011 John Goerzen <jgoerzen@complete.org>

    All rights reserved.

    For license and copyright information, see the file LICENSE
    -}

    {- |
       Module     : Data.MIME.Types
       Copyright  : Copyright (C) 2004-2011 John Goerzen
       SPDX-License-Identifier: BSD-3-Clause

       Stability  : stable
       Portability: portable

    Utilities for guessing MIME types of files.

    Written by John Goerzen, jgoerzen\@complete.org
    -}

    module Data.MIME.Types (-- * Creating Lookup Objects
                               defaultmtd,
                               readMIMETypes,
                               hReadMIMETypes,
                               readSystemMIMETypes,
                               -- * Basic Access
                               MIMEResults,
                               MIMETypeData(..),
                               guessType,
                               guessExtension,
                               guessAllExtensions
                              )
    where

    import qualified Data.Map as Map
    import qualified Control.Exception (try, IOException)
    import Control.Monad ( foldM )
    import System.IO
        ( Handle, hClose, openFile, IOMode(ReadMode) )
    import System.IO.Error ()
    import System.IO.Utils ( hGetLines )
    import System.Path ( splitExt )
    import Data.Map.Utils ( flippedLookupM )
    import Data.Char ( toLower )

    ----------------------------------------------------------------------
    -- Basic type declarations
    ----------------------------------------------------------------------

    data MIMETypeData = MIMETypeData
        {
         -- | A mapping used to expand common suffixes into equivolent,
         -- better-parsed versions.  For instance, ".tgz" would expand
         -- into ".tar.gz".
         MIMETypeData -> Map String String
    suffixMap :: Map.Map String String,
         -- | A mapping used to determine the encoding of a file.
         -- This is used, for instance, to map ".gz" to "gzip".
         MIMETypeData -> Map String String
    encodingsMap :: Map.Map String String,
         -- | A mapping used to map extensions to MIME types.
         MIMETypeData -> Map String String
    typesMap :: Map.Map String String,
         -- | A mapping used to augment the 'typesMap' when non-strict
         -- lookups are used.
         MIMETypeData -> Map String String
    commonTypesMap :: Map.Map String String
        }

    {- | Return value from guessing a file's type.

    The first element of the tuple gives the MIME type.  It is Nothing if no
    suitable type could be found.

    The second element gives the encoding.  It is Nothing if there was no particular
    encoding for the file, or if no encoding could be found.
    -}
    type MIMEResults = (Maybe String,       -- The MIME type
                        Maybe String        -- Encoding
                       )

    {- | Read the given mime.types file and add it to an existing object.
    Returns new object. -}
    readMIMETypes :: MIMETypeData            -- ^ Data to work with
                  -> Bool                    -- ^ Whether to work on strict data
                  -> FilePath               -- ^ File to read
                  -> IO MIMETypeData           -- ^ New object
    readMIMETypes :: MIMETypeData -> Bool -> String -> IO MIMETypeData
    readMIMETypes MIMETypeData
    mtd Bool
    strict String
    fn = do
                             Handle
    h <- String -> IOMode -> IO Handle
    openFile String
    fn IOMode
    ReadMode
                             MIMETypeData -> Bool -> Handle -> IO MIMETypeData
    hReadMIMETypes MIMETypeData
    mtd Bool
    strict Handle
    h

    {- | Load a mime.types file from an already-open handle. -}
    hReadMIMETypes :: MIMETypeData          -- ^ Data to work with
                      -> Bool               -- ^ Whether to work on strict data
                      -> Handle             -- ^ Handle to read from
                      -> IO MIMETypeData       -- ^ New object
    hReadMIMETypes :: MIMETypeData -> Bool -> Handle -> IO MIMETypeData
    hReadMIMETypes MIMETypeData
    mtd Bool
    strict Handle
    h = (MIMETypeData -> String -> MIMETypeData)
    -> MIMETypeData -> [String] -> MIMETypeData
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl MIMETypeData -> String -> MIMETypeData
    parseline MIMETypeData
    mtd ([String] -> MIMETypeData) -> IO [String] -> IO MIMETypeData
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Handle -> IO [String]
    forall a. HVIO a => a -> IO [String]
    hGetLines Handle
    h
        where
            parseline :: MIMETypeData -> String -> MIMETypeData
            parseline :: MIMETypeData -> String -> MIMETypeData
    parseline MIMETypeData
    obj String
    line =
                let l1 :: [String]
    l1 = String -> [String]
    words String
    line
                    procwords :: [String] -> [String]
    procwords [] = []
                    procwords ((Char
    '#':String
    _) :[String]
    _) = []
                    procwords (String
    x:[String]
    xs) = String
    x String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : [String] -> [String]
    procwords [String]
    xs
                    l2 :: [String]
    l2 = [String] -> [String]
    procwords [String]
    l1
                    in
                    if ([String] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [String]
    l2) Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    2 then
                       let thetype :: String
    thetype = [String] -> String
    forall a. HasCallStack => [a] -> a
    head [String]
    l2
                           suffixlist :: [String]
    suffixlist = [String] -> [String]
    forall a. HasCallStack => [a] -> [a]
    tail [String]
    l2
                           in
                           (MIMETypeData -> String -> MIMETypeData)
    -> MIMETypeData -> [String] -> MIMETypeData
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl (\MIMETypeData
    o String
    suff -> MIMETypeData -> Bool -> String -> String -> MIMETypeData
    addType MIMETypeData
    o Bool
    strict String
    thetype (Char
    '.' Char -> String -> String
    forall a. a -> [a] -> [a]
    : String
    suff)) MIMETypeData
    obj [String]
    suffixlist
                    else MIMETypeData
    obj

    {- | Guess the type of a file given a filename or URL.  The file
       is not opened; only the name is considered. -}
    guessType :: MIMETypeData               -- ^ Source data for guessing
                 -> Bool                    -- ^ Whether to limit to strict data
                 -> String                  -- ^ File or URL name to consider
                 -> MIMEResults             -- ^ Result of guessing (see 'MIMEResults' for details on interpreting it)
    guessType :: MIMETypeData -> Bool -> String -> MIMEResults
    guessType MIMETypeData
    mtd Bool
    strict String
    fn =
        let mapext :: (String, String) -> (String, String)
    mapext (String
    base, String
    ex) =
                case String -> Map String String -> Maybe String
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup String
    ex (MIMETypeData -> Map String String
    suffixMap MIMETypeData
    mtd) of
                    Maybe String
    Nothing -> (String
    base, String
    ex)
                    Just String
    x -> (String, String) -> (String, String)
    mapext (String -> (String, String)
    splitExt (String
    base String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    x))
            checkencodings :: (String, String) -> (String, String, Maybe String)
    checkencodings (String
    base, String
    ex) =
                case String -> Map String String -> Maybe String
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup String
    ex (MIMETypeData -> Map String String
    encodingsMap MIMETypeData
    mtd) of
                     Maybe String
    Nothing -> (String
    base, String
    ex, Maybe String
    forall a. Maybe a
    Nothing)
                     Just String
    x -> ((String, String) -> String
    forall a b. (a, b) -> a
    fst (String -> (String, String)
    splitExt String
    base),
                                (String, String) -> String
    forall a b. (a, b) -> b
    snd (String -> (String, String)
    splitExt String
    base),
                                String -> Maybe String
    forall a. a -> Maybe a
    Just String
    x)
            (String
    _, String
    ext, Maybe String
    enc) = (String, String) -> (String, String, Maybe String)
    checkencodings ((String, String) -> (String, String, Maybe String))
    -> ((String, String) -> (String, String))
    -> (String, String)
    -> (String, String, Maybe String)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (String, String) -> (String, String)
    mapext ((String, String) -> (String, String, Maybe String))
    -> (String, String) -> (String, String, Maybe String)
    forall a b. (a -> b) -> a -> b
    $ String -> (String, String)
    splitExt String
    fn
            typemap :: Map String String
    typemap = MIMETypeData -> Bool -> Map String String
    getStrict MIMETypeData
    mtd Bool
    strict
            in
            case String -> Map String String -> Maybe String
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup String
    ext Map String String
    typemap of
                 Maybe String
    Nothing -> (String -> Map String String -> Maybe String
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup ((Char -> Char) -> String -> String
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toLower String
    ext) Map String String
    typemap, Maybe String
    enc)
                 Just String
    x -> (String -> Maybe String
    forall a. a -> Maybe a
    Just String
    x, Maybe String
    enc)

    {- | Guess the extension of a file based on its MIME type.
       The return value includes the leading dot.

       Returns Nothing if no extension could be found.

       In the event that multiple possible extensions are available,
       one of them will be picked and returned.  The logic to select one
       of these should be considered undefined. -}
    guessExtension :: MIMETypeData          -- ^ Source data for guessing
                      -> Bool               -- ^ Whether to limit to strict data
                      -> String             -- ^ MIME type to consider
                      -> Maybe String       -- ^ Result of guessing, or Nothing if no match possible
    guessExtension :: MIMETypeData -> Bool -> String -> Maybe String
    guessExtension MIMETypeData
    mtd Bool
    strict String
    fn =
        case MIMETypeData -> Bool -> String -> [String]
    guessAllExtensions MIMETypeData
    mtd Bool
    strict String
    fn of
                                              [] -> Maybe String
    forall a. Maybe a
    Nothing
                                              (String
    x:[String]
    _) -> String -> Maybe String
    forall a. a -> Maybe a
    Just String
    x

    {- | Similar to 'guessExtension', but returns a list of all possible matching
    extensions, or the empty list if there are no matches. -}
    guessAllExtensions :: MIMETypeData      -- ^ Source data for guessing
                          -> Bool           -- ^ Whether to limit to strict data
                          -> String         -- ^ MIME type to consider
                          -> [String]       -- ^ Result of guessing
    guessAllExtensions :: MIMETypeData -> Bool -> String -> [String]
    guessAllExtensions MIMETypeData
    mtd Bool
    strict String
    fn =
        let mimetype :: String
    mimetype = (Char -> Char) -> String -> String
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toLower String
    fn
            themap :: Map String String
    themap = MIMETypeData -> Bool -> Map String String
    getStrict MIMETypeData
    mtd Bool
    strict
            in
            String -> Map String String -> [String]
    forall val key. (Ord val, Ord key) => val -> Map key val -> [key]
    flippedLookupM String
    mimetype Map String String
    themap

    {- | Adds a new type to the data structures, replacing whatever data
       may exist about it already.  That is, it overrides existing information
       about the given extension, but the same type may occur more than once. -}
    addType :: MIMETypeData                 -- ^ Source data
               -> Bool                      -- ^ Whether to add to strict data set
               -> String                    -- ^ MIME type to add
               -> String                    -- ^ Extension to add
               -> MIMETypeData              -- ^ Result of addition
    addType :: MIMETypeData -> Bool -> String -> String -> MIMETypeData
    addType MIMETypeData
    mtd Bool
    strict String
    thetype String
    theext =
        MIMETypeData
    -> Bool -> (Map String String -> Map String String) -> MIMETypeData
    setStrict MIMETypeData
    mtd Bool
    strict (\Map String String
    m -> String -> String -> Map String String -> Map String String
    forall k a. Ord k => k -> a -> Map k a -> Map k a
    Map.insert String
    theext String
    thetype Map String String
    m)

    {- | Default MIME type data to use -}
    defaultmtd :: MIMETypeData
    defaultmtd :: MIMETypeData
    defaultmtd =
        MIMETypeData {suffixMap :: Map String String
    suffixMap = Map String String
    default_suffix_map,
                      encodingsMap :: Map String String
    encodingsMap = Map String String
    default_encodings_map,
                      typesMap :: Map String String
    typesMap = Map String String
    default_types_map,
                      commonTypesMap :: Map String String
    commonTypesMap = Map String String
    default_common_types}

    {- | Read the system's default mime.types files, and add the data contained
    therein to the passed object, then return the new one. -}
    readSystemMIMETypes :: MIMETypeData -> IO MIMETypeData
    readSystemMIMETypes :: MIMETypeData -> IO MIMETypeData
    readSystemMIMETypes MIMETypeData
    mtd =
        let tryread :: MIMETypeData -> String -> IO MIMETypeData
            tryread :: MIMETypeData -> String -> IO MIMETypeData
    tryread MIMETypeData
    inputobj String
    filename =
                do
                Either IOException Handle
    fn <- IO Handle -> IO (Either IOException Handle)
    forall e a. Exception e => IO a -> IO (Either e a)
    Control.Exception.try (String -> IOMode -> IO Handle
    openFile String
    filename IOMode
    ReadMode)
                case Either IOException Handle
    fn of
                        Left (IOException
    _ :: Control.Exception.IOException) -> MIMETypeData -> IO MIMETypeData
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return MIMETypeData
    inputobj
                        Right Handle
    h -> do
                                   MIMETypeData
    x <- MIMETypeData -> Bool -> Handle -> IO MIMETypeData
    hReadMIMETypes MIMETypeData
    inputobj Bool
    True Handle
    h
                                   Handle -> IO ()
    hClose Handle
    h
                                   MIMETypeData -> IO MIMETypeData
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return MIMETypeData
    x
            in
            do
              (MIMETypeData -> String -> IO MIMETypeData)
    -> MIMETypeData -> [String] -> IO MIMETypeData
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM MIMETypeData -> String -> IO MIMETypeData
    tryread MIMETypeData
    mtd [String]
    defaultfilelocations

    ----------------------------------------------------------------------
    -- Internal utilities
    ----------------------------------------------------------------------
    getStrict :: MIMETypeData -> Bool -> Map.Map String String
    getStrict :: MIMETypeData -> Bool -> Map String String
    getStrict MIMETypeData
    mtd Bool
    True = MIMETypeData -> Map String String
    typesMap MIMETypeData
    mtd
    getStrict MIMETypeData
    mtd Bool
    False = Map String String -> Map String String -> Map String String
    forall k a. Ord k => Map k a -> Map k a -> Map k a
    Map.union (MIMETypeData -> Map String String
    typesMap MIMETypeData
    mtd) (MIMETypeData -> Map String String
    commonTypesMap MIMETypeData
    mtd)

    setStrict :: MIMETypeData -> Bool -> (Map.Map String String -> Map.Map String String) -> MIMETypeData
    setStrict :: MIMETypeData
    -> Bool -> (Map String String -> Map String String) -> MIMETypeData
    setStrict MIMETypeData
    mtd Bool
    True Map String String -> Map String String
    func = MIMETypeData
    mtd{typesMap = func (typesMap mtd)}
    setStrict MIMETypeData
    mtd Bool
    False Map String String -> Map String String
    func = MIMETypeData
    mtd{commonTypesMap = func (commonTypesMap mtd)}

    ----------------------------------------------------------------------
    -- Default data structures
    ----------------------------------------------------------------------
    defaultfilelocations :: [String]
    defaultfilelocations :: [String]
    defaultfilelocations =
        [
         String
    "/etc/mime.types",
         String
    "/usr/local/etc/httpd/conf/mime.types",
         String
    "/usr/local/lib/netscape/mime.types",
         String
    "/usr/local/etc/httpd/conf/mime.types",     -- Apache 1.2
         String
    "/usr/local/etc/mime.types"                -- Apache 1.3
        ]

    default_encodings_map, default_suffix_map, default_types_map, default_common_types :: Map.Map String String
    default_encodings_map :: Map String String
    default_encodings_map = [(String, String)] -> Map String String
    forall k a. Ord k => [(k, a)] -> Map k a
    Map.fromList [
                                          (String
    ".Z", String
    "compress"),
                                          (String
    ".gz", String
    "gzip"),
                                          (String
    ".bz2", String
    "bzip2")
                                         ]

    default_suffix_map :: Map String String
    default_suffix_map = [(String, String)] -> Map String String
    forall k a. Ord k => [(k, a)] -> Map k a
    Map.fromList [
                                       (String
    ".tgz", String
    ".tar.gz"),
                                       (String
    ".tz", String
    ".tar.gz"),
                                       (String
    ".taz", String
    ".tar.gz")
                                      ]

    default_types_map :: Map String String
    default_types_map = [(String, String)] -> Map String String
    forall k a. Ord k => [(k, a)] -> Map k a
    Map.fromList [
                                      (String
    ".a", String
    "application/octet-stream"),
                                      (String
    ".ai", String
    "application/postscript"),
                                      (String
    ".aif", String
    "audio/x-aiff"),
                                      (String
    ".aifc", String
    "audio/x-aiff"),
                                      (String
    ".aiff", String
    "audio/x-aiff"),
                                      (String
    ".au", String
    "audio/basic"),
                                      (String
    ".avi", String
    "video/x-msvideo"),
                                      (String
    ".bat", String
    "text/plain"),
                                      (String
    ".bcpio", String
    "application/x-bcpio"),
                                      (String
    ".bin", String
    "application/octet-stream"),
                                      (String
    ".bmp", String
    "image/x-ms-bmp"),
                                      (String
    ".c", String
    "text/plain"),
                                      (String
    ".cdf", String
    "application/x-netcdf"),
                                      (String
    ".cpio", String
    "application/x-cpio"),
                                      (String
    ".csh", String
    "application/x-csh"),
                                      (String
    ".css", String
    "text/css"),
                                      (String
    ".dll", String
    "application/octet-stream"),
                                      (String
    ".doc", String
    "application/msword"),
                                      (String
    ".dot", String
    "application/msword"),
                                      (String
    ".dvi", String
    "application/x-dvi"),
                                      (String
    ".eml", String
    "message/rfc822"),
                                      (String
    ".eps", String
    "application/postscript"),
                                      (String
    ".etx", String
    "text/x-setext"),
                                      (String
    ".exe", String
    "application/octet-stream"),
                                      (String
    ".gif", String
    "image/gif"),
                                      (String
    ".gtar", String
    "application/x-gtar"),
                                      (String
    ".h", String
    "text/plain"),
                                      (String
    ".hdf", String
    "application/x-hdf"),
                                      (String
    ".htm", String
    "text/html"),
                                      (String
    ".html", String
    "text/html"),
                                      (String
    ".ief", String
    "image/ief"),
                                      (String
    ".jpe", String
    "image/jpeg"),
                                      (String
    ".jpeg", String
    "image/jpeg"),
                                      (String
    ".jpg", String
    "image/jpeg"),
                                      (String
    ".js", String
    "application/x-javascript"),
                                      (String
    ".ksh", String
    "text/plain"),
                                      (String
    ".latex", String
    "application/x-latex"),
                                      (String
    ".m1v", String
    "video/mpeg"),
                                      (String
    ".man", String
    "application/x-troff-man"),
                                      (String
    ".me", String
    "application/x-troff-me"),
                                      (String
    ".mht", String
    "message/rfc822"),
                                      (String
    ".mhtml", String
    "message/rfc822"),
                                      (String
    ".mif", String
    "application/x-mif"),
                                      (String
    ".mov", String
    "video/quicktime"),
                                      (String
    ".movie", String
    "video/x-sgi-movie"),
                                      (String
    ".mp2", String
    "audio/mpeg"),
                                      (String
    ".mp3", String
    "audio/mpeg"),
                                      (String
    ".mpa", String
    "video/mpeg"),
                                      (String
    ".mpe", String
    "video/mpeg"),
                                      (String
    ".mpeg", String
    "video/mpeg"),
                                      (String
    ".mpg", String
    "video/mpeg"),
                                      (String
    ".ms", String
    "application/x-troff-ms"),
                                      (String
    ".nc", String
    "application/x-netcdf"),
                                      (String
    ".nws", String
    "message/rfc822"),
                                      (String
    ".o", String
    "application/octet-stream"),
                                      (String
    ".obj", String
    "application/octet-stream"),
                                      (String
    ".oda", String
    "application/oda"),
                                      (String
    ".p12", String
    "application/x-pkcs12"),
                                      (String
    ".p7c", String
    "application/pkcs7-mime"),
                                      (String
    ".pbm", String
    "image/x-portable-bitmap"),
                                      (String
    ".pdf", String
    "application/pdf"),
                                      (String
    ".pfx", String
    "application/x-pkcs12"),
                                      (String
    ".pgm", String
    "image/x-portable-graymap"),
                                      (String
    ".pl", String
    "text/plain"),
                                      (String
    ".png", String
    "image/png"),
                                      (String
    ".pnm", String
    "image/x-portable-anymap"),
                                      (String
    ".pot", String
    "application/vnd.ms-powerpoint"),
                                      (String
    ".ppa", String
    "application/vnd.ms-powerpoint"),
                                      (String
    ".ppm", String
    "image/x-portable-pixmap"),
                                      (String
    ".pps", String
    "application/vnd.ms-powerpoint"),
                                      (String
    ".ppt", String
    "application/vnd.ms-powerpoint"),
                                      (String
    ".ps", String
    "application/postscript"),
                                      (String
    ".pwz", String
    "application/vnd.ms-powerpoint"),
                                      (String
    ".py", String
    "text/x-python"),
                                      (String
    ".pyc", String
    "application/x-python-code"),
                                      (String
    ".pyo", String
    "application/x-python-code"),
                                      (String
    ".qt", String
    "video/quicktime"),
                                      (String
    ".ra", String
    "audio/x-pn-realaudio"),
                                      (String
    ".ram", String
    "application/x-pn-realaudio"),
                                      (String
    ".ras", String
    "image/x-cmu-raster"),
                                      (String
    ".rdf", String
    "application/xml"),
                                      (String
    ".rgb", String
    "image/x-rgb"),
                                      (String
    ".roff", String
    "application/x-troff"),
                                      (String
    ".rtx", String
    "text/richtext"),
                                      (String
    ".sgm", String
    "text/x-sgml"),
                                      (String
    ".sgml", String
    "text/x-sgml"),
                                      (String
    ".sh", String
    "application/x-sh"),
                                      (String
    ".shar", String
    "application/x-shar"),
                                      (String
    ".snd", String
    "audio/basic"),
                                      (String
    ".so", String
    "application/octet-stream"),
                                      (String
    ".src", String
    "application/x-wais-source"),
                                      (String
    ".sv4cpio", String
    "application/x-sv4cpio"),
                                      (String
    ".sv4crc", String
    "application/x-sv4crc"),
                                      (String
    ".swf", String
    "application/x-shockwave-flash"),
                                      (String
    ".t", String
    "application/x-troff"),
                                      (String
    ".tar", String
    "application/x-tar"),
                                      (String
    ".tcl", String
    "application/x-tcl"),
                                      (String
    ".tex", String
    "application/x-tex"),
                                      (String
    ".texi", String
    "application/x-texinfo"),
                                      (String
    ".texinfo", String
    "application/x-texinfo"),
                                      (String
    ".tif", String
    "image/tiff"),
                                      (String
    ".tiff", String
    "image/tiff"),
                                      (String
    ".tr", String
    "application/x-troff"),
                                      (String
    ".tsv", String
    "text/tab-separated-values"),
                                      (String
    ".txt", String
    "text/plain"),
                                      (String
    ".ustar", String
    "application/x-ustar"),
                                      (String
    ".vcf", String
    "text/x-vcard"),
                                      (String
    ".wav", String
    "audio/x-wav"),
                                      (String
    ".wiz", String
    "application/msword"),
                                      (String
    ".xbm", String
    "image/x-xbitmap"),
                                      (String
    ".xlb", String
    "application/vnd.ms-excel"),
                                      (String
    ".xls", String
    "application/vnd.ms-excel"),
                                      (String
    ".xml", String
    "text/xml"),
                                      (String
    ".xpm", String
    "image/x-xpixmap"),
                                      (String
    ".xsl", String
    "application/xml"),
                                      (String
    ".xwd", String
    "image/x-xwindowdump"),
                                      (String
    ".zip", String
    "application/zip")
                                     ]

    default_common_types :: Map String String
    default_common_types = [(String, String)] -> Map String String
    forall k a. Ord k => [(k, a)] -> Map k a
    Map.fromList [
                                         (String
    ".jpg", String
    "image/jpg"),
                                         (String
    ".mid", String
    "audio/midi"),
                                         (String
    ".midi", String
    "audio/midi"),
                                         (String
    ".pct", String
    "image/pict"),
                                         (String
    ".pic", String
    "image/pict"),
                                         (String
    ".pict", String
    "image/pict"),
                                         (String
    ".rtf", String
    "application/rtf"),
                                         (String
    ".xul", String
    "text/xul")
                                        ]