module Data.MIME.Types (
                           defaultmtd,
                           readMIMETypes,
                           hReadMIMETypes,
                           readSystemMIMETypes,
                           
                           MIMEResults,
                           MIMETypeData(..),
                           guessType,
                           guessExtension,
                           guessAllExtensions
                          )
where
import qualified Data.Map as Map
import qualified Control.Exception (try, IOException)
import Control.Monad
import System.IO
import System.IO.Error
import System.IO.Utils
import System.Path
import Data.Map.Utils
import Data.Char
data MIMETypeData = MIMETypeData
    {
     
     
     
     suffixMap :: Map.Map String String,
     
     
     encodingsMap :: Map.Map String String,
     
     typesMap :: Map.Map String String,
     
     
     commonTypesMap :: Map.Map String String
    }
type MIMEResults = (Maybe String,       
                    Maybe String        
                   )
readMIMETypes :: MIMETypeData            
              -> Bool                    
              -> FilePath               
              -> IO MIMETypeData           
readMIMETypes mtd strict fn = do
                         h <- openFile fn ReadMode
                         hReadMIMETypes mtd strict h
hReadMIMETypes :: MIMETypeData          
                  -> Bool               
                  -> Handle             
                  -> IO MIMETypeData       
hReadMIMETypes mtd strict h =
    let parseline :: MIMETypeData -> String -> MIMETypeData
        parseline obj line =
            let l1 = words line
                procwords [] = []
                procwords (('#':_) :_) = []
                procwords (x:xs) = x : procwords xs
                l2 = procwords l1
                in
                if (length l2) >= 2 then
                   let thetype = head l2
                       suffixlist = tail l2
                       in
                       foldl (\o suff -> addType o strict thetype ('.' : suff)) obj suffixlist
                else obj
        in
          do
            lines <- hGetLines h
            return (foldl parseline mtd lines)
guessType :: MIMETypeData               
             -> Bool                    
             -> String                  
             -> MIMEResults             
guessType mtd strict fn =
    let mapext (base, ex) =
            case Map.lookup ex (suffixMap mtd) of
                Nothing -> (base, ex)
                Just x -> mapext (splitExt (base ++ x))
        checkencodings (base, ex) =
            case Map.lookup ex (encodingsMap mtd) of
                 Nothing -> (base, ex, Nothing)
                 Just x -> (fst (splitExt base),
                            snd (splitExt base),
                            Just x)
        (_, ext, enc) = checkencodings . mapext $ splitExt fn
        typemap = getStrict mtd strict
        in
        case Map.lookup ext typemap of
             Nothing -> (Map.lookup (map toLower ext) typemap, enc)
             Just x -> (Just x, enc)
guessExtension :: MIMETypeData          
                  -> Bool               
                  -> String             
                  -> Maybe String       
guessExtension mtd strict fn =
    case guessAllExtensions mtd strict fn of
                                          [] -> Nothing
                                          (x:_) -> Just x
guessAllExtensions :: MIMETypeData      
                      -> Bool           
                      -> String         
                      -> [String]       
guessAllExtensions mtd strict fn =
    let mimetype = map toLower fn
        themap = getStrict mtd strict
        in
        flippedLookupM mimetype themap
addType :: MIMETypeData                 
           -> Bool                      
           -> String                    
           -> String                    
           -> MIMETypeData              
addType mtd strict thetype theext =
    setStrict mtd strict (\m -> Map.insert theext thetype m)
defaultmtd :: MIMETypeData
defaultmtd =
    MIMETypeData {suffixMap = default_suffix_map,
                  encodingsMap = default_encodings_map,
                  typesMap = default_types_map,
                  commonTypesMap = default_common_types}
