]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Initial revision
authorGuido van Rossum <guido@python.org>
Sat, 30 Sep 1995 16:52:24 +0000 (16:52 +0000)
committerGuido van Rossum <guido@python.org>
Sat, 30 Sep 1995 16:52:24 +0000 (16:52 +0000)
Lib/mailcap.py [new file with mode: 0644]

diff --git a/Lib/mailcap.py b/Lib/mailcap.py
new file mode 100644 (file)
index 0000000..9da57d7
--- /dev/null
@@ -0,0 +1,223 @@
+# Mailcap file handling.  See RFC 1524.
+
+import os
+import string
+import tempfile
+
+
+# Part 1: top-level interface.
+
+def getcaps():
+    caps = {}
+    for mailcap in listmailcapfiles():
+       try:
+           fp = open(mailcap, 'r')
+       except:
+           continue
+       morecaps = readmailcapfile(fp)
+       fp.close()
+       for key in morecaps.keys():
+           if not caps.has_key(key):
+               caps[key] = morecaps[key]
+           else:
+               caps[key] = caps[key] + morecaps[key]
+    return caps
+
+def listmailcapfiles():
+    # XXX Actually, this is Unix-specific
+    if os.environ.has_key('MAILCAPS'):
+       str = os.environ['MAILCAPS']
+       mailcaps = string.splitfields(str, ':')
+    else:
+       if os.environ.has_key('HOME'):
+           home = os.environ['HOME']
+       else:
+           # Don't bother with getpwuid()
+           home = '.' # Last resort
+       mailcaps = [home + '/.mailcap', '/etc/mailcap',
+               '/usr/etc/mailcap', '/usr/local/etc/mailcap']
+    return mailcaps
+
+
+# Part 2: the parser.
+
+def readmailcapfile(fp):
+    caps = {}
+    while 1:
+       line = fp.readline()
+       if not line: break
+       # Ignore comments and blank lines
+       if line[0] == '#' or string.strip(line) == '':
+           continue
+       nextline = line
+       # Join continuation lines
+       while nextline[-2:] == '\\\n':
+           nextline = fp.readline()
+           if not nextline: nextline = '\n'
+           line = line[:-2] + nextline
+       # Parse the line
+       key, fields = parseline(line)
+       if not (key and fields):
+           cotinue
+       # Normalize the key
+       types = string.splitfields(key, '/')
+       for j in range(len(types)):
+           types[j] = string.strip(types[j])
+       key = string.lower(string.joinfields(types, '/'))
+       # Update the database
+       if caps.has_key(key):
+           caps[key].append(fields)
+       else:
+           caps[key] = [fields]
+    return caps
+
+def parseline(line):
+    fields = []
+    i, n = 0, len(line)
+    while i < n:
+       field, i = parsefield(line, i, n)
+       fields.append(field)
+       i = i+1 # Skip semicolon
+    if len(fields) < 2:
+       return None, None
+    key, view, rest = fields[0], fields[1], fields[2:]
+    fields = {'view': view}
+    for field in rest:
+       i = string.find(field, '=')
+       if i < 0:
+           fkey = field
+           fvalue = ""
+       else:
+           fkey = string.strip(field[:i])
+           fvalue = string.strip(field[i+1:])
+       if fields.has_key(fkey):
+           # Ignore it
+           pass
+       else:
+           fields[fkey] = fvalue
+    return key, fields
+
+def parsefield(line, i, n):
+    start = i
+    while i < n:
+       c = line[i]
+       if c == ';':
+           break
+       elif c == '\\':
+           i = i+2
+       else:
+           i = i+1
+    return string.strip(line[start:i]), i
+
+
+# Part 3: using the database.
+
+def findmatch(caps, type, key='view', filename="/dev/null", plist=[]):
+    entries = lookup(caps, type, key)
+    for e in entries:
+       if e.has_key('test'):
+           test = subst(e['test'], filename, plist)
+           if test and os.system(test) != 0:
+               continue
+       command = subst(e[key], type, filename, plist)
+       return command, e
+    return None, None
+
+def lookup(caps, type, key=None):
+    entries = []
+    if caps.has_key(type):
+       entries = entries + caps[type]
+    types = string.splitfields(type, '/')
+    type = types[0] + '/*'
+    if caps.has_key(type):
+       entries = entries + caps[type]
+    if key is not None:
+       entries = filter(lambda e, key=key: e.has_key(key), entries)
+    return entries
+
+def subst(field, type, filename, plist=[]):
+    # XXX Actually, this is Unix-specific
+    res = ''
+    i, n = 0, len(field)
+    while i < n:
+       c = field[i]; i = i+1
+       if c <> '%':
+           if c == '\\':
+               c = field[i:i+1]; i = i+1
+           res = res + c
+       else:
+           c = field[i]; i = i+1
+           if c == '%':
+               res = res + c
+           elif c == 's':
+               res = res + filename
+           elif c == 't':
+               res = res + type
+           elif c == '{':
+               start = i
+               while i < n and field[i] <> '}':
+                   i = i+1
+               name = field[start:i]
+               i = i+1
+               res = res + findparam(name, plist)
+           # XXX To do:
+           # %n == number of parts if type is multipart/*
+           # %F == list of alternating type and filename for parts
+           else:
+               res = res + '%' + c
+    return res
+
+def findparam(name, plist):
+    name = string.lower(name) + '='
+    n = len(name)
+    for p in plist:
+       if string.lower(p[:n]) == name:
+           return p[n:]
+    return ''
+
+
+# Part 4: test program.
+
+def test():
+    import sys
+    caps = getcaps()
+    if not sys.argv[1:]:
+       show(caps)
+       return
+    for i in range(1, len(sys.argv), 2):
+       args = sys.argv[i:i+2]
+       if len(args) < 2:
+           print "usage: mailcap [type file] ..."
+           return
+       type = args[0]
+       file = args[1]
+       command, e = findmatch(caps, type, 'view', file)
+       if not command:
+           print "No viewer found for", type
+       else:
+           print "Executing:", command
+           sts = os.system(command)
+           if sts:
+               print "Exit status:", sts
+
+def show(caps):
+    print "Mailcap files:"
+    for fn in listmailcapfiles(): print "\t" + fn
+    print
+    if not caps: caps = getcaps()
+    print "Mailcap entries:"
+    print
+    ckeys = caps.keys()
+    ckeys.sort()
+    for type in ckeys:
+       print type
+       entries = caps[type]
+       for e in entries:
+           keys = e.keys()
+           keys.sort()
+           for k in keys:
+               print "  %-15s" % k, e[k]
+           print
+
+if __name__ == '__main__':
+    test()