Skip to content

Commit ad06a02

Browse files
authored
Merge pull request #1994 from roland-ruedenauer/fix-file-upload-in-modify-form
Modify form: make loading content from file upload work
2 parents 72072fa + d72be05 commit ad06a02

File tree

2 files changed

+31
-12
lines changed

2 files changed

+31
-12
lines changed

src/moin/items/__init__.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,10 +1591,22 @@ def do_modify(self, item_may=None):
15911591

15921592
form = self.ModifyForm.from_request(request)
15931593
meta, data, contenttype_guessed, comment = form._dump(self)
1594-
if contenttype_guessed:
1595-
m = re.search("charset=(.+?)($|;)", contenttype_guessed)
1596-
if m:
1597-
data = str(data, m.group(1))
1594+
if data is not None:
1595+
if not isinstance(data, (str, bytes)):
1596+
data = data.read()
1597+
if isinstance(data, bytes):
1598+
encoding = "utf-8"
1599+
if contenttype_guessed:
1600+
if m := re.search("charset=(.+?)($|;)", contenttype_guessed):
1601+
encoding = m.group(1)
1602+
try:
1603+
data = str(data, encoding)
1604+
except ValueError:
1605+
flash(_("Invalid data content received. Expecting text content."), "error")
1606+
data = ""
1607+
if not isinstance(data, str):
1608+
abort(422, description="invalid content")
1609+
15981610
state = dict(fqname=self.fqname, itemid=meta.get(ITEMID), meta=meta)
15991611
if form.validate(state):
16001612
if request.values.get("preview"):
@@ -1609,6 +1621,9 @@ def do_modify(self, item_may=None):
16091621
else: # TODO: make preview button inactive for empty items, see #1539
16101622
flash(_("No preview available for empty items."), "error")
16111623
close_file(old_item.rev.data)
1624+
# update content form text data if data originated from a file upload
1625+
if data and form["content_form"]["data_file"]:
1626+
form["content_form"]["data_text"] = data
16121627
else:
16131628
# user clicked OK/Save button, check for conflicts,
16141629
if "charset" in self.contenttype:

src/moin/utils/edit_locking.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
To stress-test edit locking, use the Locust-based tests in /contrib/loadtesting/.
3131
"""
3232

33+
from __future__ import annotations
34+
3335
import os
3436
import time
3537
import sqlite3
@@ -145,7 +147,7 @@ def get_user_name(self):
145147
user_name = request.remote_user or request.remote_addr
146148
return user_name
147149

148-
def put_draft(self, data_in, overwrite=True):
150+
def put_draft(self, data_in: str | None, overwrite: bool = True) -> None:
149151
"""
150152
Only 1 item draft is saved per user. Most recent item draft overlays prior item draft.
151153
@@ -159,7 +161,7 @@ def put_draft(self, data_in, overwrite=True):
159161
"""
160162
rev_id = self.rev_id
161163
draft_rev_number = self.rev_number
162-
draft, data = self.get_draft()
164+
draft, _ = self.get_draft()
163165
if draft:
164166
# draft may be of this item or remnant of a prior abandoned edit
165167
u_name, i_id, i_name, rev_number, save_time, i_rev_id = draft
@@ -170,22 +172,24 @@ def put_draft(self, data_in, overwrite=True):
170172
draft_rev_number = rev_number # XXX per line 1074 in __init__
171173
rev_id = i_rev_id
172174
self.draft_name = self.make_draft_name(rev_id)
173-
self.cursor.execute("""DELETE FROM editdraft WHERE user_name = ? """, (self.user_name,))
175+
self.cursor.execute("""DELETE FROM editdraft WHERE user_name = ?""", (self.user_name,))
176+
174177
if data_in:
175-
data_in = data_in.encode(self.coding)
178+
data = data_in.encode(self.coding)
176179
with open(self.draft_name, "wb") as f:
177-
f.write(data_in)
180+
f.write(data)
178181
save_time = int(time.time())
179182
else:
180183
save_time = 0 # indicates user is editing item but has not done a preview, no draft has been saved
184+
181185
self.cursor.execute(
182186
"""INSERT INTO editdraft(user_name, item_id, item_name, rev_number, save_time, rev_id)
183187
VALUES(?,?,?,?,?,?)""",
184188
(self.user_name, self.item_id, self.item_name, draft_rev_number, save_time, rev_id),
185189
)
186190
self.conn.commit()
187191

188-
def get_draft(self):
192+
def get_draft(self) -> tuple[sqlite3.Row, str] | tuple[sqlite3.Row, None] | tuple[None, None]:
189193
"""
190194
Return None, None if no draft available; else tuple of row fields, textarea data or None.
191195
@@ -205,8 +209,8 @@ def get_draft(self):
205209
try:
206210
with open(self.draft_name, "rb") as f:
207211
data = f.read()
208-
data = data.decode(self.coding)
209-
return draft, data
212+
content = data.decode(self.coding)
213+
return draft, content
210214
except OSError:
211215
logging.error(f"User {u_name} failed to load draft for: {i_name}")
212216
return draft, None

0 commit comments

Comments
 (0)