readSystemMIMETypes :: MIMETypeData -> IO MIMETypeData
readSystemMIMETypes mtd =
    let tryread :: MIMETypeData -> String -> IO MIMETypeData
        tryread inputobj filename =
            do
            fn <- Control.Exception.try (openFile filename ReadMode)
            case fn of
                    Left (_ :: Control.Exception.IOException) -> return inputobj
                    Right h -> do
                               x <- hReadMIMETypes inputobj True h
                               hClose h
                               return x
        in
        do
          foldM tryread mtd defaultfilelocations
getStrict :: MIMETypeData -> Bool -> Map.Map String String
getStrict mtd True = typesMap mtd
getStrict mtd False = Map.union (typesMap mtd) (commonTypesMap mtd)
setStrict :: MIMETypeData -> Bool -> (Map.Map String String -> Map.Map String String) -> MIMETypeData
setStrict mtd True func = mtd{typesMap = func (typesMap mtd)}
setStrict mtd False func = mtd{commonTypesMap = func (commonTypesMap mtd)}
defaultfilelocations :: [String]
defaultfilelocations =
    [
     "/etc/mime.types",
     "/usr/local/etc/httpd/conf/mime.types",
     "/usr/local/lib/netscape/mime.types",
     "/usr/local/etc/httpd/conf/mime.types",     
     "/usr/local/etc/mime.types"                
    ]
default_encodings_map, default_suffix_map, default_types_map, default_common_types :: Map.Map String String
default_encodings_map = Map.fromList [
                                      (".Z", "compress"),
                                      (".gz", "gzip"),
                                      (".bz2", "bzip2")
                                     ]
default_suffix_map = Map.fromList [
                                   (".tgz", ".tar.gz"),
                                   (".tz", ".tar.gz"),
                                   (".taz", ".tar.gz")
                                  ]
