MIMETypes.st
author Claus Gittinger <cg@exept.de>
Fri, 11 May 2018 13:09:47 +0200
changeset 4087 d9336080778d
parent 4080 90b625be9e29
child 4088 bbf9b58f99c8
permissions -rw-r--r--
#DOCUMENTATION by cg class: MIMETypes class changed: #commentStringsForFilename:

"{ Encoding: utf8 }"

"
 COPYRIGHT (c) 1997 by eXept Software AG 
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
"{ Package: 'stx:libview2' }"

"{ NameSpace: Smalltalk }"

Object subclass:#MIMETypes
	instanceVariableNames:''
	classVariableNames:'CharSetToFontMapping DefaultCommandPerMIMEPerOS
		DefaultPrintCommandPerMIMEPerOS
		FileSuffixToImageReaderClassMapping FileSuffixToTypeMapping
		FilenameToTypeMapping LastSuffix LastType
		SuffixToCommentStringMapping SuffixToParenthesisSpecMapping
		TypeFromContentsDetectors TypeToCommentStringMapping
		TypeToFileSuffixMapping TypeToImageReaderClassMapping
		TypeToInfoMapping TypeToParenthesisSpecMapping
		TypeToViewerApplicationMapping'
	poolDictionaries:''
	category:'Net-Communication-Support'
!

ImmutableString variableByteSubclass:#MIMEType
	instanceVariableNames:''
	classVariableNames:'CachedTypes'
	poolDictionaries:''
	privateIn:MIMETypes
!

!MIMETypes class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1997 by eXept Software AG 
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.


"
!

documentation
"
    just a place to keep MIME information
    (avoid spreading things at many places)

    MIMETypes is abstract and functional.
    Actually, in some OperatingSystems, this information may
    be found in some config files (or registries).
    Therefore, this class may have to be extended to support this
    and fetch the information from there eventually.

    [author:]
        Claus Gittinger
"
!

examples
"
                                                                            [exBegin]
    MIMETypes mimeTypeFromString:'text/plain'
                                                                            [exEnd]
                                                                            [exBegin]
    MIMETypes mimeTypeFromString:'application/x-expecco-testsuite'
                                                                            [exEnd]

                                                                            [exBegin]
    MIMETypes mimeTypeForSuffix:'gif'
    MIMETypes mimeTypeForSuffix:'ets'
    MIMETypes mimeTypeForSuffix:'xlsx'
                                                                            [exEnd]
"
!

knownTypes
"
    simply a reminder for me ...

    application         mime                            file extentsions

        powerpoint      application/ms-powerpoint       .pot, .ppz, .ppt, .pps,
                        application/mspowerpoint
                        application/vnd.ms-powerpoint
                        application/x-mspowerpoint

        shockwave       application/x-shockwave-flash   .swf

        futuresplash    application/futuresplash        .spl
"
! !

!MIMETypes class methodsFor:'initialization'!

addMimeTypeDetector:aMimeTypeFromContentsDetectorBlock
    "any class (especially: image readers) may add a block
     that detects the MIME type from a given content.
     The block is called with two arguments, some data (usually the first few kilobytes
     of a file) and the suffix of the file, or nil if unknown.
     The block should return the MIME type or nil."

    TypeFromContentsDetectors isNil ifTrue:[ TypeFromContentsDetectors := OrderedCollection new ].
    TypeFromContentsDetectors add:aMimeTypeFromContentsDetectorBlock.

    "Modified (comment): / 01-03-2018 / 19:06:46 / mawalch"
!

initialize
    "initialize wellKnown facts"

    MIMEType initialize. "must be initialized first"
    LastSuffix := LastType := nil.
    self initializeFileNameToMimeTypeMapping.
    self initializeImageReaderMappings.
    self initializeCommentStringMappings.
    self initializeParenthesisSpecMappings.

    "
     self initialize
    "

    "Modified: / 10-04-2007 / 15:16:44 / cg"
    "Modified (comment): / 29-11-2011 / 19:11:51 / cg"
!

initializeCommentStringMappings
    "these are used by the editor's comment/uncomment functions"

    TypeToCommentStringMapping := Dictionary new.
    SuffixToCommentStringMapping := Dictionary new.

    TypeToCommentStringMapping
        at:'application/x-make'
        put:#('#' (nil nil)).           "/ '#' EOL comments only

    TypeToCommentStringMapping
        at:'application/x-sh'
        put:#('#' (nil nil)).           "/ '#' EOL comments only

    #('text/html' 'text/xml'
      'application/xml'
      'application/x-expecco-testsuite'
      'application/x-expecco-logfile'
    )
    do:[:eachXMLType |
        TypeToCommentStringMapping
            at:eachXMLType
            put:#(nil ('<!!-- ' ' -->')). "/ '<!!-- ... -->' delimited comments only
    ].

    TypeToCommentStringMapping
        at:'text/css'
        put:#('//' ('/*' '*/')).

    TypeToCommentStringMapping
        at:'application/x-batch-script'
        put:#('@REM ' '@rem ' 'REM ' 'rem ' (nil nil)).         "/ 'rem ' for EOL comments only

    "/ the following is ST/X specific
    TypeToCommentStringMapping
        at:'application/x-smalltalk-source'
        put:#('"/' ('"' '"')).           "/ '"/ ' for EOL; ".." for delimited comments

    "/ this is for standard smalltalk
"/    TypeToCommentStringMapping
"/        at:'application/x-smalltalk-source'
"/        put:#(nil ('"' '"')).            "/ ".." for delimited comments only


    TypeToCommentStringMapping
        at:'application/x-pascal-source'
        put:#(nil ('{' '}')).           "/ '{'..'}' for delimited comments

    "/ this is ANSI-c
    TypeToCommentStringMapping
        at:'application/x-c-source'
        put:#('//' ('/*' '*/')).

    TypeToCommentStringMapping
        at:'application/x-cpp-source'
        put:#('//' ('/*' '*/')).

    TypeToCommentStringMapping
        at:'application/x-csharp-source'
        put:#('//' ('/*' '*/')).

    TypeToCommentStringMapping
        at:'application/x-java-source'
        put:#('//' ('/*' '*/')).

    TypeToCommentStringMapping
        at:'application/x-javascript'
        put:#('//' ('/*' '*/')).

    TypeToCommentStringMapping
        at:'application/x-scheme-source'
        put:#(';' ('#| ' ' |#')).           "/ ';' for EOL comments only

    TypeToCommentStringMapping
        at:'application/x-lisp-source'
        put:#(';' (nil nil)).           "/ ';' for EOL comments only

    TypeToCommentStringMapping
        at:'application/x-python-source'
        put:#('#' (nil nil)).           "/ '#' for EOL comments only

    TypeToCommentStringMapping
        at:'application/x-asn1-source'
        put:#('--' ('--' '--')).


    "/ st/x support files
    SuffixToCommentStringMapping
        at:'style'
        put:#(';' (nil nil)).

    SuffixToCommentStringMapping
        at:'rs'
        put:#(';' (nil nil)).

    "Modified: / 06-09-2011 / 10:46:27 / cg"
!

