--- /usr/lib/python2.7/mailcap.py 2015-10-14 19:33:25.000000000 +0200 +++ mailcap_patch.py 2015-10-28 17:52:46.382271980 +0100 @@ -1,9 +1,22 @@ """Mailcap file handling. See RFC 1524.""" import os +import subprocess +try: + from shlex import quote +except ImportError: + from pipes import quote __all__ = ["getcaps","findmatch"] +def run(cmd): + try: + p = subprocess.Popen(cmd) + p.communicate() + except: + pass + return p.returncode + # Part 1: top-level interface. def getcaps(): @@ -136,7 +149,7 @@ # Part 3: using the database. def findmatch(caps, MIMEtype, key='view', filename="/dev/null", plist=[]): - """Find a match for a mailcap entry. + """Find a match (string) for a mailcap entry. Return a tuple containing the command line, and the mailcap entry used; (None, None) if no match is found. This may invoke the @@ -144,15 +157,22 @@ entry to use. """ + command, e = findmatch_list(caps, MIMEtype, key, filename, plist) + if command: + command = ' '.join(command) + return command, e + +def findmatch_list(caps, MIMEtype, key='view', filename="/dev/null", plist=[]): + """Find a match [list] for a mailcap entry.""" entries = lookup(caps, MIMEtype, key) # XXX This code should somehow check for the needsterminal flag. for e in entries: if 'test' in e: - test = subst(e['test'], filename, plist) - if test and os.system(test) != 0: + test = subst(e['test'], MIMEtype, filename, plist) + if test and run(test) != 0: continue - command = subst(e[key], MIMEtype, filename, plist) - return command, e + cmd_list = subst(e[key], MIMEtype, filename, plist) + return cmd_list, e return None, None def lookup(caps, MIMEtype, key=None): @@ -168,46 +188,27 @@ return entries def subst(field, MIMEtype, 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 + MIMEtype - 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 + display='' + if 'DISPLAY' in os.environ: + display = os.environ['DISPLAY'] # 'test -n "$DISPLAY"' + if field : + res = field.split() + n = len(res) + if n > 0: + for i in range(n): + c = res[i] + c = c.replace("$DISPLAY", display) + c = c.replace("'%s'" , quote(filename)) + c = c.replace('%s' , quote(filename)) + c = c.replace('%t' , MIMEtype) + for pl in plist: + if '=' in pl: + name = '%{' + pl.split('=')[0].lower() + '}' + para = pl.split('=')[1] + c = c.replace(name, para) + res[i] = c return res -def findparam(name, plist): - name = name.lower() + '=' - n = len(name) - for p in plist: - if p[:n].lower() == name: - return p[n:] - return '' - - # Part 4: test program. def test(): @@ -223,12 +224,12 @@ return MIMEtype = args[0] file = args[1] - command, e = findmatch(caps, MIMEtype, 'view', file) + command, e = findmatch_list(caps, MIMEtype, 'view', file) if not command: print "No viewer found for", type else: print "Executing:", command - sts = os.system(command) + sts = run(command) if sts: print "Exit status:", sts