default_types_map = Map.fromList [
                                  (".a", "application/octet-stream"),
                                  (".ai", "application/postscript"),
                                  (".aif", "audio/x-aiff"),
                                  (".aifc", "audio/x-aiff"),
                                  (".aiff", "audio/x-aiff"),
                                  (".au", "audio/basic"),
                                  (".avi", "video/x-msvideo"),
                                  (".bat", "text/plain"),
                                  (".bcpio", "application/x-bcpio"),
                                  (".bin", "application/octet-stream"),
                                  (".bmp", "image/x-ms-bmp"),
                                  (".c", "text/plain"),
                                  (".cdf", "application/x-netcdf"),
                                  (".cpio", "application/x-cpio"),
                                  (".csh", "application/x-csh"),
                                  (".css", "text/css"),
                                  (".dll", "application/octet-stream"),
                                  (".doc", "application/msword"),
                                  (".dot", "application/msword"),
                                  (".dvi", "application/x-dvi"),
                                  (".eml", "message/rfc822"),
                                  (".eps", "application/postscript"),
                                  (".etx", "text/x-setext"),
                                  (".exe", "application/octet-stream"),
                                  (".gif", "image/gif"),
                                  (".gtar", "application/x-gtar"),
                                  (".h", "text/plain"),
                                  (".hdf", "application/x-hdf"),
                                  (".htm", "text/html"),
                                  (".html", "text/html"),
                                  (".ief", "image/ief"),
                                  (".jpe", "image/jpeg"),
                                  (".jpeg", "image/jpeg"),
                                  (".jpg", "image/jpeg"),
                                  (".js", "application/x-javascript"),
                                  (".ksh", "text/plain"),
                                  (".latex", "application/x-latex"),
                                  (".m1v", "video/mpeg"),
                                  (".man", "application/x-troff-man"),
                                  (".me", "application/x-troff-me"),
                                  (".mht", "message/rfc822"),
                                  (".mhtml", "message/rfc822"),
                                  (".mif", "application/x-mif"),
                                  (".mov", "video/quicktime"),
                                  (".movie", "video/x-sgi-movie"),
                                  (".mp2", "audio/mpeg"),
                                  (".mp3", "audio/mpeg"),
                                  (".mpa", "video/mpeg"),
                                  (".mpe", "video/mpeg"),
                                  (".mpeg", "video/mpeg"),
                                  (".mpg", "video/mpeg"),
                                  (".ms", "application/x-troff-ms"),
                                  (".nc", "application/x-netcdf"),
                                  (".nws", "message/rfc822"),
                                  (".o", "application/octet-stream"),
                                  (".obj", "application/octet-stream"),
                                  (".oda", "application/oda"),
                                  (".p12", "application/x-pkcs12"),
                                  (".p7c", "application/pkcs7-mime"),
                                  (".pbm", "image/x-portable-bitmap"),
                                  (".pdf", "application/pdf"),
                                  (".pfx", "application/x-pkcs12"),
                                  (".pgm", "image/x-portable-graymap"),
                                  (".pl", "text/plain"),
                                  (".png", "image/png"),
                                  (".pnm", "image/x-portable-anymap"),
                                  (".pot", "application/vnd.ms-powerpoint"),
                                  (".ppa", "application/vnd.ms-powerpoint"),
                                  (".ppm", "image/x-portable-pixmap"),
                                  (".pps", "application/vnd.ms-powerpoint"),
                                  (".ppt", "application/vnd.ms-powerpoint"),
                                  (".ps", "application/postscript"),
                                  (".pwz", "application/vnd.ms-powerpoint"),
                                  (".py", "text/x-python"),
                                  (".pyc", "application/x-python-code"),
                                  (".pyo", "application/x-python-code"),
                                  (".qt", "video/quicktime"),
                                  (".ra", "audio/x-pn-realaudio"),
                                  (".ram", "application/x-pn-realaudio"),
                                  (".ras", "image/x-cmu-raster"),
                                  (".rdf", "application/xml"),
                                  (".rgb", "image/x-rgb"),
                                  (".roff", "application/x-troff"),
                                  (".rtx", "text/richtext"),
                                  (".sgm", "text/x-sgml"),
                                  (".sgml", "text/x-sgml"),
                                  (".sh", "application/x-sh"),
                                  (".shar", "application/x-shar"),
                                  (".snd", "audio/basic"),
                                  (".so", "application/octet-stream"),
                                  (".src", "application/x-wais-source"),
                                  (".sv4cpio", "application/x-sv4cpio"),
                                  (".sv4crc", "application/x-sv4crc"),
                                  (".swf", "application/x-shockwave-flash"),
                                  (".t", "application/x-troff"),
                                  (".tar", "application/x-tar"),
                                  (".tcl", "application/x-tcl"),
                                  (".tex", "application/x-tex"),
                                  (".texi", "application/x-texinfo"),
                                  (".texinfo", "application/x-texinfo"),
                                  (".tif", "image/tiff"),
                                  (".tiff", "image/tiff"),
                                  (".tr", "application/x-troff"),
                                  (".tsv", "text/tab-separated-values"),
                                  (".txt", "text/plain"),
                                  (".ustar", "application/x-ustar"),
                                  (".vcf", "text/x-vcard"),
                                  (".wav", "audio/x-wav"),
                                  (".wiz", "application/msword"),
                                  (".xbm", "image/x-xbitmap"),
                                  (".xlb", "application/vnd.ms-excel"),
                                  (".xls", "application/vnd.ms-excel"),
                                  (".xml", "text/xml"),
                                  (".xpm", "image/x-xpixmap"),
                                  (".xsl", "application/xml"),
                                  (".xwd", "image/x-xwindowdump"),
                                  (".zip", "application/zip")
                                 ]
default_common_types = Map.fromList [
                                     (".jpg", "image/jpg"),
                                     (".mid", "audio/midi"),
                                     (".midi", "audio/midi"),
                                     (".pct", "image/pict"),
                                     (".pic", "image/pict"),
                                     (".pict", "image/pict"),
                                     (".rtf", "application/rtf"),
                                     (".xul", "text/xul")
                                    ]