initializeDefaultCommands
    "these are used to select an application to be opened when a file of a particular
     type is double clicked in the browser.
     TODO: move this to OS"

    |unixCommands win32Commands unixPrintCommands win32PrintCommands listToTry|

    DefaultCommandPerMIMEPerOS := Dictionary new.
    DefaultCommandPerMIMEPerOS at:#unix  put:(unixCommands := Dictionary new).
    DefaultCommandPerMIMEPerOS at:#win32 put:(win32Commands := Dictionary new).

    unixCommands at:'application/x-tar-compressed' put:'tar tvf -'.

    OperatingSystem isMSWINDOWSlike ifFalse:[ |cmd|
        OperatingSystem isOSXlike ifTrue:[
            unixCommands at:'text/html' put:('open -a Safari "%1"').
            unixCommands at:'application/pdf' put:('open -a Preview "%1"').
        ] ifFalse:[
            listToTry := #('firefox' 'chrome' 'chromium' 'konqueror' 'opera').
            cmd := listToTry
                        detect:[:aCmd| (OperatingSystem pathOfCommand:aCmd) notEmptyOrNil ]
                        ifNone:nil.
            cmd notNil ifTrue:[
                unixCommands at:'text/html' put:(cmd, ' "%1"')
            ].

            listToTry := #('acroread' 'okular' 'evince' 'kpdf' 'xpdf').
            cmd := listToTry
                        detect:[:aCmd| (OperatingSystem pathOfCommand:aCmd) notEmptyOrNil ]
                        ifNone:nil.
            cmd notNil ifTrue:[
                unixCommands at:'application/pdf' put:(cmd, ' "%1"')
            ].

            listToTry := #('xdg-open').
            cmd := listToTry
                        detect:[:aCmd| (OperatingSystem pathOfCommand:aCmd) notEmptyOrNil ]
                        ifNone:nil.
            cmd notNil ifTrue:[
                unixCommands at:'text/plain' put:(cmd , ' "%1"')
            ].

        ].
    ].


    DefaultPrintCommandPerMIMEPerOS := Dictionary new.
    DefaultPrintCommandPerMIMEPerOS at:#unix  put:(unixPrintCommands := Dictionary new).
    DefaultPrintCommandPerMIMEPerOS at:#win32 put:(win32PrintCommands := Dictionary new).

    "/ if you have a good (intelligent) spooler ;-)
    unixPrintCommands at:'application/pdf'         put:'lpr "%1"'.
    "/ if not, you may need more...
    "/ unixPrintCommands at:'application/pdf'         put:'pdfToPS %1 | lpr'.

    "
     self initializeDefaultCommands
    "

    "Modified: / 12-05-2004 / 11:43:23 / cg"
    "Modified: / 01-03-2018 / 18:42:42 / mawalch"
!

initializeFileInfoMappings
    "these are used by the file browser if a 'file' command is not present in the OS"

    TypeToInfoMapping := Dictionary new.

    TypeToInfoMapping at:'application/x-smalltalk-source' put:'Smalltalk source'.
    TypeToInfoMapping at:'text/html' put:'HTML document'.
    TypeToInfoMapping at:'text/xml' put:'XML document'.
    TypeToInfoMapping at:'application/xml' put:'XML document'.
    TypeToInfoMapping at:'application/x-c-source' put:'C source'.
    TypeToInfoMapping at:'application/x-c-header' put:'C header file'.
    TypeToInfoMapping at:'application/x-cpp-source' put:'C++ source'.
    TypeToInfoMapping at:'application/x-csharp-source' put:'C# source'.
    TypeToInfoMapping at:'application/x-java-source' put:'Java source'.
    TypeToInfoMapping at:'application/x-javascript' put:'JavaScript source'.
    TypeToInfoMapping at:'application/x-lisp-source' put:'Lisp source'.
    TypeToInfoMapping at:'application/x-scheme-source' put:'Scheme source'.
    TypeToInfoMapping at:'application/x-python-source' put:'Python source'.

    TypeToInfoMapping at:'application/x-make' put:'make rules'.
    TypeToInfoMapping at:'application/binary' put:'binary object file'.

    "
     self initializeFileInfoMappings
     'foo.H' asFilename mimeTypeFromName
     'foo.o' asFilename mimeTypeFromName
    "

    "Modified: / 30-11-2017 / 07:54:23 / mawalch"
!

initializeFileNameToMimeTypeMapping
    "initialize wellKnown facts"

    |types|

    FileSuffixToTypeMapping isNil ifTrue:[
        FileSuffixToTypeMapping := Dictionary new:270.
    ].
    TypeToFileSuffixMapping isNil ifTrue:[
        TypeToFileSuffixMapping := Dictionary new:105.
    ].
    FilenameToTypeMapping isNil ifTrue:[
        FilenameToTypeMapping := Dictionary new:16.
    ].

    types := OrderedCollection new.
    types addAll:self textTypeList.
    types addAll:self imageTypeList.
    types addAll:self videoTypeList.
    types addAll:self audioTypeList.
    types addAll:self applicationTypeList.
    types addAll:self osSpecificTypeList.

    types pairWiseDo:[:suff :typeString|
        |mimeType|

        mimeType := MIMEType fromString:typeString.
        suff isArray ifTrue:[
            suff do:[:s |FileSuffixToTypeMapping at:s put:mimeType].
            TypeToFileSuffixMapping at:mimeType put:suff first.
        ] ifFalse:[
            FileSuffixToTypeMapping at:suff put:mimeType.
            TypeToFileSuffixMapping at:mimeType put:suff.
        ].
    ].

    self miscFilenameList pairWiseDo:[:suffixes :typeString|
        |mimeType|

        mimeType := MIMEType fromString:typeString.
        suffixes isArray ifTrue:[
            suffixes do:[:eachSuffix | FilenameToTypeMapping at:eachSuffix put:mimeType]
        ] ifFalse:[
            FilenameToTypeMapping at:suffixes put:mimeType
        ]
    ].

    "
     self initializeFileNameToMimeTypeMapping
    "

    "Modified (format): / 09-02-2017 / 14:59:33 / stefan"
!

initializeImageReaderMappings
    "these are used so select an image reader, based on a bitmap image's MIME type"

    |rdr|

    FileSuffixToImageReaderClassMapping isNil ifTrue:[
        FileSuffixToImageReaderClassMapping := Dictionary new
    ].
    "MIME" TypeToImageReaderClassMapping isNil ifTrue:[
        TypeToImageReaderClassMapping := Dictionary new
    ].

    "/ setup mimeType to image reader class mapping ...
    self imageReaderForType:'image/jpeg' put:JPEGReader.
    self imageReaderForType:'image/gif'  put:GIFReader.
    self imageReaderForType:'image/tiff' put:TIFFReader.
    self imageReaderForType:'image/x-adobe-dng' put:TIFFReader.
    self imageReaderForType:'image/png'  put:PNGReader.
    self imageReaderForType:'image/icns' put:MacOSXIconReader.

    "/ setup suffix to image reader class mapping ...
    self imageReaderForSuffix:'jpg'  put:JPEGReader.
    self imageReaderForSuffix:'jpeg' put:JPEGReader.
    self imageReaderForSuffix:'gif'  put:GIFReader.
    self imageReaderForSuffix:'tif'  put:TIFFReader.
    self imageReaderForSuffix:'tiff' put:TIFFReader.
    self imageReaderForSuffix:'png'  put:PNGReader.
    self imageReaderForSuffix:'icns' put:MacOSXIconReader.

    "/ some 'used-to-be-optional' readers
    (rdr := Smalltalk at:#WindowsIconReader) notNil ifTrue:[
        self imageReaderForType:'image/bmp'      put:rdr.
        self imageReaderForType:'image/x-MS-bmp' put:rdr.
        self imageReaderForType:'image/x-ms-bmp' put:rdr.
        self imageReaderForType:'image/x-MS-ico' put:rdr.
        self imageReaderForType:'image/x-ms-ico' put:rdr.
        self imageReaderForSuffix:'bmp'            put:rdr.
        self imageReaderForSuffix:'ico'            put:rdr.
    ].
    (rdr := Smalltalk at:#XBMReader) notNil ifTrue:[
        self imageReaderForType:'image/x-xbitmap' put:rdr.
        self imageReaderForSuffix:'xbm'             put:rdr.
    ].
    (rdr := Smalltalk at:#XPMReader) notNil ifTrue:[
        self imageReaderForType:'image/x-xpixmap' put:rdr.
        self imageReaderForSuffix:'pm'              put:rdr.
    ].
    (rdr := Smalltalk at:#PBMReader) notNil ifTrue:[
        self imageReaderForType:'image/x-portable-pixmap'  put:rdr.
        self imageReaderForType:'image/x-portable-bitmap'  put:rdr.
        self imageReaderForType:'image/x-portable-graymap' put:rdr.
        self imageReaderForType:'image/x-portable-anymap'  put:rdr.
        self imageReaderForSuffix:'ppm'                      put:rdr.
        self imageReaderForSuffix:'pbm'                      put:rdr.
        self imageReaderForSuffix:'pgm'                      put:rdr.
        self imageReaderForSuffix:'pnm'                      put:rdr.
    ].
    (rdr := Smalltalk at:#PCXReader) notNil ifTrue:[
        self imageReaderForType:'image/x-pcx' put:rdr.
        self imageReaderForSuffix:'pcx'         put:rdr.
    ].
    (rdr := Smalltalk at:#TargaReader) notNil ifTrue:[
        self imageReaderForType:'image/x-targa' put:rdr.
        self imageReaderForSuffix:'tga'           put:rdr.
    ].
    (rdr := Smalltalk at:#XWDReader) notNil ifTrue:[
        self imageReaderForType:'image/x-xwindowdump' put:rdr.
        self imageReaderForType:'image/x-windowdump'  put:rdr.
        self imageReaderForSuffix:'xwd'                 put:rdr.
    ].
    (rdr := Smalltalk at:#BlitImageReader) notNil ifTrue:[
        self imageReaderForType:'image/x-blitimage' put:rdr.
        self imageReaderForSuffix:'48x48x1'           put:rdr.
    ].
    (rdr := Smalltalk at:#IrisRGBReader) notNil ifTrue:[
        self imageReaderForType:'image/x-rgb' put:rdr.
        self imageReaderForSuffix:'rgb'         put:rdr.
    ].
    (rdr := Smalltalk at:#SunRasterReader) notNil ifTrue:[
        self imageReaderForType:'image/x-sunraster' put:rdr.
        self imageReaderForSuffix:'im8'               put:rdr.
        self imageReaderForSuffix:'icon'              put:rdr.
    ].
    (rdr := Smalltalk at:#ST80FormReader) notNil ifTrue:[
        self imageReaderForType:'image/x-st80-form' put:rdr.
        self imageReaderForSuffix:'form'              put:rdr.
    ].
    (rdr := Smalltalk at:#FaceReader) notNil ifTrue:[
        self imageReaderForType:'image/x-face' put:rdr.
        self imageReaderForSuffix:'face'         put:rdr.
    ].
    (rdr := Smalltalk at:#PCDReader) notNil ifTrue:[
        self imageReaderForType:'image/x-photo-cd' put:rdr.
        self imageReaderForSuffix:'pcd'              put:rdr.
    ].
    (rdr := Smalltalk at:#CMURasterReader) notNil ifTrue:[
        self imageReaderForType:'image/x-cmu-raster' put:rdr.
        self imageReaderForSuffix:'ras'                put:rdr.
    ].

    "/ movie formats - experimental and not yet complete / finished / delivered / published
