blob: 1b73a656b81c6c0e7f9dfb17d2e3ce7d9457214a [file] [log] [blame]
Guido van Rossumac8a9f31997-09-30 19:05:50 +00001"""Guess the MIME type of a file.
2
Fred Drake5109ffd1998-05-18 16:27:20 +00003This module defines two useful functions:
Guido van Rossumac8a9f31997-09-30 19:05:50 +00004
Barry Warsaw107771a2001-10-25 21:49:18 +00005guess_type(url, strict=1) -- guess the MIME type and encoding of a URL.
Guido van Rossumac8a9f31997-09-30 19:05:50 +00006
Barry Warsaw107771a2001-10-25 21:49:18 +00007guess_extension(type, strict=1) -- guess the extension for a given MIME type.
Fred Drake5109ffd1998-05-18 16:27:20 +00008
Guido van Rossumac8a9f31997-09-30 19:05:50 +00009It also contains the following, for tuning the behavior:
10
11Data:
12
13knownfiles -- list of files to parse
14inited -- flag set when init() has been called
Fred Drakeeeee4ec2001-08-03 21:01:44 +000015suffix_map -- dictionary mapping suffixes to suffixes
Guido van Rossumac8a9f31997-09-30 19:05:50 +000016encodings_map -- dictionary mapping suffixes to encodings
17types_map -- dictionary mapping suffixes to types
18
19Functions:
20
21init([files]) -- parse a list of files, default knownfiles
22read_mime_types(file) -- parse one file, return a dictionary or None
Guido van Rossumac8a9f31997-09-30 19:05:50 +000023"""
24
Fred Drakeeeee4ec2001-08-03 21:01:44 +000025import os
Guido van Rossumac8a9f31997-09-30 19:05:50 +000026import posixpath
Guido van Rossum1c5fb1c1998-10-12 15:12:28 +000027import urllib
Guido van Rossumac8a9f31997-09-30 19:05:50 +000028
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +000029__all__ = [
30 "guess_type","guess_extension","guess_all_extensions",
31 "add_type","read_mime_types","init"
32]
Skip Montanaro03d90142001-01-25 15:29:22 +000033
Guido van Rossumac8a9f31997-09-30 19:05:50 +000034knownfiles = [
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +000035 "/etc/mime.types",
Thomas Wouters0e3f5912006-08-11 14:57:12 +000036 "/etc/httpd/mime.types", # Mac OS X
37 "/etc/httpd/conf/mime.types", # Apache
38 "/etc/apache/mime.types", # Apache 1
39 "/etc/apache2/mime.types", # Apache 2
Guido van Rossumac8a9f31997-09-30 19:05:50 +000040 "/usr/local/etc/httpd/conf/mime.types",
41 "/usr/local/lib/netscape/mime.types",
Fred Drake13a2c272000-02-10 17:17:14 +000042 "/usr/local/etc/httpd/conf/mime.types", # Apache 1.2
43 "/usr/local/etc/mime.types", # Apache 1.3
Guido van Rossumac8a9f31997-09-30 19:05:50 +000044 ]
45
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +000046inited = False
Guido van Rossumac8a9f31997-09-30 19:05:50 +000047
Fred Drakeeeee4ec2001-08-03 21:01:44 +000048
49class MimeTypes:
50 """MIME-types datastore.
51
52 This datastore can handle information from mime.types-style files
53 and supports basic determination of MIME type from a filename or
54 URL, and can guess a reasonable extension given a MIME type.
55 """
56
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +000057 def __init__(self, filenames=(), strict=True):
Fred Drakeeeee4ec2001-08-03 21:01:44 +000058 if not inited:
59 init()
60 self.encodings_map = encodings_map.copy()
61 self.suffix_map = suffix_map.copy()
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +000062 self.types_map = ({}, {}) # dict for (non-strict, strict)
63 self.types_map_inv = ({}, {})
64 for (ext, type) in types_map.items():
65 self.add_type(type, ext, True)
66 for (ext, type) in common_types.items():
67 self.add_type(type, ext, False)
Fred Drakeeeee4ec2001-08-03 21:01:44 +000068 for name in filenames:
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +000069 self.read(name, strict)
Fred Drakeeeee4ec2001-08-03 21:01:44 +000070
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +000071 def add_type(self, type, ext, strict=True):
Walter Dörwaldf0dfc7a2003-10-20 14:01:56 +000072 """Add a mapping between a type and an extension.
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +000073
74 When the extension is already known, the new
75 type will replace the old one. When the type
76 is already known the extension will be added
77 to the list of known extensions.
78
79 If strict is true, information will be added to
80 list of standard types, else to the list of non-standard
81 types.
82 """
83 self.types_map[strict][ext] = type
84 exts = self.types_map_inv[strict].setdefault(type, [])
85 if ext not in exts:
86 exts.append(ext)
87
88 def guess_type(self, url, strict=True):
Fred Drakeeeee4ec2001-08-03 21:01:44 +000089 """Guess the type of a file based on its URL.
90
91 Return value is a tuple (type, encoding) where type is None if
92 the type can't be guessed (no or unknown suffix) or a string
93 of the form type/subtype, usable for a MIME Content-type
94 header; and encoding is None for no encoding or the name of
95 the program used to encode (e.g. compress or gzip). The
96 mappings are table driven. Encoding suffixes are case
97 sensitive; type suffixes are first tried case sensitive, then
98 case insensitive.
99
100 The suffixes .tgz, .taz and .tz (case sensitive!) are all
101 mapped to '.tar.gz'. (This is table-driven too, using the
102 dictionary suffix_map.)
Barry Warsaw107771a2001-10-25 21:49:18 +0000103
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000104 Optional `strict' argument when False adds a bunch of commonly found,
Barry Warsaw107771a2001-10-25 21:49:18 +0000105 but non-standard types.
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000106 """
107 scheme, url = urllib.splittype(url)
108 if scheme == 'data':
109 # syntax of data URLs:
110 # dataurl := "data:" [ mediatype ] [ ";base64" ] "," data
111 # mediatype := [ type "/" subtype ] *( ";" parameter )
112 # data := *urlchar
113 # parameter := attribute "=" value
114 # type/subtype defaults to "text/plain"
115 comma = url.find(',')
116 if comma < 0:
117 # bad data URL
118 return None, None
119 semi = url.find(';', 0, comma)
120 if semi >= 0:
121 type = url[:semi]
122 else:
123 type = url[:comma]
124 if '=' in type or '/' not in type:
125 type = 'text/plain'
126 return type, None # never compressed, so encoding is None
127 base, ext = posixpath.splitext(url)
Raymond Hettinger54f02222002-06-01 14:18:47 +0000128 while ext in self.suffix_map:
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000129 base, ext = posixpath.splitext(base + self.suffix_map[ext])
Raymond Hettinger54f02222002-06-01 14:18:47 +0000130 if ext in self.encodings_map:
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000131 encoding = self.encodings_map[ext]
132 base, ext = posixpath.splitext(base)
133 else:
134 encoding = None
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000135 types_map = self.types_map[True]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000136 if ext in types_map:
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000137 return types_map[ext], encoding
Raymond Hettinger54f02222002-06-01 14:18:47 +0000138 elif ext.lower() in types_map:
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000139 return types_map[ext.lower()], encoding
Barry Warsaw107771a2001-10-25 21:49:18 +0000140 elif strict:
141 return None, encoding
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000142 types_map = self.types_map[False]
143 if ext in types_map:
144 return types_map[ext], encoding
145 elif ext.lower() in types_map:
146 return types_map[ext.lower()], encoding
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000147 else:
148 return None, encoding
149
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000150 def guess_all_extensions(self, type, strict=True):
151 """Guess the extensions for a file based on its MIME type.
152
153 Return value is a list of strings giving the possible filename
154 extensions, including the leading dot ('.'). The extension is not
Barry Warsaw9caa0d12003-06-09 22:27:41 +0000155 guaranteed to have been associated with any particular data stream,
156 but would be mapped to the MIME type `type' by guess_type().
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000157
158 Optional `strict' argument when false adds a bunch of commonly found,
159 but non-standard types.
160 """
161 type = type.lower()
162 extensions = self.types_map_inv[True].get(type, [])
163 if not strict:
164 for ext in self.types_map_inv[False].get(type, []):
165 if ext not in extensions:
166 extensions.append(ext)
Barry Warsaw9caa0d12003-06-09 22:27:41 +0000167 return extensions
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000168
169 def guess_extension(self, type, strict=True):
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000170 """Guess the extension for a file based on its MIME type.
171
172 Return value is a string giving a filename extension,
173 including the leading dot ('.'). The extension is not
174 guaranteed to have been associated with any particular data
175 stream, but would be mapped to the MIME type `type' by
176 guess_type(). If no extension can be guessed for `type', None
177 is returned.
Barry Warsaw107771a2001-10-25 21:49:18 +0000178
179 Optional `strict' argument when false adds a bunch of commonly found,
180 but non-standard types.
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000181 """
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000182 extensions = self.guess_all_extensions(type, strict)
Barry Warsaw9caa0d12003-06-09 22:27:41 +0000183 if not extensions:
184 return None
185 return extensions[0]
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000186
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000187 def read(self, filename, strict=True):
188 """
189 Read a single mime.types-format file, specified by pathname.
190
191 If strict is true, information will be added to
192 list of standard types, else to the list of non-standard
193 types.
194 """
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000195 fp = open(filename)
Walter Dörwald51cc72c2003-01-03 21:02:36 +0000196 self.readfp(fp, strict)
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000197 fp.close()
198
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000199 def readfp(self, fp, strict=True):
200 """
201 Read a single mime.types-format file.
202
203 If strict is true, information will be added to
204 list of standard types, else to the list of non-standard
205 types.
206 """
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000207 while 1:
Fred Drakec019ecb2001-08-16 15:54:28 +0000208 line = fp.readline()
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000209 if not line:
210 break
211 words = line.split()
212 for i in range(len(words)):
213 if words[i][0] == '#':
214 del words[i:]
215 break
216 if not words:
217 continue
218 type, suffixes = words[0], words[1:]
219 for suff in suffixes:
Walter Dörwald8fa89722003-01-03 21:06:46 +0000220 self.add_type(type, '.' + suff, strict)
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000221
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000222def guess_type(url, strict=True):
Guido van Rossumac8a9f31997-09-30 19:05:50 +0000223 """Guess the type of a file based on its URL.
224
225 Return value is a tuple (type, encoding) where type is None if the
226 type can't be guessed (no or unknown suffix) or a string of the
227 form type/subtype, usable for a MIME Content-type header; and
228 encoding is None for no encoding or the name of the program used
229 to encode (e.g. compress or gzip). The mappings are table
230 driven. Encoding suffixes are case sensitive; type suffixes are
231 first tried case sensitive, then case insensitive.
232
233 The suffixes .tgz, .taz and .tz (case sensitive!) are all mapped
234 to ".tar.gz". (This is table-driven too, using the dictionary
Fred Drake3130b7a1998-05-18 16:05:24 +0000235 suffix_map).
Barry Warsaw107771a2001-10-25 21:49:18 +0000236
237 Optional `strict' argument when false adds a bunch of commonly found, but
238 non-standard types.
Guido van Rossumac8a9f31997-09-30 19:05:50 +0000239 """
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000240 init()
Barry Warsaw107771a2001-10-25 21:49:18 +0000241 return guess_type(url, strict)
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000242
Guido van Rossumac8a9f31997-09-30 19:05:50 +0000243
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000244def guess_all_extensions(type, strict=True):
245 """Guess the extensions for a file based on its MIME type.
246
247 Return value is a list of strings giving the possible filename
248 extensions, including the leading dot ('.'). The extension is not
249 guaranteed to have been associated with any particular data
250 stream, but would be mapped to the MIME type `type' by
251 guess_type(). If no extension can be guessed for `type', None
252 is returned.
253
254 Optional `strict' argument when false adds a bunch of commonly found,
255 but non-standard types.
256 """
257 init()
258 return guess_all_extensions(type, strict)
259
260def guess_extension(type, strict=True):
Fred Drake5109ffd1998-05-18 16:27:20 +0000261 """Guess the extension for a file based on its MIME type.
262
263 Return value is a string giving a filename extension, including the
264 leading dot ('.'). The extension is not guaranteed to have been
Fred Drake49413411998-05-19 15:15:59 +0000265 associated with any particular data stream, but would be mapped to the
266 MIME type `type' by guess_type(). If no extension can be guessed for
267 `type', None is returned.
Barry Warsaw107771a2001-10-25 21:49:18 +0000268
269 Optional `strict' argument when false adds a bunch of commonly found,
270 but non-standard types.
Fred Drake5109ffd1998-05-18 16:27:20 +0000271 """
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000272 init()
Barry Warsaw107771a2001-10-25 21:49:18 +0000273 return guess_extension(type, strict)
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000274
Walter Dörwald893020b2003-12-19 18:15:10 +0000275def add_type(type, ext, strict=True):
Walter Dörwaldf0dfc7a2003-10-20 14:01:56 +0000276 """Add a mapping between a type and an extension.
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000277
278 When the extension is already known, the new
279 type will replace the old one. When the type
280 is already known the extension will be added
281 to the list of known extensions.
282
283 If strict is true, information will be added to
284 list of standard types, else to the list of non-standard
285 types.
286 """
287 init()
288 return add_type(type, ext, strict)
289
Fred Drake5109ffd1998-05-18 16:27:20 +0000290
Guido van Rossumac8a9f31997-09-30 19:05:50 +0000291def init(files=None):
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000292 global guess_all_extensions, guess_extension, guess_type
Barry Warsaw107771a2001-10-25 21:49:18 +0000293 global suffix_map, types_map, encodings_map, common_types
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000294 global add_type, inited
295 inited = True
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000296 db = MimeTypes()
297 if files is None:
298 files = knownfiles
299 for file in files:
300 if os.path.isfile(file):
301 db.readfp(open(file))
302 encodings_map = db.encodings_map
Fred Drakec81a0692001-08-16 18:14:38 +0000303 suffix_map = db.suffix_map
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000304 types_map = db.types_map[True]
305 guess_all_extensions = db.guess_all_extensions
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000306 guess_extension = db.guess_extension
307 guess_type = db.guess_type
Walter Dörwald5ccaf8f2002-09-06 16:15:58 +0000308 add_type = db.add_type
309 common_types = db.types_map[False]
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000310
Guido van Rossumac8a9f31997-09-30 19:05:50 +0000311
312def read_mime_types(file):
313 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000314 f = open(file)
Guido van Rossumac8a9f31997-09-30 19:05:50 +0000315 except IOError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000316 return None
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000317 db = MimeTypes()
Walter Dörwaldbb51ed32003-01-03 19:33:17 +0000318 db.readfp(f, True)
319 return db.types_map[True]
Fred Drakeeeee4ec2001-08-03 21:01:44 +0000320
Guido van Rossumac8a9f31997-09-30 19:05:50 +0000321
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000322def _default_mime_types():
323 global suffix_map
324 global encodings_map
325 global types_map
326 global common_types
Guido van Rossumac8a9f31997-09-30 19:05:50 +0000327
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000328 suffix_map = {
329 '.tgz': '.tar.gz',
330 '.taz': '.tar.gz',
331 '.tz': '.tar.gz',
Guido van Rossum360e4b82007-05-14 22:51:27 +0000332 '.tbz2': '.tar.bz2',
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000333 }
Guido van Rossumac8a9f31997-09-30 19:05:50 +0000334
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000335 encodings_map = {
336 '.gz': 'gzip',
337 '.Z': 'compress',
Guido van Rossum360e4b82007-05-14 22:51:27 +0000338 '.bz2': 'bzip2',
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000339 }
Barry Warsaw107771a2001-10-25 21:49:18 +0000340
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000341 # Before adding new types, make sure they are either registered with IANA,
342 # at http://www.isi.edu/in-notes/iana/assignments/media-types
343 # or extensions, i.e. using the x- prefix
Eric S. Raymond51cc3bc2001-02-09 09:44:47 +0000344
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000345 # If you add to these, please keep them sorted!
346 types_map = {
347 '.a' : 'application/octet-stream',
348 '.ai' : 'application/postscript',
349 '.aif' : 'audio/x-aiff',
350 '.aifc' : 'audio/x-aiff',
351 '.aiff' : 'audio/x-aiff',
352 '.au' : 'audio/basic',
353 '.avi' : 'video/x-msvideo',
354 '.bat' : 'text/plain',
355 '.bcpio' : 'application/x-bcpio',
356 '.bin' : 'application/octet-stream',
357 '.bmp' : 'image/x-ms-bmp',
358 '.c' : 'text/plain',
359 # Duplicates :(
360 '.cdf' : 'application/x-cdf',
361 '.cdf' : 'application/x-netcdf',
362 '.cpio' : 'application/x-cpio',
363 '.csh' : 'application/x-csh',
364 '.css' : 'text/css',
365 '.dll' : 'application/octet-stream',
366 '.doc' : 'application/msword',
367 '.dot' : 'application/msword',
368 '.dvi' : 'application/x-dvi',
369 '.eml' : 'message/rfc822',
370 '.eps' : 'application/postscript',
371 '.etx' : 'text/x-setext',
372 '.exe' : 'application/octet-stream',
373 '.gif' : 'image/gif',
374 '.gtar' : 'application/x-gtar',
375 '.h' : 'text/plain',
376 '.hdf' : 'application/x-hdf',
377 '.htm' : 'text/html',
378 '.html' : 'text/html',
379 '.ief' : 'image/ief',
380 '.jpe' : 'image/jpeg',
381 '.jpeg' : 'image/jpeg',
382 '.jpg' : 'image/jpeg',
383 '.js' : 'application/x-javascript',
384 '.ksh' : 'text/plain',
385 '.latex' : 'application/x-latex',
386 '.m1v' : 'video/mpeg',
387 '.man' : 'application/x-troff-man',
388 '.me' : 'application/x-troff-me',
389 '.mht' : 'message/rfc822',
390 '.mhtml' : 'message/rfc822',
391 '.mif' : 'application/x-mif',
392 '.mov' : 'video/quicktime',
393 '.movie' : 'video/x-sgi-movie',
394 '.mp2' : 'audio/mpeg',
395 '.mp3' : 'audio/mpeg',
396 '.mpa' : 'video/mpeg',
397 '.mpe' : 'video/mpeg',
398 '.mpeg' : 'video/mpeg',
399 '.mpg' : 'video/mpeg',
400 '.ms' : 'application/x-troff-ms',
401 '.nc' : 'application/x-netcdf',
402 '.nws' : 'message/rfc822',
403 '.o' : 'application/octet-stream',
404 '.obj' : 'application/octet-stream',
405 '.oda' : 'application/oda',
406 '.p12' : 'application/x-pkcs12',
407 '.p7c' : 'application/pkcs7-mime',
408 '.pbm' : 'image/x-portable-bitmap',
409 '.pdf' : 'application/pdf',
410 '.pfx' : 'application/x-pkcs12',
411 '.pgm' : 'image/x-portable-graymap',
412 '.pl' : 'text/plain',
413 '.png' : 'image/png',
414 '.pnm' : 'image/x-portable-anymap',
415 '.pot' : 'application/vnd.ms-powerpoint',
416 '.ppa' : 'application/vnd.ms-powerpoint',
417 '.ppm' : 'image/x-portable-pixmap',
418 '.pps' : 'application/vnd.ms-powerpoint',
419 '.ppt' : 'application/vnd.ms-powerpoint',
420 '.ps' : 'application/postscript',
421 '.pwz' : 'application/vnd.ms-powerpoint',
422 '.py' : 'text/x-python',
423 '.pyc' : 'application/x-python-code',
424 '.pyo' : 'application/x-python-code',
425 '.qt' : 'video/quicktime',
426 '.ra' : 'audio/x-pn-realaudio',
427 '.ram' : 'application/x-pn-realaudio',
428 '.ras' : 'image/x-cmu-raster',
429 '.rdf' : 'application/xml',
430 '.rgb' : 'image/x-rgb',
431 '.roff' : 'application/x-troff',
432 '.rtx' : 'text/richtext',
433 '.sgm' : 'text/x-sgml',
434 '.sgml' : 'text/x-sgml',
435 '.sh' : 'application/x-sh',
436 '.shar' : 'application/x-shar',
437 '.snd' : 'audio/basic',
438 '.so' : 'application/octet-stream',
439 '.src' : 'application/x-wais-source',
440 '.sv4cpio': 'application/x-sv4cpio',
441 '.sv4crc' : 'application/x-sv4crc',
442 '.swf' : 'application/x-shockwave-flash',
443 '.t' : 'application/x-troff',
444 '.tar' : 'application/x-tar',
445 '.tcl' : 'application/x-tcl',
446 '.tex' : 'application/x-tex',
447 '.texi' : 'application/x-texinfo',
448 '.texinfo': 'application/x-texinfo',
449 '.tif' : 'image/tiff',
450 '.tiff' : 'image/tiff',
451 '.tr' : 'application/x-troff',
452 '.tsv' : 'text/tab-separated-values',
453 '.txt' : 'text/plain',
454 '.ustar' : 'application/x-ustar',
455 '.vcf' : 'text/x-vcard',
456 '.wav' : 'audio/x-wav',
457 '.wiz' : 'application/msword',
458 '.wsdl' : 'application/xml',
459 '.xbm' : 'image/x-xbitmap',
460 '.xlb' : 'application/vnd.ms-excel',
461 # Duplicates :(
462 '.xls' : 'application/excel',
463 '.xls' : 'application/vnd.ms-excel',
464 '.xml' : 'text/xml',
465 '.xpdl' : 'application/xml',
466 '.xpm' : 'image/x-xpixmap',
467 '.xsl' : 'application/xml',
468 '.xwd' : 'image/x-xwindowdump',
469 '.zip' : 'application/zip',
470 }
Barry Warsaw107771a2001-10-25 21:49:18 +0000471
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000472 # These are non-standard types, commonly found in the wild. They will
473 # only match if strict=0 flag is given to the API methods.
474
475 # Please sort these too
476 common_types = {
477 '.jpg' : 'image/jpg',
478 '.mid' : 'audio/midi',
479 '.midi': 'audio/midi',
480 '.pct' : 'image/pict',
481 '.pic' : 'image/pict',
482 '.pict': 'image/pict',
483 '.rtf' : 'application/rtf',
484 '.xul' : 'text/xul'
485 }
486
487
488_default_mime_types()
Barry Warsaw107771a2001-10-25 21:49:18 +0000489
490
Eric S. Raymond51cc3bc2001-02-09 09:44:47 +0000491if __name__ == '__main__':
492 import sys
Barry Warsaw107771a2001-10-25 21:49:18 +0000493 import getopt
494
Fred Drake698da022001-12-05 15:58:29 +0000495 USAGE = """\
496Usage: mimetypes.py [options] type
497
498Options:
499 --help / -h -- print this message and exit
500 --lenient / -l -- additionally search of some common, but non-standard
501 types.
502 --extension / -e -- guess extension instead of type
503
504More than one type argument may be given.
505"""
506
507 def usage(code, msg=''):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000508 print(USAGE)
509 if msg: print(msg)
Fred Drake698da022001-12-05 15:58:29 +0000510 sys.exit(code)
511
Barry Warsaw107771a2001-10-25 21:49:18 +0000512 try:
513 opts, args = getopt.getopt(sys.argv[1:], 'hle',
514 ['help', 'lenient', 'extension'])
Guido van Rossumb940e112007-01-10 16:19:56 +0000515 except getopt.error as msg:
Barry Warsaw107771a2001-10-25 21:49:18 +0000516 usage(1, msg)
517
518 strict = 1
519 extension = 0
520 for opt, arg in opts:
521 if opt in ('-h', '--help'):
522 usage(0)
523 elif opt in ('-l', '--lenient'):
524 strict = 0
525 elif opt in ('-e', '--extension'):
526 extension = 1
527 for gtype in args:
528 if extension:
529 guess = guess_extension(gtype, strict)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000530 if not guess: print("I don't know anything about type", gtype)
531 else: print(guess)
Barry Warsaw107771a2001-10-25 21:49:18 +0000532 else:
533 guess, encoding = guess_type(gtype, strict)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000534 if not guess: print("I don't know anything about type", gtype)
535 else: print('type:', guess, 'encoding:', encoding)