117 lines
4.8 KiB
Diff
117 lines
4.8 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Mamoru TASAKA <mtasaka@fedoraproject.org>
|
|
Date: Thu, 29 Aug 2024 15:31:25 +0900
|
|
Subject: [PATCH] [UI] Replace deprecated cgi module with email
|
|
|
|
As PEP 594 says, cgi module is marked as deprecated
|
|
in python 3.11, and will be removed in 3.13
|
|
(actually removed at least in 3.13 rc1).
|
|
|
|
As suggested on PEP 594, replace cgi.parse_header
|
|
with email.message.EmailMessage introduced in python 3.6.
|
|
|
|
Updated test modify test_download_with_rename_sanitised
|
|
- With RFC2045 specification, Content-Disposition filenames
|
|
parameter containing slash (directory separator) must be
|
|
quoted, so changing as such.
|
|
|
|
Ref: https://peps.python.org/pep-0594/#deprecated-modules
|
|
Ref: https://peps.python.org/pep-0594/#cgi
|
|
|
|
Closes: https://github.com/deluge-torrent/deluge/pull/462
|
|
---
|
|
deluge/httpdownloader.py | 14 +++++++++-----
|
|
deluge/tests/test_httpdownloader.py | 4 ++--
|
|
deluge/ui/web/json_api.py | 6 ++++--
|
|
3 files changed, 15 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/deluge/httpdownloader.py b/deluge/httpdownloader.py
|
|
index 700ade06bfd5..c19e3aa7ed1c 100644
|
|
--- a/deluge/httpdownloader.py
|
|
+++ b/deluge/httpdownloader.py
|
|
@@ -6,7 +6,7 @@
|
|
# See LICENSE for more details.
|
|
#
|
|
|
|
-import cgi
|
|
+import email.message
|
|
import logging
|
|
import os.path
|
|
import zlib
|
|
@@ -133,26 +133,30 @@ def request_callback(self, response):
|
|
content_disp = headers.getRawHeaders(b'content-disposition')[0].decode(
|
|
'utf-8'
|
|
)
|
|
- content_disp_params = cgi.parse_header(content_disp)[1]
|
|
- if 'filename' in content_disp_params:
|
|
- new_file_name = content_disp_params['filename']
|
|
+ message = email.message.EmailMessage()
|
|
+ message['content-disposition'] = content_disp
|
|
+ new_file_name = message.get_filename()
|
|
+ if new_file_name:
|
|
new_file_name = sanitise_filename(new_file_name)
|
|
new_file_name = os.path.join(
|
|
os.path.split(self.filename)[0], new_file_name
|
|
)
|
|
|
|
count = 1
|
|
fileroot = os.path.splitext(new_file_name)[0]
|
|
fileext = os.path.splitext(new_file_name)[1]
|
|
while os.path.isfile(new_file_name):
|
|
# Increment filename if already exists
|
|
new_file_name = f'{fileroot}-{count}{fileext}'
|
|
count += 1
|
|
|
|
self.filename = new_file_name
|
|
|
|
cont_type_header = headers.getRawHeaders(b'content-type')[0].decode()
|
|
- cont_type, params = cgi.parse_header(cont_type_header)
|
|
+ message = email.message.EmailMessage()
|
|
+ message['content-type'] = cont_type_header
|
|
+ cont_type = message.get_content_type()
|
|
+ params = message['content-type'].params
|
|
# Only re-ecode text content types.
|
|
encoding = None
|
|
if cont_type.startswith('text/'):
|
|
diff --git a/deluge/tests/test_httpdownloader.py b/deluge/tests/test_httpdownloader.py
|
|
index 8c491b68ad9f..96f740d2e5b5 100644
|
|
--- a/deluge/tests/test_httpdownloader.py
|
|
+++ b/deluge/tests/test_httpdownloader.py
|
|
@@ -212,10 +212,10 @@ async def test_download_with_rename_exists(self):
|
|
|
|
@pytest_twisted.ensureDeferred
|
|
async def test_download_with_rename_sanitised(self):
|
|
- url = self.get_url('rename?filename=/etc/passwd')
|
|
+ url = self.get_url('rename?filename="/etc/passwd"')
|
|
filename = await download_file(url, fname('original'))
|
|
assert filename == fname('passwd')
|
|
- self.assert_contains(filename, 'This file should be called /etc/passwd')
|
|
+ self.assert_contains(filename, 'This file should be called "/etc/passwd"')
|
|
|
|
@pytest_twisted.ensureDeferred
|
|
async def test_download_with_attachment_no_filename(self):
|
|
diff --git a/deluge/ui/web/json_api.py b/deluge/ui/web/json_api.py
|
|
index 3f256140e521..f148ac569cb0 100644
|
|
--- a/deluge/ui/web/json_api.py
|
|
+++ b/deluge/ui/web/json_api.py
|
|
@@ -6,7 +6,7 @@
|
|
# See LICENSE for more details.
|
|
#
|
|
|
|
-import cgi
|
|
+import email.message
|
|
import json
|
|
import logging
|
|
import os
|
|
@@ -191,7 +191,9 @@ def _on_json_request(self, request):
|
|
Handler to take the json data as a string and pass it on to the
|
|
_handle_request method for further processing.
|
|
"""
|
|
- content_type, _ = cgi.parse_header(request.getHeader(b'content-type').decode())
|
|
+ message = email.message.EmailMessage()
|
|
+ message['content-type'] = request.getHeader(b'content-type').decode()
|
|
+ content_type = message.get_content_type()
|
|
if content_type != 'application/json':
|
|
message = 'Invalid JSON request content-type: %s' % content_type
|
|
raise JSONException(message)
|