Properly encode filenames using RFC6266.

see #473
fixes #481
This commit is contained in:
Antoine Nguyen
2013-09-17 08:43:23 +02:00
parent 0faf4caa73
commit 5e87fc764c
6 changed files with 23 additions and 15 deletions
+1 -1
View File
@@ -804,7 +804,7 @@ def _export(content, filename):
resp = HttpResponse(content)
resp["Content-Type"] = "text/csv"
resp["Content-Length"] = len(content)
resp["Content-Disposition"] = 'attachment; filename="%s"' % filename
resp["Content-Disposition"] = build_header(filename)
return resp
+2 -1
View File
@@ -1,5 +1,6 @@
# coding: utf-8
from sievelib.managesieve import Error
from rfc6266 import build_header
from django.http import HttpResponse
from django.template.loader import render_to_string
from django.contrib.auth.decorators import login_required
@@ -263,7 +264,7 @@ def download_filters_set(request, name):
resp = HttpResponse(script)
resp["Content-Type"] = "text/plain; charset=utf-8"
resp["Content-Length"] = len(script)
resp["Content-Disposition"] = 'attachment; filename="%s.txt"' % name
resp["Content-Disposition"] = build_header('%s.txt' % name)
return resp
@login_required
+12 -7
View File
@@ -4,6 +4,7 @@ from datetime import datetime, timedelta
import email
import lxml
import chardet
from rfc6266 import build_header, parse_headers
from django.core.files.uploadhandler import FileUploadHandler, SkipFile
from django.utils.translation import ugettext as _, ugettext_lazy
@@ -277,20 +278,24 @@ class ImapEmail(Email):
attname = "part_%s" % att["pnum"]
params = None
key = None
if att.has_key("params") and att["params"] != "NIL":
if "params" in att and att["params"] != "NIL":
params = att["params"]
key = "name"
if key is None and \
att.has_key("disposition") and len(att["disposition"]) > 1:
if key is None and "disposition" in att and len(att["disposition"]) > 1:
params = att["disposition"][1]
key = "filename"
if key and params:
for pos, value in enumerate(params):
if value == key:
if not value.startswith(key):
continue
header = "%s; %s=%s" % (att['disposition'][0], value,
u2u_decode.u2u_decode(params[pos + 1]).strip("\r\t\n"))
attname = parse_headers(header).filename_unsafe
if attname is None:
attname = u2u_decode.u2u_decode(params[pos + 1]).strip("\r\t\n")
break
break
self.attachments[att["pnum"]] = attname
def _fetch_inlines(self):
@@ -302,7 +307,7 @@ class ImapEmail(Email):
params["fname"] = os.path.join(settings.MEDIA_URL, fname)
if os.path.exists(path):
continue
pdef, content = self.imapc.fetchpart(self.mailid, self.mbox, params["pnum"])
fp = open(path, "wb")
fp.write(decode_payload(params["encoding"], content))
@@ -613,7 +618,7 @@ def create_mail_attachment(attdef):
res.set_payload(fp.read())
fp.close()
Encoders.encode_base64(res)
res.add_header("Content-Disposition", 'attachment', filename=attdef["fname"])
res['Content-Disposition'] = build_header(attdef['fname'].decode('utf-8'))
return res
+4 -3
View File
@@ -43,16 +43,17 @@ def getattachment(request):
resp = HttpResponse(decode_payload(partdef["encoding"], payload))
resp["Content-Type"] = partdef["Content-Type"]
resp["Content-Transfer-Encoding"] = partdef["encoding"]
print partdef
if partdef["disposition"] != 'NIL':
disp = partdef["disposition"]
# FIXME : ugly hack, see fetch_parser.py for more explanation
# :p
if type(disp[1][0]) != dict:
cd = '%s; %s="%s"' % (disp[0], disp[1][0], disp[1][1])
cd = '%s; %s=%s' % (disp[0], disp[1][0], disp[1][1])
else:
cd = '%s; %s="%s"' % (disp[0], disp[1][0]['struct'][0], disp[1][0]['struct'][1])
cd = '%s; %s=%s' % (disp[0], disp[1][0]['struct'][0], disp[1][0]['struct'][1])
else:
cd = 'attachment; filename="%s"' % request.GET["fname"]
cd = build_header(request.GET["fname"])
resp["Content-Disposition"] = cd
resp["Content-Length"] = partdef["size"]
return resp
+3 -3
View File
@@ -79,15 +79,15 @@ class Email(object):
must be displayed and not attached.
"""
if self.dformat == "html" and self.links \
and msg.has_key("Content-Disposition"):
and "Content-Disposition" in msg:
if msg["Content-Disposition"].startswith("inline"):
cid = None
if msg.has_key("Content-ID"):
if "Content-ID" in msg:
m = re.match("<(.+)>", msg["Content-ID"])
cid = m is not None and m.group(1) or msg["Content-ID"]
fname = msg.get_filename()
if fname is None:
if msg.has_key("Content-Location"):
if "Content-Location" in msg:
fname = msg["Content-Location"]
elif cid is not None:
fname = cid
+1
View File
@@ -6,3 +6,4 @@ pycrypto
sievelib
chardet
argparse
rfc6266