"/    (rdr := Smalltalk at:#FLIReader) notNil ifTrue:[
"/        self imageReaderForType:'video/x-fli' put:rdr.
"/        self imageReaderForSuffix:'fli'         put:rdr.
"/    ].
"/    (rdr := Smalltalk at:#AVIReader) notNil ifTrue:[
"/        self imageReaderForType:'video/x-msvideo' put:rdr.
"/        self imageReaderForSuffix:'avi'             put:rdr.
"/    ].
"/    (rdr := Smalltalk at:#AVIReader) notNil ifTrue:[
"/        self imageReaderForType:'video/x-msvideo' put:rdr.
"/        self imageReaderForSuffix:'avi'             put:rdr.
"/    ].
"/    (rdr := Smalltalk at:#QuickTimeReader) notNil ifTrue:[
"/        self imageReaderForType:'video/quicktime' put:rdr.
"/        self imageReaderForSuffix:'qt'              put:rdr.
"/        self imageReaderForSuffix:'mov'             put:rdr.
"/        self imageReaderForSuffix:'moov'            put:rdr.
"/    ].
"/    (rdr := Smalltalk at:#MPEG2Reader) notNil ifTrue:[
"/        self imageReaderForType:'video/x-mpeg2' put:rdr.
"/        self imageReaderForSuffix:'mpg2'          put:rdr.
"/        self imageReaderForSuffix:'mpv2'          put:rdr.
"/        self imageReaderForSuffix:'mp2v'          put:rdr.
"/        self imageReaderForSuffix:'mp2'           put:rdr.
"/    ].
"/    (rdr := Smalltalk at:#MPEGReader) notNil ifTrue:[
"/        self imageReaderForType:'video/mpeg' put:rdr.
"/        self imageReaderForSuffix:'mpg'        put:rdr.
"/        self imageReaderForSuffix:'mpeg'       put:rdr.
"/        self imageReaderForSuffix:'mpe'        put:rdr.
"/        self imageReaderForSuffix:'mpv'        put:rdr.
"/        self imageReaderForSuffix:'vps'        put:rdr.
"/        self imageReaderForSuffix:'mpegv'      put:rdr.
"/    ].
"/    (rdr := Smalltalk at:#SGIMovieReader) notNil ifTrue:[
"/        self imageReaderForType:'video/x-sgi-movie' put:rdr.
"/        self imageReaderForSuffix:'movie'             put:rdr.
"/    ].

    "Modified (format): / 09-02-2017 / 15:46:48 / stefan"
    "Modified: / 25-08-2017 / 15:24:51 / cg"
!

initializeParenthesisSpecMappings
    "these are used by the editors to mark matching parentheses"

    |spec|

    TypeToParenthesisSpecMapping := Dictionary new.
    SuffixToParenthesisSpecMapping := Dictionary new.

    "/ ST/X spec
    spec := IdentityDictionary new.
    spec at:#open put:#( $( $[ ${ ).
    spec at:#close put:#( $) $] $} ).
    spec at:#ignore put:#( $' $" '$[' '$]' '${' '$)' ).
    spec at:#eolComment put:'"/'.
    TypeToParenthesisSpecMapping at:'application/x-smalltalk-source' put:spec.

    "/ XML & HTML
    spec := IdentityDictionary new.
    spec at:#open put:#( $< ).
    spec at:#close put:#( $> ).
    spec at:#ignore put:#( $' $" '$[' '$]' '${' '$)' ).
    #( 'text/html' 'text/xml' 'application/xml' ) do:[:eachXMLType |
        TypeToParenthesisSpecMapping at:eachXMLType put:spec
    ].

    "/ ANSI-c, Java, C#
    spec := IdentityDictionary new.
    spec at:#open put:#( $( $[ ${ ).
    spec at:#close put:#( $) $] $} ).
    spec at:#ignore put:#( $' $" ).
    spec at:#eolComment put:'//'.
    TypeToParenthesisSpecMapping at:'application/x-c-source' put:spec.
    TypeToParenthesisSpecMapping at:'application/x-cpp-source' put:spec.
    TypeToParenthesisSpecMapping at:'application/x-csharp-source' put:spec.
    TypeToParenthesisSpecMapping at:'application/x-java-source' put:spec.
    TypeToParenthesisSpecMapping at:'application/x-javascript' put:spec.
    TypeToParenthesisSpecMapping at:'application/x-python-source' put:spec.

    "/ Lisp / Scheme
    spec := IdentityDictionary new.
    spec at:#open put:#( $( $[ ).
    spec at:#close put:#( $) $] ).
    spec at:#ignore put:#( $" ).
    spec at:#eolComment put:';'.
    TypeToParenthesisSpecMapping at:'application/x-lisp-source' put:spec.
    TypeToParenthesisSpecMapping at:'application/x-scheme-source' put:spec.

    "Created: / 10-04-2007 / 15:16:37 / cg"
    "Modified (format): / 01-03-2018 / 19:02:39 / mawalch"
! !

!MIMETypes class methodsFor:'initialization-lists'!

applicationCompressorsAndArchiveTypeList
    "compressor applications"

    ^ #(
        "/ the first column is a list of extensions, the second the more-or-less official MIME type

        'tar'                       'application/x-tar'
        'gtar'                      'application/x-gtar'
        ('tgz' 'tar.gz')            'application/x-tar-gzip-compressed' "/ 'application/x-tar-compressed'
        ('tar.bz2')                 'application/x-tar-bzip2-compressed'
        'zip'                       'application/x-zip-compressed'      "/ will be changed to application/zip soon
        'bz2'                       'application/x-bzip2-compressed'
        ('gz' 'z')                  'application/x-gzip-compressed'     "/ will be changed to application/gzip soon
        'lz'                        'application/lzip'
        'cpio'                      'application/x-cpio'
        'shar'                      'application/x-shar'
        'jar'                       'application/java-archive'
        'sar'                       'application/x-squeak-archive'
        'sit'                       'application/x-stuffit'
        'hqx'                       'application/mac-binhex40'
        'cpt'                       'application/mac-compactpro'
        'pkg'                       'application/x-xar'                 "/ a mac archiver for packages
    )

    "Modified (format): / 05-02-2017 / 19:37:10 / cg"
    "Modified (comment): / 01-03-2018 / 19:07:27 / mawalch"
