Download file may corrupt if filename not encode correctly in Content-Disposition header for some web browser;

diff -r 6278b366fb32 MoinMoin/Page.py
--- a/MoinMoin/Page.py	Wed Nov 19 10:25:26 2008 +0800
+++ b/MoinMoin/Page.py	Wed Nov 19 10:25:28 2008 +0800
@@ -1047,6 +1047,7 @@
                 # TODO: fix the encoding here, plain 8 bit is not allowed according to the RFCs
                 # There is no solution that is compatible to IE except stripping non-ascii chars
                 filename_enc = "%s.txt" % self.page_name.encode(config.charset)
+                filename_enc = wikiutil.content_disposition_encode(filename_enc, request)
                 request.setHttpHeader('Content-Disposition: %s; filename="%s"' % (
                                       content_disposition, filename_enc))
         else:
diff -r 6278b366fb32 MoinMoin/action/AttachFile.py
--- a/MoinMoin/action/AttachFile.py	Wed Nov 19 10:25:26 2008 +0800
+++ b/MoinMoin/action/AttachFile.py	Wed Nov 19 10:25:28 2008 +0800
@@ -872,7 +872,7 @@
             'Content-Type: %s' % content_type,
             'Last-Modified: %s' % timestamp,
             'Content-Length: %d' % os.path.getsize(fpath),
-            'Content-Disposition: %s; filename="%s"' % (content_dispo, filename_enc),
+            'Content-Disposition: %s; filename="%s"' % (content_dispo, wikiutil.content_disposition_encode(filename_enc, request)),
         ])
 
         # send data
diff -r 6278b366fb32 MoinMoin/action/backup.py
--- a/MoinMoin/action/backup.py	Wed Nov 19 10:25:26 2008 +0800
+++ b/MoinMoin/action/backup.py	Wed Nov 19 10:25:28 2008 +0800
@@ -39,7 +39,7 @@
     filename = "%s-%s.tar.%s" % (request.cfg.siteid, dateStamp, request.cfg.backup_compression)
     request.emit_http_headers([
         'Content-Type: application/octet-stream',
-        'Content-Disposition: inline; filename="%s"' % filename, ])
+        'Content-Disposition: inline; filename="%s"' % wikiutil.content_disposition_encode(filename, request), ])
 
     tar = tarfile.open(fileobj=request, mode="w|%s" % request.cfg.backup_compression)
     # allow GNU tar's longer file/pathnames
diff -r 6278b366fb32 MoinMoin/action/cache.py
--- a/MoinMoin/action/cache.py	Wed Nov 19 10:25:26 2008 +0800
+++ b/MoinMoin/action/cache.py	Wed Nov 19 10:25:28 2008 +0800
@@ -154,7 +154,7 @@
         # TODO: fix the encoding here, plain 8 bit is not allowed according to the RFCs
         # There is no solution that is compatible to IE except stripping non-ascii chars
         filename = filename.encode(config.charset)
-        headers.append('Content-Disposition: %s; filename="%s"' % (content_disposition, filename))
+        headers.append('Content-Disposition: %s; filename="%s"' % (content_disposition, wikiutil.content_disposition_encode(filename, request)))
 
     meta_cache = caching.CacheEntry(request, cache_arena, key+'.meta', cache_scope, do_locking=do_locking, use_pickle=True)
     meta_cache.update({
diff -r 6278b366fb32 MoinMoin/wikiutil.py
--- a/MoinMoin/wikiutil.py	Wed Nov 19 10:25:26 2008 +0800
+++ b/MoinMoin/wikiutil.py	Wed Nov 19 10:25:28 2008 +0800
@@ -2624,3 +2624,46 @@
                           ( authtype == 'w' and user.may.write(pagename) ) ) ):
                 return "( " + _("Permission denied for macro: %s")% macro_name + " )";
     return None
+
+def content_disposition_encode(text,request=None):
+    """
+    UTF filename in Content-Disposition:
+        IE: failed to download
+        Chrome: wront filename
+        FF: works. (Firefox,Epiphany,Iceweasel,Iceape,Galeon)
+        Opera: works.
+        Safari: wrong filename
+    URL encode filename in Content-Disposition:
+        IE: works.
+        Chrome: works.
+        FF: wrong filename. (Firefox,Epiphany,Iceweasel,Iceape,Galeon)
+        Opera: wrong filename
+        Safari: wrong filename
+    """
+    if isinstance(text, unicode):
+        text = text.encode('utf-8')
+    do_url_encode = None
+    if request:
+        ua = request.http_user_agent
+        ## browsers shoud url encode: MSIE, Chrome
+        for browser in ["MSIE",
+                        "Chrome"]:
+            if browser in ua:
+                do_url_encode = True
+        ## should NOT url encode: Firefox, Opera
+        if do_url_encode is None:
+            for browser in ["Opera",
+                            "Firefox",
+                            "Epiphany",
+                            "Iceweasel",
+                            "Iceape",
+                            "Galeon",]:
+                if browser in ua:
+                    do_url_encode = False
+        # should convert to OS's charset.
+        if do_url_encode is None and "Safari" in ua:
+            do_url_encode = False
+
+    if do_url_encode:
+        text = urllib.quote(text)
+    return text
