Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Build] Prevent usage of twisted>=24 #468

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

mhertz
Copy link
Contributor

@mhertz mhertz commented Oct 28, 2024

Breaking ability of adding multiple torrents at once in WebUI, with following error in web-console after pressing 'Add':

deluge-all.js:7 Uncaught TypeError: Cannot read properties of undefined (reading 'filename')
    at S.getFilename (deluge-all.js:7:1946)
    at S.<anonymous> (deluge-all.js:3:2013)
    at Ext.util.MixedCollection.each (ext-all.js:21:111850)
    at constructor.each (ext-all.js:21:321534)
    at S.onAddClick (deluge-all.js:3:1932)
    at S.onClick (ext-all.js:21:426947)
    at HTMLTableElement.I (ext-all.js:21:57750)

The issue stems from only one of the torrents getting uploaded to server, after cgi.parse_multipart was removed from twisted.web.http and replaced with email.message_from_bytes, in there commit 4579398.

Note, there's currently a twisted draft PR replacing email.message* with 'multipart' lib, as seemingly better fitted/faster, and which coincidentally also is fixing our issue.

Avoids breaking ability of adding multiple torrents at once in WebUI.
@cas--
Copy link
Member

cas-- commented Feb 2, 2025

Can you provide an example of the problem? Why can't we handle this in the web server code?

Edit1: I cannot replicate, however I think there is an issue with adding multiple torrent files in the file picker which would suggest a problem in the frontend js code rather than server side

Edit2: Ah so I wasn't actually switching Twisted to an earlier version so I can see it now

@cas--
Copy link
Member

cas-- commented Feb 2, 2025

Okay I can see the problem now. The content-disposition of the file upload form is using the same name for both files.

Sample snippet of request

Content-Disposition: form-data; name="file"; filename="test1.torrent"
Content-Type: application/x-bittorrent
...
Content-Disposition: form-data; name="file"; filename="tes2.torrent"
Content-Type: application/x-bittorrent

From mdn web docs there is a suggestion that this is a valid when using the multiple attribute:

When dealing with multiple files in the same field (for example, the multiple attribute of an element), there can be several subparts with the same name.

I think the only fix is to override the _getMultiPartArgs with our own version:

+from collections import defaultdict
 import fnmatch
 import json
 import logging
@@ -40,7 +41,7 @@ def _getMultiPartArgs(content: bytes, ctype: bytes) -> dict[bytes, list[bytes]]:
     """
     Parse the content of a multipart/form-data request.
     """
-    result = {}
+    result = defaultdict(list)
     multiPartHeaders = b'MIME-Version: 1.0\r\n' + b'Content-Type: ' + ctype + b'\r\n'
     msg = message_from_bytes(multiPartHeaders + content)
 
@@ -56,7 +57,7 @@ def _getMultiPartArgs(content: bytes, ctype: bytes) -> dict[bytes, list[bytes]]:
             continue
 
         payload: bytes = part.get_payload(decode=True)  # type:ignore[assignment]
-        result[name.encode('utf8')] = [payload]
+        result[name.encode('utf8')].append(payload)
     return result

Created Twisted Issue/PR: twisted/twisted#12423

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants