Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions Src/StdLib/Lib/mailcap.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
"""Mailcap file handling. See RFC 1524."""

import os
import warnings
import re

__all__ = ["getcaps","findmatch"]

_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search

class UnsafeMailcapInput(Warning):
"""Warning raised when refusing unsafe input"""

# Part 1: top-level interface.

def getcaps():
Expand Down Expand Up @@ -149,10 +156,13 @@ def findmatch(caps, MIMEtype, key='view', filename="/dev/null", plist=[]):
for e in entries:
if 'test' in e:
test = subst(e['test'], filename, plist)
if test is None:
continue
if test and os.system(test) != 0:
continue
command = subst(e[key], MIMEtype, filename, plist)
return command, e
if command is not None:
return command, e
return None, None

def lookup(caps, MIMEtype, key=None):
Expand Down Expand Up @@ -184,14 +194,23 @@ def subst(field, MIMEtype, filename, plist=[]):
elif c == 's':
res = res + filename
elif c == 't':
if _find_unsafe(MIMEtype):
msg = "Refusing to substitute MIME type %r into a shell command." % (MIMEtype,)
warnings.warn(msg, UnsafeMailcapInput)
return None
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)
param = findparam(name, plist)
if _find_unsafe(param):
msg = "Refusing to substitute parameter %r (%s) into a shell command" % (param, name)
warnings.warn(msg, UnsafeMailcapInput)
return None
res = res + param
# XXX To do:
# %n == number of parts if type is multipart/*
# %F == list of alternating type and filename for parts
Expand Down