!

applicationMiscTypeList
    "misc applications"

    ^ #(
        "/ the first column is a list of extensions, the second the more-or-less official MIME type

        ('a' 'o' 'obj' )                      'application/binary'
        'lic'                                 'application/license'
        ('dll' 'so')                          'application/shared-library'

        'ets'                                 'application/x-expecco-testsuite'
        'etr'                                 'application/x-expecco-testrepository'
        'elf'                                 'application/x-expecco-logfile'
        'expeccolicense'                      'application/x-expecco-license'
        'expeccopatch'                        'application/x-expecco-patch'
    )

    "Modified: / 03-11-2011 / 10:42:28 / sr"
    "Modified (format): / 05-02-2017 / 19:37:05 / cg"
    "Modified: / 09-02-2017 / 14:31:45 / stefan"
    "Modified (comment): / 01-03-2018 / 19:07:37 / mawalch"
!

applicationProgLangTypeList
    "applications for programming languages"

    ^ #(
        "/ the first column is a list of extensions, the second the more-or-less official MIME type

        ('st' 'cls' 'rc')            'application/x-smalltalk-source'
        'sif'                        'application/x-smalltalk-source-sif'
        'pac'                        'application/x-smalltalk-dolphin-package'

        'sts'                        'application/x-squeak-source'
        'pr'                         'application/x-squeak-project'

        'c'                          'application/x-c-source'
        ('cc' 'cpp')                 'application/x-cpp-source'
        'cs'                         'application/x-csharp-source'
        ('h' 'hi')                   'application/x-c-header'
        ('js' 'mocha')               'application/x-javascript'
        ('java' 'jav')               'application/x-java-source'
        'sh'                         'application/x-sh'
        'csh'                        'application/x-csh'
        'tcl'                        'application/x-tcl'
        'pl'                         'application/x-perl'
        'dart'                       'application/x-dart'
        'mak'                        'application/x-make'
        'bat'                        'application/x-batch-script'
        ('asn1' 'x409' 'gdmo' 'gdm') 'application/x-asn1-source'

        ('scm' 'ss' 'sch'
         'arc' 'brg' 'rkt')          'application/x-scheme-source'

        ('lisp' 'lsp' 'cl' )         'application/x-lisp-source'

        'py'                         'application/x-python-source'
        ('pyc' 'pyo' )               'application/x-python-compiled-bytecode'
        'pyd'                        'application/x-python-compiled-code'
        'whl'                        'application/x-python-wheel-package'
    )

    "Modified: / 23-06-2017 / 13:34:37 / cg"
    "Modified (comment): / 01-03-2018 / 19:07:43 / mawalch"
!

applicationTextTypeList
    "text applications"

    ^ #(
        "/ the first column is a list of extensions, the second the more-or-less official MIME type

        ('ps' 'eps')                 'application/postscript'
        "/ 'ai'                         'application/postscript'
        'pdf'                        'application/pdf'
        'rtf'                        'application/rtf'
        "/ 'rtf'                        'text/rtf'            ????
        'ics'                        'text/calendar'
        'doc'                        'application/ms-word-document'
        "/ 'doc'                        'application/winword'
        'swf'                        'application/x-shockwave-flash'
        ('ppt' 'ppz' 'pot' 'pps')    'application/mspowerpoint'
        'xls'                        'application/x-excel'
        'slk'                        'application/vnd.ms-excel'
        'txt'                        'text/plain'
        'xlsx'                       'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        'xltx'                       'application/vnd.openxmlformats-officedocument.spreadsheetml.template'
        'potx'                       'application/vnd.openxmlformats-officedocument.presentationml.template'
        'ppsx'                       'application/vnd.openxmlformats-officedocument.presentationml.slideshow'
        'pptx'                       'application/vnd.openxmlformats-officedocument.presentationml.presentation'
        'sldx'                       'application/vnd.openxmlformats-officedocument.presentationml.slide'
        'docx'                       'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
        'dotx'                       'application/vnd.openxmlformats-officedocument.wordprocessingml.template'
        'xlam'                       'application/vnd.ms-excel.addin.macroEnabled.12'
        'xlsb'                       'application/vnd.ms-excel.sheet.binary.macroEnabled.12'
        'xhtml'                      'application/xhtml+xml'

        'edi'                        'application/EDIFACT'
    )

    "Modified: / 26-05-2012 / 15:27:30 / cg"
    "Modified: / 18-05-2015 / 09:46:47 / sr"
    "Modified (format): / 05-02-2017 / 19:37:20 / cg"
    "Modified (comment): / 01-03-2018 / 19:07:51 / mawalch"
!

applicationTypeList
    "applications"

    |typeList|

    typeList := OrderedCollection new.
    typeList addAll:self applicationProgLangTypeList.
    typeList addAll:self applicationTextTypeList.
    typeList addAll:self applicationCompressorsAndArchiveTypeList.
    typeList addAll:self applicationMiscTypeList.

    ^ typeList
!

audioTypeList
    "audio formats ..."

    ^ #(
        "/ the first column is a list of extensions, the second the more-or-less official MIME type

        ('au' 'snd')            'audio/basic'
        'ra'                    'audio/x-realaudio'
        ('ram' 'rm')            'audio/x-pn-realaudio'
        "/ cg: see unixSpecific / windowsSpecific
        "/        'rpm'                   'audio/x-pn-realaudio-plugin'
        ('mpa' 'mpega' 'mpga')  'audio/mpeg'
        "/        'mp3'                   'audio/x-mp3'
        ('mp3' 'mp2')           'audio/mpeg'
        'wav'                   'audio/x-wav'
        ('aif' 'aiff' 'aifc')   'audio/x-aiff'
        ('midi' 'mid')          'audio/midi'
    )

    "Modified: / 26-05-2012 / 15:23:45 / cg"
    "Modified (comment): / 05-02-2017 / 19:37:48 / cg"
    "Modified: / 09-02-2017 / 14:29:59 / stefan"
    "Modified (comment): / 01-03-2018 / 19:07:54 / mawalch"
!

imageTypeList
    "/ wellknown image formats ...

    ^ #(
        "/ the first column is a list of extensions, the second the more-or-less official MIME type

        ('jpg' 'jpeg')  'image/jpeg'
        'gif'           'image/gif'
        ('tif' 'tiff')  'image/tiff'
        ('xbm' 'bm')    'image/x-xbitmap'
        'xpm'           'image/x-xpixmap'
        'png'           'image/png'
        'pcd'           'image/x-photo-cd'
        'bmp'           'image/x-MS-bmp'
        'rgb'           'image/x-rgb'
        'ppm'           'image/x-portable-pixmap'
        'pgm'           'image/x-portable-graymap'
        'pbm'           'image/x-portable-bitmap'
        'pnm'           'image/x-portable-anymap'
        'xwd'           'image/x-xwindowdump'
        'ras'           'image/x-cmu-raster'
        'tga'           'image/x-targa'
        'ico'           'image/x-icon'
        'icns'          'image/icns'
        'dng'           'image/x-adobe-dng'
    )

    "Modified: / 13-09-2017 / 09:05:15 / cg"
    "Modified (comment): / 01-03-2018 / 19:08:18 / mawalch"
!

miscFilenameList
    "other formats (not by suffix, but by fileName instead) ..."

    ^ #(
        "/ the first column is a list of extensions, the second the more-or-less official MIME type

        ('makefile' 'make.proto' 'make.spec' 'nt.mak')  'application/x-make'
        ('exe' 'bin' 'com')                             'application/octet-stream'
        ('class')                                       'application/octet-stream'
        ('top')                                         'application/x-waltop-digital-notepad'
    )

    "Modified (comment): / 05-02-2017 / 19:38:00 / cg"
    "Modified (comment): / 01-03-2018 / 19:09:17 / mawalch"
