source: trunk/essentials/dev-lang/python/Lib/mailcap.py@ 3393

Last change on this file since 3393 was 3225, checked in by bird, 19 years ago

Python 2.5

File size: 7.3 KB
Line 
1"""Mailcap file handling. See RFC 1524."""
2
3import os
4
5__all__ = ["getcaps","findmatch"]
6
7# Part 1: top-level interface.
8
9def getcaps():
10 """Return a dictionary containing the mailcap database.
11
12 The dictionary maps a MIME type (in all lowercase, e.g. 'text/plain')
13 to a list of dictionaries corresponding to mailcap entries. The list
14 collects all the entries for that MIME type from all available mailcap
15 files. Each dictionary contains key-value pairs for that MIME type,
16 where the viewing command is stored with the key "view".
17
18 """
19 caps = {}
20 for mailcap in listmailcapfiles():
21 try:
22 fp = open(mailcap, 'r')
23 except IOError:
24 continue
25 morecaps = readmailcapfile(fp)
26 fp.close()
27 for key, value in morecaps.iteritems():
28 if not key in caps:
29 caps[key] = value
30 else:
31 caps[key] = caps[key] + value
32 return caps
33
34def listmailcapfiles():
35 """Return a list of all mailcap files found on the system."""
36 # XXX Actually, this is Unix-specific
37 if 'MAILCAPS' in os.environ:
38 str = os.environ['MAILCAPS']
39 mailcaps = str.split(':')
40 else:
41 if 'HOME' in os.environ:
42 home = os.environ['HOME']
43 else:
44 # Don't bother with getpwuid()
45 home = '.' # Last resort
46 mailcaps = [home + '/.mailcap', '/etc/mailcap',
47 '/usr/etc/mailcap', '/usr/local/etc/mailcap']
48 return mailcaps
49
50
51# Part 2: the parser.
52
53def readmailcapfile(fp):
54 """Read a mailcap file and return a dictionary keyed by MIME type.
55
56 Each MIME type is mapped to an entry consisting of a list of
57 dictionaries; the list will contain more than one such dictionary
58 if a given MIME type appears more than once in the mailcap file.
59 Each dictionary contains key-value pairs for that MIME type, where
60 the viewing command is stored with the key "view".
61 """
62 caps = {}
63 while 1:
64 line = fp.readline()
65 if not line: break
66 # Ignore comments and blank lines
67 if line[0] == '#' or line.strip() == '':
68 continue
69 nextline = line
70 # Join continuation lines
71 while nextline[-2:] == '\\\n':
72 nextline = fp.readline()
73 if not nextline: nextline = '\n'
74 line = line[:-2] + nextline
75 # Parse the line
76 key, fields = parseline(line)
77 if not (key and fields):
78 continue
79 # Normalize the key
80 types = key.split('/')
81 for j in range(len(types)):
82 types[j] = types[j].strip()
83 key = '/'.join(types).lower()
84 # Update the database
85 if key in caps:
86 caps[key].append(fields)
87 else:
88 caps[key] = [fields]
89 return caps
90
91def parseline(line):
92 """Parse one entry in a mailcap file and return a dictionary.
93
94 The viewing command is stored as the value with the key "view",
95 and the rest of the fields produce key-value pairs in the dict.
96 """
97 fields = []
98 i, n = 0, len(line)