PageRenderTime 38ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/Utilities/Mime/Mime.tcl

http://wub.googlecode.com/
TCL | 207 lines | 151 code | 29 blank | 27 comment | 26 complexity | 61129b16a508ce44e5c2c4afea8d3c6b MD5 | raw file
  1. # Mime - calculate the mime types of file
  2. package require WubUtils
  3. package require Debug
  4. Debug define mime 10
  5. package require mime-magic
  6. package provide Mime 1.0
  7. set ::API(Utilities/Mime) {
  8. {
  9. Mime analysis - like unix [[file]] command
  10. Identifies file types by inspection, maps .ext to mime type
  11. }
  12. }
  13. namespace eval ::Mime {
  14. variable file_attributes 1 ;# should we seek file attributes to tell us?
  15. variable home [file dirname [info script]]
  16. variable e2m {}
  17. variable default text/plain ;# default mime type
  18. variable prime mime.types ;# file to prime map
  19. # simple minded file extension<->mime-type map
  20. # add --
  21. #
  22. # add a MIME type mapping
  23. #
  24. # Arguments:
  25. # suffix A file suffix
  26. # type The corresponding MIME Content-Type.
  27. #
  28. # Results:
  29. # None
  30. proc add {ext type} {
  31. variable e2m
  32. set ext [string tolower [string trimleft $ext .]]
  33. dict set e2m .$ext $type
  34. dict lappend e2m $type .$ext
  35. }
  36. proc read {file} {
  37. package require fileutil
  38. variable e2m
  39. ::fileutil::foreachLine line $file {
  40. set line [string trim $line]
  41. if {($line eq "") || [string match \#* $line]} {
  42. continue
  43. }
  44. regsub {[\t ]+} $line " " line
  45. set line [split $line]
  46. if {[llength $line] == 1} {
  47. # record a known type with no extension
  48. dict set e2m [lindex $line 0] {}
  49. } else {
  50. if {[string match {*/*} [lindex $line 0]]} {
  51. foreach ext [lrange $line 1 end] {
  52. add $ext [lindex $line 0]
  53. }
  54. } else {
  55. add [lindex $line 0] [lindex $line 1]
  56. }
  57. }
  58. }
  59. }
  60. # determine type by file extension
  61. proc MimeOf {ext {def ""}} {
  62. # try to prime the e2m array
  63. variable prime
  64. variable home
  65. if {$prime ne ""} {
  66. if {[file pathtype $prime] eq "relative"} {
  67. set prime [file join $home $prime]
  68. }
  69. catch {
  70. read $prime
  71. }
  72. }
  73. # set the default mimetype
  74. variable e2m; variable default
  75. dict set e2m "" $default
  76. proc MimeOf [list ext [list default $default]] {
  77. variable e2m
  78. set ext ".[string trim [string tolower $ext] .]"
  79. if {[dict exist $e2m $ext]} {
  80. return [dict get $e2m $ext] ;# mime type of extension
  81. } else {
  82. return $default ;# default mime type
  83. }
  84. }
  85. return [MimeOf $ext $def]
  86. }
  87. # init the thing
  88. proc init {args} {
  89. Debug.mime {Mime init $args}
  90. foreach {n v} $args {
  91. variable $n $v
  92. }
  93. proc init {args} {} ;# can only be initialized once.
  94. }
  95. # call mime magic on a given string or {path $file}
  96. proc magic {args} {
  97. if {[llength $args]%2} {
  98. # this is a string
  99. Debug.mime {typeOf text}
  100. magic::value [lindex $args end]
  101. set args [lrange $args 0 end-1]
  102. } else {
  103. # this is a file
  104. Debug.mime {typeOf file}
  105. magic::open [dict get $args path]
  106. }
  107. if {[catch {
  108. ::magic::/magic.mime
  109. } result eo]} {
  110. Debug.mime {magic error: $result ($eo)}
  111. set result ""
  112. }
  113. if {$result eq ""
  114. && [dict exists $args path]
  115. } {
  116. return [MimeOf [file extension [dict get $args path]]]
  117. }
  118. Debug.mime {magic result: $result}
  119. return [lindex [split $result] 0]
  120. }
  121. variable cache; array set cache {}
  122. # this tries to store mime info in the file's attributes
  123. proc type {file} {
  124. Debug.mime {MIME type $file}
  125. # filesystem may know file's mime type
  126. variable file_attributes
  127. if {$file_attributes
  128. && ![catch {file attributes $file -mime} type]
  129. && $type != ""} {
  130. # filesystem maintains -mime type attribute
  131. return $type
  132. }
  133. # some special file types have special mime types
  134. set ft [string tolower [file type $file]]
  135. switch -- $ft {
  136. directory {
  137. return "multipart/x-directory"
  138. }
  139. characterspecial -
  140. blockspecial -
  141. fifo -
  142. socket {
  143. return "application/x-$ft"
  144. }
  145. }
  146. variable cache
  147. if {[info exists cache($file)]} {
  148. return $cache($file)
  149. }
  150. # possibly do mime magic
  151. Debug.mime {MIME magic}
  152. if {![catch {
  153. ::magic::open $file
  154. set result [::magic::/magic.mime]
  155. Debug.mime {MIME magic: $result}
  156. } r eo]} {
  157. if {$file_attributes} {
  158. # record the finding for posterity
  159. catch {file attributes $file -mime $result}
  160. }
  161. Debug.mime {MIME cache: $result}
  162. if {$result ne ""} {
  163. set cache($file) $result
  164. return $result
  165. }
  166. } else {
  167. Debug.mime {MAGIC error: $r ($eo)}
  168. }
  169. # fallback to using file extension
  170. set result [MimeOf [file extension $file]]
  171. set cache($file) $result
  172. Debug.mime {MIME ext: $result}
  173. return $result
  174. }
  175. namespace import
  176. namespace export -clear *
  177. namespace ensemble create -subcommands {}
  178. }