!

osSpecificTypeList
    OperatingSystem isMSWINDOWSlike ifTrue:[
        ^ self windowsSpecificTypeList
    ].
    ^ self unixSpecificTypeList

"
    self osSpecificTypeList
"
!

textTypeList
   "/ misc text ...

    ^ #(
        "/ the first column is a list of extensions, the second the more-or-less official MIME type

        ('html' 'htm' 'shtml')  'text/html'
        ('txt' 'text')          'text/plain'
        'xml'                   'text/xml'
        'fxml'                  'text/xml'
        'xsd'                   'text/xml'
        'css'                   'text/css'
        'csv'                   'text/csv'
    )

    "Modified: / 05-02-2017 / 19:38:12 / cg"
    "Modified (comment): / 01-03-2018 / 19:09:34 / mawalch"
!

unixSpecificTypeList

    ^ #(
        "/ the first column is a list of extensions, the second the more-or-less official MIME type

        "/ cg: RPM is 'audio/x-pn-realaudio-plugin' for WIN32
        "/     and 'application/x-rpm' for Unix
        'rpm'                   'application/x-rpm'
    )

    "Modified (comment): / 05-02-2017 / 19:38:23 / cg"
    "Modified (comment): / 01-03-2018 / 19:09:37 / mawalch"
!

videoTypeList
    "/ video formats ...

    ^ #(
        "/ the first column is a list of extensions, the second the more-or-less official mimetype

        ('qt' 'mov' 'moov')                'video/quicktime'
        ('mpv' 'mpegv' 'mpg' 'mpeg' 'mpe') 'video/mpeg'
        'movie'                            'video/x-sgi-movie'
        ('avi' 'wmv' 'asf')                'video/x-msvideo'
        ('mpv2' 'mp2v' 'mp2' 'mpeg2')      'video/x-mpeg2'
        ('mp4')                            'video/mp4'
        'rm'                               'application/vnd.rn-realmedia'
        'rv'                               'video/x-pn-realvideo'
        'fli'                              'video/x-fli'
        'flv'                              'video/x-flv'      "/ macromedia flash video
   )

    "Modified (comment): / 05-02-2017 / 19:38:33 / cg"
!

windowsSpecificTypeList
    ^ #(
        "/ the first column is a list of extensions, the second the more-or-less official MIME type

        "/ cg: RPM is 'audio/x-pn-realaudio-plugin' for WIN32
        "/     and 'application/x-rpm' for Unix
        'rpm'                   'audio/x-pn-realaudio-plugin'
    )

    "Modified (comment): / 05-02-2017 / 19:38:42 / cg"
    "Modified (comment): / 01-03-2018 / 19:09:41 / mawalch"
! !

!MIMETypes class methodsFor:'obsolete'!

defaultCommandForMimeType:mimeType
    <resource: #obsolete>
    self obsoleteMethodWarning:'use #defaultCommandTemplateToOpenMimeType:'.

    ^ self defaultCommandTemplateToOpenMimeType:mimeType

    "
     MIMETypes defaultCommandTemplateToOpenMimeType:'application/pdf'
    "

    "Created: / 12-05-2004 / 11:09:22 / cg"
    "Modified: / 12-05-2004 / 11:16:53 / cg"
!

fontForCharset:aCharSetName
    "return the font-encoding for an iso-charset"

    <resource:#obsolete>
    self obsoleteMethodWarning:'use FontDescription >> fontNamePatternForCharset:'.
    ^ FontDescription fontNamePatternForCharset:aCharSetName.

    "
     MIMETypes fontForCharset:'iso2022-jp'
     MIMETypes fontForCharset:'euc-jp'
    "

    "Modified: / 1.8.1998 / 17:00:57 / cg"
! !

!MIMETypes class methodsFor:'queries'!

defineImageType:mimeType suffix:aSuffix reader:aReaderClass
    "register an image reader."

    self defineImageType:mimeType suffix:aSuffix reader:aReaderClass info:nil

    "Modified: / 26-08-2017 / 10:30:00 / cg"
!

defineImageType:mimeType suffix:aSuffix reader:aReaderClass info:info
    "register an image reader."

    "/ flush caches
    LastSuffix := LastType := nil.

    aSuffix notNil ifTrue:[
        self imageReaderForSuffix:aSuffix put:aReaderClass.
    ].

    mimeType notNil ifTrue:[
        self imageReaderForType:mimeType put:aReaderClass
    ].

    (aSuffix notNil and:[mimeType notNil]) ifTrue:[
        self mimeTypeForSuffix:aSuffix put:mimeType
    ].

    (info notNil and:[mimeType notNil])  ifTrue:[
        self typeToInfoMapping at:mimeType put:info.
    ].

    "Created: / 26-08-2017 / 10:29:11 / cg"
    "Modified: / 27-08-2017 / 14:30:53 / cg"
!

fileInfoForMimeType:mimeType
    "given a mimeType, return an info string similar to what the unix 'file' command
     provides. This info here is returned by systems which have no file (i.e. MSDOS) and
     for types of which file does not know about (smalltalk files, for example)"

    ^ self typeToInfoMapping at:mimeType ifAbsent:nil

    "
     self fileInfoForMimeType:(MIMEType fromString:'text/html')
     self fileInfoForMimeType:(MIMEType fromString:'image/gif')
    "

    "Modified (comment): / 27-08-2017 / 14:31:33 / cg"
!

fileSuffixToImageReaderMapping
    "return the suffix-to-imageReader mapping"

    ^ FileSuffixToImageReaderClassMapping ? #()

    "Modified: / 1.8.1998 / 17:00:11 / cg"
!

imageFileSuffixes
    "return a collection with known file suffixes"

    FileSuffixToImageReaderClassMapping isNil ifTrue:[^ #()].
    ^ FileSuffixToImageReaderClassMapping keys

    "Created: / 30.6.1997 / 22:04:48 / cg"
    "Modified: / 1.8.1998 / 17:01:26 / cg"
!

mimeTypeForFilename:filenameOrString
    "given a filename, return the MIME type or nil if unknown"

    |type filename lcFilename suff suff2|

    filename := filenameOrString asFilename.

    lcFilename := filename baseName asLowercase.
    type := FilenameToTypeMapping at:lcFilename ifAbsent:nil.
    type isNil ifTrue:[
        "/ allow for fallback (maybe Windows registry knows something)...
        type := OperatingSystem mimeTypeForFilename:lcFilename.
        "/ the special value #unknown is returned as nil;
        "/ this avoids constant retry if a mimeType is not known in
        "/ the OS.
"/        type isNil ifTrue:[
"/            FilenameToTypeMapping at:lcFilename put:#unknown
"/        ].
    ].

    type == #unknown ifTrue:[
        type := nil.
    ].

    type isNil ifTrue:[
        suff := filename suffix.
        suff notEmpty ifTrue:[
            "/ sigh - special code for multiple-suffices...
            "/ .tar.gz -> tgz
            suff2 := filename withoutSuffix suffix.
            suff2 notEmpty ifTrue:[
                type := self mimeTypeForSuffix:(suff2 , '.' , suff).
            ].
            (type isNil or:[type == #unknown]) ifTrue:[
                type := self mimeTypeForSuffix:suff
            ].
        ]
    ].

    type == #unknown ifTrue:[
        type := nil.
    ].

    ^ type

    "
     MIMETypes mimeTypeForFilename:'typeinst.dvi'
     MIMETypes mimeTypeForFilename:'foo.tar'
     MIMETypes mimeTypeForFilename:'foo.tgz'
     MIMETypes mimeTypeForFilename:'foo.tar.gz'
     MIMETypes mimeTypeForFilename:'foo.txt'
     MIMETypes mimeTypeForFilename:'foo.pkg'
     MIMETypes mimeTypeForFilename:'foo.sm'
     MIMETypes mimeTypeForFilename:'/Users/cg/work/stx/goodies/bitmaps/tiffimages/moreSamples/multi-channel.ome.tif'
     MIMETypes mimeTypeForFilename:'multi-channel.ome.tif'
     MIMETypes mimeTypeForFilename:'multi-channel.tif'
    "

    "Modified (format): / 27-06-2017 / 16:25:40 / stefan"
    "Modified: / 27-08-2017 / 16:35:37 / cg"
    "Modified (comment): / 01-03-2018 / 18:52:25 / mawalch"
!

mimeTypeForFilename:filename put:mimeType
    "register a MIME type for a filename"

    FilenameToTypeMapping isNil ifTrue:[
        FilenameToTypeMapping := Dictionary new
    ].
    FilenameToTypeMapping at:filename put:(MIMEType fromString:mimeType asLowercase)

    "Modified (comment): / 01-03-2018 / 18:52:42 / mawalch"
!

mimeTypeForSuffix:suffix
    "given a file suffix, return the MIME type"

    |type lcSuffix|

    suffix = LastSuffix ifTrue:[
        ^ LastType
    ].

    lcSuffix := suffix asLowercase.
    type := FileSuffixToTypeMapping at:lcSuffix ifAbsent:nil.
    type isNil ifTrue:[
        "/ allow for fallback ...
        type := OperatingSystem mimeTypeForSuffix:lcSuffix.
        "/ the special value #unknown is returned as nil;
        "/ this avoids constant retry if a suffix is not known in the OS.
        type := type isNil ifTrue:[#unknown] ifFalse:[MIMEType fromString:type].
        FileSuffixToTypeMapping at:lcSuffix put:type.
    ].

    LastSuffix := suffix.
    LastType := type.
    ^ type

    "
     self mimeTypeForSuffix:'gif'
     self mimeTypeForSuffix:'rpm'
     self mimeTypeForSuffix:'zip'
    "

    "Created: / 30-06-1997 / 21:55:51 / cg"
    "Modified: / 14-02-2011 / 17:14:34 / cg"
    "Modified: / 09-02-2017 / 14:57:52 / stefan"
    "Modified (comment): / 01-03-2018 / 18:51:35 / mawalch"
!

mimeTypeForSuffix:suffix put:mimeType
    "register a MIME type for a file suffix"

    FileSuffixToTypeMapping isNil ifTrue:[
        FileSuffixToTypeMapping := Dictionary new
    ].
    FileSuffixToTypeMapping at:suffix ifAbsentPut:[MIMEType fromString:mimeType asLowercase].

    "Created: / 30-06-1997 / 21:56:20 / cg"
    "Modified: / 01-08-1998 / 17:03:18 / cg"
    "Modified: / 09-02-2017 / 15:09:17 / stefan"
    "Modified (comment): / 01-03-2018 / 18:51:17 / mawalch"
!

mimeTypeForSuffixMapping

    ^ FileSuffixToTypeMapping
!

mimeTypeFromString:mimeTypeString
    "given a MIME type for a string"

     ^ MIMEType fromString:mimeTypeString

    "
     MIMETypes mimeTypeFromString:'text/html'
     MIMETypes mimeTypeFromString:'image/gif'
     MIMETypes mimeTypeFromString:'application/x-expecco-testsuite'
    "

    "Modified (comment): / 01-03-2018 / 18:49:50 / mawalch"
!

mimeTypeOfContents:filename
    "given a filename, scan the contents, return the MIME type or nil, if unknown"

    |typeString|

    typeString := filename mimeTypeOfContents.
    typeString isNil ifTrue:[^ nil].
    ^ MIMEType fromString:typeString.

    "Modified (comment): / 01-03-2018 / 18:50:06 / mawalch"
!

mimeTypeOfData:someData
    "this tries to guess the MIME type of contents of someData.
     Returns nil if unknown.
     This is done using some heuristics, and may need some improvement"

    ^ self mimeTypeOfData:someData suffix:nil

    "Modified (comment): / 01-03-2018 / 18:50:22 / mawalch"
!

mimeTypeOfData:someData suffix:fileNameSuffixOrNilIfUnknown
    "this tries to guess the MIME type of someData.
     Returns nil if unknown.
     In addition to registered detectors (see addMimeTypeDetector:),
     this is done using heuristics, and may need some improvement"

    |buffer lcBuffer size idx idx2|

    someData isEmptyOrNil ifTrue:[^ nil].

    TypeFromContentsDetectors notNil ifTrue:[
        TypeFromContentsDetectors do:[:eachDetector |
            |m|
            
            m := eachDetector value:someData value:fileNameSuffixOrNilIfUnknown.
            m notNil ifTrue:[^ m]
        ]
    ].    
    
    size := 2048 min:someData size.

    "/ read some data from the file ...
    buffer := (someData copyTo:size) asString.

    lcBuffer := buffer asLowercase.

    (idx := lcBuffer findString:'mimetype:') ~~ 0 ifTrue:[
        idx := idx + 'mimetype:' size.
        idx := lcBuffer indexOfNonSeparatorStartingAt:idx.
        idx2 := lcBuffer indexOfSeparatorStartingAt:idx.
        idx2 > idx ifTrue:[
            ^ MIMEType fromString:(lcBuffer copyFrom:idx to:idx2-1)
        ].
    ].

    "/ real starters
    #(
        ( #[16r4C 16r00 16r00 16r00 16r01 16r14 16r02 16r00 16r00 16r00 16r00 16r00 16rC0 16r00 16r00 16r00 16r00 16r00 16r00 16r46] 
                #'application/x-ms-shortcut' )
        ( 'ITOLITLS' 
                #'application/x-ms-reader' )
        ( 'WALTOP' 
                #'application/x-waltop-digital-notepad' )
        ('PK'                       
                #'application/x-zip-compressed')
        ('LZIP'
                #'application/lzip')
        ('<?xml'                       
                #'text/xml')
     ) pairsDo:[:pattern :what |
        |patternString|

        patternString := pattern asString.
        (buffer startsWith:patternString) ifTrue:[
            what = #'application/x-zip-compressed' ifTrue:[
                fileNameSuffixOrNilIfUnknown = 'jar' ifTrue:[
                    ^ MIMEType fromString: #'application/java-archive'
                ].
            ].
            ^ MIMEType fromString:what
        ]
    ].

    "/ somewhere near the beginning
    #(
            ('<body:'                   #'text/html')
            ('%!!ps-adobe'               #'application/postscript')
            ('%PDF-'                    #'application/pdf')
            ('#!! /bin/sh'               #'application/x-sh')
            ('#!!/bin/sh'                #'application/x-sh')
            "/ ('#!! /bin/bash'              'application/x-bash')
            "/ ('#!!/bin/bash'               'application/x-bash')
            ('UNB+UNO'                  #'application/EDIFACT')

            ('---- encoding: '          #'application/x-smalltalk-source')
            ('---- timestamp '          #'application/x-smalltalk-source')
            ('from dolphin'             #'application/x-smalltalk-source')
            ('from visualworks'         #'application/x-smalltalk-source')
            ('from squeak'              #'application/x-smalltalk-source')
            ('from smalltalk/x'         #'application/x-smalltalk-source')
            ('"{ Package:'              #'application(x-smalltalk-source')
            ('categoriesforclass'       #'application/x-smalltalk-source')
            ('methodsfor!!'              #'application/x-smalltalk-source')
            ('subclass:'                #'application/x-smalltalk-source')
            ('methodsfor:'              #'application/x-smalltalk-source')
            ('interchangeversion:'      #'application/x-smalltalk-source-sif')
            ('subclass:'                #'application/x-smalltalk-source')
            ('methodsfor:'              #'application/x-smalltalk-source')
            ('Application create:'      #'application/x-smalltalk-source')
            ('becomeDefault!!'           #'application/x-smalltalk-source')
            ('(reader defineClass:'     #'application/x-smalltalk-source')      "/ gravel smalltalk
            ('(define '                 #'application/x-scheme-source')      

    ) pairsDo:[:pattern :what | 
        (lcBuffer findString:pattern) ~~ 0 ifTrue:[
            ^ MIMEType fromString:what
        ]
    ].
    
    (idx := lcBuffer findString:'<h') ~~ 0 ifTrue:[
        ((lcBuffer continuesWith:'<head' startingAt:idx)
        or:[(lcBuffer continuesWith:'<html' startingAt:idx)
        or:[(lcBuffer continuesWith:'<h1' startingAt:idx)
        or:[(lcBuffer continuesWith:'<h2' startingAt:idx)
        or:[(lcBuffer continuesWith:'<h3' startingAt:idx)
        or:[(lcBuffer continuesWith:'<h4' startingAt:idx)
        or:[(lcBuffer continuesWith:'<h5' startingAt:idx)
        or:[(lcBuffer continuesWith:'<h6' startingAt:idx)]]]]]]])
        ifTrue:[
            ^ MIMEType fromString:'text/html'
        ]
    ].

    [size ~~ 0 and:[(buffer at:size) isPrintable]] whileTrue:[size := size - 1].

    size == 0 ifTrue:[
        ^ MIMEType fromString:'text/plain'
    ].
    ^ nil

    "Modified: / 12-07-2011 / 19:08:17 / cg"
    "Modified (comment): / 01-03-2018 / 18:50:36 / mawalch"
!

suffixForMimeType:mimeType
    "given a file suffix, return the MIME type"

    ^ TypeToFileSuffixMapping at:mimeType ifAbsent:nil

    "
     self suffixForMimeType:(MIMEType fromString:'image/gif')
    "

    "Created: / 30-06-1997 / 21:55:51 / cg"
    "Modified: / 23-12-1999 / 22:30:55 / cg"
    "Modified (comment): / 01-03-2018 / 18:50:50 / mawalch"
!

suffixForMimeTypeString:mimeTypeString
    "given a file suffix, return the MIME type"

     ^ self suffixForMimeType:(MIMEType fromString:mimeTypeString)

    "
     self suffixForMimeTypeString:'image/gif'
    "

    "Created: / 30-06-1997 / 21:55:51 / cg"
    "Modified: / 23-12-1999 / 22:30:55 / cg"
    "Modified (comment): / 01-03-2018 / 18:51:06 / mawalch"
!

typeToInfoMapping
    TypeToInfoMapping isNil ifTrue:[
        self initializeFileInfoMappings
    ].
    ^ TypeToInfoMapping

    "Created: / 27-08-2017 / 14:30:44 / cg"
! !

!MIMETypes class methodsFor:'queries-applications'!

defaultCommandPerMIME
    "returns the collection which is used to map MIME type to command-templates."

    "TODO: move this to OS/UserPreferences"

    DefaultCommandPerMIMEPerOS isNil ifTrue:[
        self initializeDefaultCommands
    ].
    OperatingSystem isUNIXlike ifTrue:[
        ^ DefaultCommandPerMIMEPerOS at:#unix
    ].
    ^ DefaultCommandPerMIMEPerOS at:#win32

    "
     MIMETypes defaultCommandPerMIME
    "

    "Modified (comment): / 16-09-2011 / 16:20:12 / cg"
    "Modified (comment): / 01-03-2018 / 19:06:54 / mawalch"
!

defaultCommandTemplateToOpenMimeType:mimeType
    |cmd|

    cmd := self defaultCommandPerMIME at:mimeType ifAbsent:nil.
    cmd isNil ifTrue:[
        OperatingSystem isMSWINDOWSlike ifTrue:[
            cmd := Win32OperatingSystem::RegistryEntry commandTemplateToOpenMimeType:mimeType
        ].
    ].
    ^ cmd

    "
     MIMETypes defaultCommandTemplateToOpenMimeType:'application/pdf'
     MIMETypes defaultCommandTemplateToOpenMimeType:'text/html'
    "

    "Created: / 12-05-2004 / 11:09:22 / cg"
    "Modified: / 12-05-2004 / 11:16:53 / cg"
!

defaultCommandTemplateToPrintMimeType:mimeType
    |cmd|

    cmd := self defaultPrintCommandPerMIME at:mimeType ifAbsent:nil.
    cmd isNil ifTrue:[
        OperatingSystem isMSWINDOWSlike ifTrue:[
            cmd := Win32OperatingSystem::RegistryEntry commandTemplateToPrintMimeType:mimeType
        ].
    ].
    ^ cmd

    "
     MIMETypes defaultCommandTemplateToPrintMimeType:'application/pdf'
    "
!

defaultPrintCommandPerMIME
    "returns the collection which is used to map MIME type to printing command-templates."

    "TODO: move this to OS/UserPreferences"

    DefaultPrintCommandPerMIMEPerOS isNil ifTrue:[
        self initializeDefaultCommands
    ].
    OperatingSystem isUNIXlike ifTrue:[
        ^ DefaultPrintCommandPerMIMEPerOS at:#unix
    ].
    ^ DefaultPrintCommandPerMIMEPerOS at:#win32
! !

!MIMETypes class methodsFor:'queries-image formats'!

imageReaderClasses
    "return a collection of registered image reader classes"

    TypeToImageReaderClassMapping notNil ifTrue:[
        ^ TypeToImageReaderClassMapping values asSet.
    ].
    ^ #().

    "Created: / 30-06-1997 / 22:03:42 / cg"
    "Modified: / 01-08-1998 / 16:59:52 / cg"
    "Modified: / 09-02-2017 / 15:23:52 / stefan"
!

imageReaderForSuffix:aSuffix
    "given a file suffix, return an appropriate image reader class"

    FileSuffixToImageReaderClassMapping isNil ifTrue:[
        self initializeImageReaderMappings
    ].
    ^ FileSuffixToImageReaderClassMapping at:aSuffix asLowercase ifAbsent:nil

    "
     self imageReaderForSuffix:'wbmp'
    "

    "Created: / 30-06-1997 / 21:59:11 / cg"
    "Modified: / 01-08-1998 / 17:01:58 / cg"
    "Modified (comment): / 01-03-2018 / 18:57:59 / mawalch"
!

imageReaderForSuffix:aSuffix put:aReaderClass
    "register an image reader for a file suffix"

    FileSuffixToImageReaderClassMapping isNil ifTrue:[
        self initializeImageReaderMappings
    ].
    FileSuffixToImageReaderClassMapping at:aSuffix asLowercase put:aReaderClass

    "Created: / 30.6.1997 / 21:59:43 / cg"
    "Modified: / 1.8.1998 / 17:02:14 / cg"
!

imageReaderForType:mimeTypeString
    "given a MIME type, return an appropriate image reader class"

    TypeToImageReaderClassMapping isNil ifTrue:[
        self initializeImageReaderMappings
    ].
    ^ TypeToImageReaderClassMapping at:mimeTypeString asLowercase ifAbsent:nil

    "Created: / 30-06-1997 / 21:56:01 / cg"
    "Modified: / 01-08-1998 / 17:02:28 / cg"
    "Modified (format): / 01-03-2018 / 18:58:10 / mawalch"
!

imageReaderForType:mimeTypeString put:aReaderClass
    "register an image reader for a MIME type"

    TypeToImageReaderClassMapping isNil ifTrue:[
        self initializeImageReaderMappings
    ].
    TypeToImageReaderClassMapping
        at:(MIMEType fromString:mimeTypeString asLowercase)
        put:aReaderClass

    "Created: / 30-06-1997 / 21:56:11 / cg"
    "Modified: / 01-08-1998 / 17:02:40 / cg"
    "Modified: / 09-02-2017 / 15:32:58 / stefan"
    "Modified (comment): / 01-03-2018 / 18:58:27 / mawalch"
! !

!MIMETypes class methodsFor:'queries-language syntax'!

commentStringsForFilename:aFilenameOrString
    "return a useful comment definition; heuristics for now.
     The returned value is an array of 2 elements;
     the first is the end-of-line comment string (or nil);
     the second an array of opening/closing delimiters (or an array of nils)"

     |filename mime|

     filename := aFilenameOrString asFilename.
     mime := MIMETypes mimeTypeForFilename:filename.
     ^ self commentStringsForMimeType:mime suffix:(filename suffix)

    "
     MIMETypes commentStringsForFilename:'Makefile'.
     MIMETypes commentStringsForFilename:'Object.st'.
     MIMETypes commentStringsForFilename:'Foo.java'.
     MIMETypes commentStringsForFilename:'Foo.html'.
    "
!

commentStringsForFilename:aFilename ifUnknown:alternativeBlockReturningCommentString
    "return a useful comment definition; heuristics for now.
     The returned value is an array of 2 elements;
     the first is the end-of-line comment string (or nil);
     the second an array of opening/closing delimiters (or an array of nils)"

     |mime|

     mime := MIMETypes mimeTypeForFilename:aFilename.
     ^ self commentStringsForMimeType:mime suffix:(aFilename asFilename suffix) ifUnknown:alternativeBlockReturningCommentString

    "
     MIMETypes commentStringsForFilename:'Makefile'.
     MIMETypes commentStringsForFilename:'Object.st'.
     MIMETypes commentStringsForFilename:'Foo.java'.
    "
!

commentStringsForMimeType:mime suffix:suff
    "return a useful comment definition; heuristics for now.
     The returned value is an array of 2 elements;
     the first is the end-of-line comment string (or nil);
     the second an array of opening/closing delimiters (or an array of nils)"

    ^ self
        commentStringsForMimeType:mime suffix:suff
        ifUnknown: #(';' (nil nil))

    "
     |mime|

     mime := MIMETypes mimeTypeForFilename:'Makefile'.
     MIMETypes commentStringsForMimeType:mime suffix:nil.
    "

    "
     |mime|

     mime := MIMETypes mimeTypeForFilename:'Object.st'.
     MIMETypes commentStringsForMimeType:mime suffix:nil.
    "
!

commentStringsForMimeType:mime suffix:suff ifUnknown:alternativeBlockReturningCommentString
    "return a useful comment definition; heuristics for now.
     The returned value is an array of 2 elements;
     the first is the end-of-line comment string (or nil);
     the second an array of opening/closing delimiters (or an array of nils)"

    |commentSpec|

    commentSpec := TypeToCommentStringMapping at:mime ifAbsent:nil.
    commentSpec notNil ifTrue:[
        ^ commentSpec
    ].
    suff notNil ifTrue:[
        commentSpec := SuffixToCommentStringMapping at:suff ifAbsent:nil.
        commentSpec notNil ifTrue:[
            ^ commentSpec
        ].
    ].
    ^ alternativeBlockReturningCommentString value

    "
     |mime|

     mime := MIMETypes mimeTypeForFilename:'Makefile'.
     MIMETypes commentStringsForMimeType:mime suffix:nil.
    "

    "
     |mime|

     mime := MIMETypes mimeTypeForFilename:'Object.st'.
     MIMETypes commentStringsForMimeType:mime suffix:nil.
    "
!

parenthesisSpecForFilename:aFilename
    "return a useful parentesis spec; heuristics for now.
     The returned value is a dictionary to be used as parentesis spec in an editor"

     |mime|

     mime := MIMETypes mimeTypeForFilename:aFilename.
     ^ self parenthesisSpecForMimeType:mime suffix:(aFilename asFilename suffix)

    "
     MIMETypes parenthesisSpecForFilename:'Object.st'.
     MIMETypes parenthesisSpecForFilename:'Foo.java'.
     MIMETypes parenthesisSpecForFilename:'Foo.html'.
     MIMETypes parenthesisSpecForFilename:'Foo.lsp'.
    "

    "Created: / 10-04-2007 / 15:18:41 / cg"
!

parenthesisSpecForFilename:aFilename ifUnknown:alternative
     |mime|

     mime := MIMETypes mimeTypeForFilename:aFilename.
     ^ self parenthesisSpecForMimeType:mime suffix:(aFilename asFilename suffix) ifUnknown:alternative

    "Created: / 10-04-2007 / 15:26:20 / cg"
!

parenthesisSpecForMimeType:mime suffix:suff
    ^ self
        parenthesisSpecForMimeType:mime suffix:suff
        ifUnknown:nil

    "Created: / 10-04-2007 / 15:19:39 / cg"
    "Modified (format): / 01-03-2018 / 19:03:58 / mawalch"
!

parenthesisSpecForMimeType:mime suffix:suff ifUnknown:alternativeValue
    |spec|

    spec := TypeToParenthesisSpecMapping at:mime ifAbsent:nil.
    spec notNil ifTrue:[
        ^ spec
    ].

    spec := SuffixToParenthesisSpecMapping at:suff ifAbsent:nil.
    spec notNil ifTrue:[
        ^ spec
    ].

    ^ alternativeValue value

    "Created: / 10-04-2007 / 15:20:38 / cg"
! !

!MIMETypes::MIMEType class methodsFor:'documentation'!

documentation
"
    like a string, but knows that it represents a mimeType.
    mimetypes are singletons, remembered in the class variable CachedTypes.
"
! !

!MIMETypes::MIMEType class methodsFor:'instance creation'!

fromString:aString
    |cachedType newType|

    aString class == self ifTrue:[^ aString].

    CachedTypes isNil ifTrue:[
        CachedTypes := Dictionary new:100.
    ].
    cachedType := CachedTypes at:aString ifAbsent:nil.
    cachedType notNil ifTrue:[^ cachedType].

    newType := aString copy changeClassTo:self.
    CachedTypes at:aString put:newType.
    ^ newType

    "
     CachedTypes := nil.
     self fromString:'text/html'
    "

    "Modified: / 20-07-2012 / 17:36:31 / cg"
    "Modified (comment): / 09-02-2017 / 15:36:06 / stefan"
! !

!MIMETypes::MIMEType methodsFor:'queries'!

fileTypeInfo
    ^ MIMETypes fileInfoForMimeType:self

    "
     (MIMETypes mimeTypeFromString:'application/x-smalltalk-source') fileTypeInfo
    "

    "Modified: / 01-03-2018 / 19:16:49 / mawalch"
!

isArchive
    <resource: #obsolete>
    "return true, if I represent an archive type (such as zip or tar)"

    ^ self isArchiveType
!

isArchiveType
    "return true, if I represent an archive type (such as zip or tar)"

    |archivTypes|

    archivTypes := MIMETypes applicationCompressorsAndArchiveTypeList.
    archivTypes pairWiseDo:[: ext : type |
        self = type ifTrue:[ ^ true].
    ].
    ^ false
!

isBinary
    <resource: #obsolete>
    "return true, if I represent a binary (non-text) type"

    ^ self isBinaryType
!

isBinaryType
    "return true, if I represent a binary (non-text) type"

    ^ self isTextType not
!

isHtml
    <resource: #obsolete>
    "return true, if I represent the html text type"

    ^ self isHtmlType
!

isHtmlType
    "return true, if I represent the html text type"

    ^ (self = 'text/html')
!

isImage
    <resource: #obsolete>
    "return true, if I represent an image type (such as gif or jpg)"

    ^ self isImageType
!

isImageType
    "return true, if I represent an image type (such as gif or jpg)"

    ^ (self startsWith:'image/')
!

isPdf
    <resource: #obsolete>
    "return true, if I represent the pdf type"

    ^ self isPdfType
!

isPdfType
    "return true, if I represent the pdf type"

    ^ (self = 'application/pdf')
!

isSmalltalkSource
    <resource: #obsolete>
    "return true, if I represent the smalltalk sourcecode type"

    ^ self isSmalltalkSourceType
!

isSmalltalkSourceType
    "return true, if I represent the smalltalk sourcecode type"

    ^ (self startsWith: 'application/x-smalltalk-source')
!

isTextType
    "return true, if I represent some text type"

    ^ self startsWith:'text/'
!

isXml
    <resource: #obsolete>
    "return true, if I represent the xml text type"

    ^ self isXmlType
!

isXmlType
    "return true, if I represent the xml text type"

    ^ self = 'text/xml' or:[self = 'application/xml']

    "Modified (format): / 13-03-2017 / 09:41:52 / stefan"
!

suffix
    ^ MIMETypes suffixForMimeType:self

    "
       (MIMETypes mimeTypeFromString:'application/x-expecco-testsuite') suffix
    "
! !

!MIMETypes class methodsFor:'documentation'!

version
    ^ '$Header$'
!

version_CVS
    ^ '$Header$'
! !


MIMETypes initialize!