Skip to content

Commit ef5b35d

Browse files
authoredNov 3, 2023
twisted#12015 Replace cgi.escape and cgi.parse_header (twisted#12016)
2 parents db0d980 + b4d3a83 commit ef5b35d

File tree

16 files changed

+37
-42
lines changed

16 files changed

+37
-42
lines changed
 

‎docs/core/howto/tutorial/listings/finger/finger15.tac

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Read from file, announce on the web!
2-
import cgi
2+
import html
33

44
from twisted.application import service, strports
55
from twisted.internet import defer, protocol, reactor
@@ -39,9 +39,9 @@ class FingerResource(resource.Resource):
3939
messagevalue = messagevalue.decode("ascii")
4040
if username:
4141
username = username.decode("ascii")
42-
username = cgi.escape(username)
42+
username = html.escape(username)
4343
if messagevalue is not None:
44-
messagevalue = cgi.escape(messagevalue)
44+
messagevalue = html.escape(messagevalue)
4545
text = f"<h1>{username}</h1><p>{messagevalue}</p>"
4646
else:
4747
text = f"<h1>{username}</h1><p>No such user</p>"

‎docs/core/howto/tutorial/listings/finger/finger16.tac

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
# Read from file, announce on the web, irc
2-
import cgi
3-
42
from twisted.application import internet, service, strports
53
from twisted.internet import defer, endpoints, protocol, reactor
64
from twisted.protocols import basic

‎docs/core/howto/tutorial/listings/finger/finger17.tac

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
# Read from file, announce on the web, irc, xml-rpc
2-
import cgi
3-
42
from twisted.application import internet, service, strports
53
from twisted.internet import defer, endpoints, protocol, reactor
64
from twisted.protocols import basic

‎docs/core/howto/tutorial/listings/finger/finger18.tac

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Do everything properly
2-
import cgi
2+
import html
33

44
from twisted.application import internet, service, strports
55
from twisted.internet import defer, endpoints, protocol, reactor
@@ -70,7 +70,7 @@ class UserStatus(resource.Resource):
7070

7171
def render_GET(self, request):
7272
d = self.service.getUser(self.user)
73-
d.addCallback(cgi.escape)
73+
d.addCallback(html.escape)
7474
d.addCallback(lambda m: "<h1>%s</h1>" % self.user + "<p>%s</p>" % m)
7575
d.addCallback(request.write)
7676
d.addCallback(lambda _: request.finish())

‎docs/core/howto/tutorial/listings/finger/finger19.tac

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Do everything properly, and componentize
2-
import cgi
2+
import html
33

44
from zope.interface import Interface, implementer
55

@@ -196,7 +196,7 @@ class UserStatus(resource.Resource):
196196

197197
def render_GET(self, request):
198198
d = self.service.getUser(self.user)
199-
d.addCallback(cgi.escape)
199+
d.addCallback(html.escape)
200200
d.addCallback(lambda m: "<h1>%s</h1>" % self.user + "<p>%s</p>" % m)
201201
d.addCallback(request.write)
202202
d.addCallback(lambda _: request.finish())

‎docs/core/howto/tutorial/listings/finger/finger19a.tac

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Do everything properly, and componentize
2-
import cgi
2+
import html
33

44
from zope.interface import Interface, implementer
55

@@ -179,7 +179,7 @@ class UserStatus(resource.Resource):
179179

180180
def render_GET(self, request):
181181
d = self.service.getUser(self.user)
182-
d.addCallback(cgi.escape)
182+
d.addCallback(html.escape)
183183
d.addCallback(lambda m: "<h1>%s</h1>" % self.user + "<p>%s</p>" % m)
184184
d.addCallback(request.write)
185185
d.addCallback(lambda _: request.finish())

‎docs/core/howto/tutorial/listings/finger/finger19b.tac

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Do everything properly, and componentize
2-
import cgi
2+
import html
33
import pwd
44

55
from zope.interface import Interface, implementer
@@ -205,7 +205,7 @@ class UserStatus(resource.Resource):
205205

206206
def render_GET(self, request):
207207
d = self.service.getUser(self.user)
208-
d.addCallback(cgi.escape)
208+
d.addCallback(html.escape)
209209
d.addCallback(lambda m: "<h1>%s</h1>" % self.user + "<p>%s</p>" % m)
210210
d.addCallback(request.write)
211211
d.addCallback(lambda _: request.finish())

‎docs/core/howto/tutorial/listings/finger/finger19c.tac

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Do everything properly, and componentize
2-
import cgi
2+
import html
33
import os
44
import pwd
55

@@ -206,7 +206,7 @@ class UserStatus(resource.Resource):
206206

207207
def render_GET(self, request):
208208
d = self.service.getUser(self.user)
209-
d.addCallback(cgi.escape)
209+
d.addCallback(html.escape)
210210
d.addCallback(lambda m: "<h1>%s</h1>" % self.user + "<p>%s</p>" % m)
211211
d.addCallback(request.write)
212212
d.addCallback(lambda _: request.finish())

‎docs/core/howto/tutorial/listings/finger/finger20.tac

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
# Do everything properly, and componentize
2-
import cgi
3-
42
from zope.interface import Interface, implementer
53

64
from twisted.application import internet, service, strports

‎docs/core/howto/tutorial/listings/finger/finger21.tac

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
# Do everything properly, and componentize
2-
import cgi
3-
42
from zope.interface import Interface, implementer
53

64
from twisted.application import internet, service, strports

‎docs/core/howto/tutorial/listings/finger/finger22.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
# Do everything properly, and componentize
2-
import cgi
3-
42
from zope.interface import Interface, implementer
53

64
from OpenSSL import SSL

‎docs/web/howto/web-in-60/handling-posts.rst

+6-6
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ understand the possible negative consequences.
3131

3232

3333
As usual, we start with some imports. In addition to the Twisted imports,
34-
this example uses the ``cgi`` module to `escape user-enteredcontent <http://en.wikipedia.org/wiki/Cross-site_scripting>`_ for inclusion in the output.
34+
this example uses the ``html`` module to `escape user-enteredcontent <http://en.wikipedia.org/wiki/Cross-site_scripting>`_ for inclusion in the output.
3535

3636

3737

@@ -44,7 +44,7 @@ this example uses the ``cgi`` module to `escape user-enteredcontent <http://en.w
4444
from twisted.web.resource import Resource
4545
from twisted.internet import reactor, endpoints
4646
47-
import cgi
47+
import html
4848
4949
5050
@@ -82,7 +82,7 @@ method will allow it to accept ``POST`` requests:
8282
...
8383
def render_POST(self, request):
8484
args = request.args[b"the-field"][0].decode("utf-8")
85-
escapedArgs = cgi.escape(args)
85+
escapedArgs = html.escape(args)
8686
return (b"<!DOCTYPE html><html><head><meta charset='utf-8'>"
8787
b"<title></title></head><body>"
8888
b"You submitted: " + escapedArgs.encode('utf-8'))
@@ -96,7 +96,7 @@ provides access to the contents of the form. The keys in this
9696
dictionary are the names of inputs in the form. Each value is a list
9797
containing bytes objects (since there can be multiple inputs with the same
9898
name), which is why we had to extract the first element to pass
99-
to ``cgi.escape`` . ``request.args`` will be
99+
to ``html.escape`` . ``request.args`` will be
100100
populated from form contents whenever a ``POST`` request is
101101
made with a content type
102102
of ``application/x-www-form-urlencoded``
@@ -146,7 +146,7 @@ Here's the complete source for the example:
146146
from twisted.web.resource import Resource
147147
from twisted.internet import reactor, endpoints
148148
149-
import cgi
149+
import html
150150
151151
class FormPage(Resource):
152152
def render_GET(self, request):
@@ -156,7 +156,7 @@ Here's the complete source for the example:
156156
157157
def render_POST(self, request):
158158
args = request.args[b"the-field"][0].decode("utf-8")
159-
escapedArgs = cgi.escape(args)
159+
escapedArgs = html.escape(args)
160160
return (b"<!DOCTYPE html><html><head><meta charset='utf-8'>"
161161
b"<title></title></head><body>"
162162
b"You submitted: " + escapedArgs.encode('utf-8'))

‎docs/web/howto/web-in-60/other-request-bodies.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ directly:
3636
...
3737
def render_POST(self, request):
3838
content = request.content.read().decode("utf-8")
39-
escapedContent = cgi.escape(content)
39+
escapedContent = html.escape(content)
4040
return (b"<!DOCTYPE html><html><head><meta charset='utf-8'>"
4141
b"<title></title></head><body>"
4242
b"You submitted: " +
@@ -68,7 +68,7 @@ only ``render_POST`` changed:
6868
from twisted.web.resource import Resource
6969
from twisted.internet import reactor, endpoints
7070
71-
import cgi
71+
import html
7272
7373
class FormPage(Resource):
7474
def render_GET(self, request):
@@ -78,7 +78,7 @@ only ``render_POST`` changed:
7878
7979
def render_POST(self, request):
8080
content = request.content.read().decode("utf-8")
81-
escapedContent = cgi.escape(content)
81+
escapedContent = html.escape(content)
8282
return (b"<!DOCTYPE html><html><head><meta charset='utf-8'>"
8383
b"<title></title></head><body>"
8484
b"You submitted: " +

‎src/twisted/web/http.py

+11-6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
it, as in the HTTP 1.1 chunked I{Transfer-Encoding} (RFC 7230 section 4.1).
3232
This limits how much data may be buffered when decoding the line.
3333
"""
34+
from __future__ import annotations
3435

3536
__all__ = [
3637
"SWITCHING",
@@ -107,6 +108,7 @@
107108
import tempfile
108109
import time
109110
import warnings
111+
from email.message import EmailMessage
110112
from io import BytesIO
111113
from typing import AnyStr, Callable, List, Optional, Tuple
112114
from urllib.parse import (
@@ -224,15 +226,18 @@
224226
monthname_lower = [name and name.lower() for name in monthname]
225227

226228

227-
def _parseHeader(line):
228-
# cgi.parse_header requires a str
229-
key, pdict = cgi.parse_header(line.decode("charmap"))
229+
def _parseContentType(line: bytes) -> tuple[bytes, dict[str, bytes]]:
230+
msg = EmailMessage()
231+
msg["content-type"] = line.decode("charmap")
232+
233+
key = msg.get_content_type()
234+
pdict = msg["content-type"].params
230235

231236
# We want the key as bytes, and cgi.parse_multipart (which consumes
232237
# pdict) expects a dict of str keys but bytes values
233-
key = key.encode("charmap")
238+
encodedKey = key.encode("charmap")
234239
pdict = {x: y.encode("charmap") for x, y in pdict.items()}
235-
return (key, pdict)
240+
return (encodedKey, pdict)
236241

237242

238243
def urlparse(url):
@@ -973,7 +978,7 @@ def requestReceived(self, command, path, version):
973978

974979
if self.method == b"POST" and ctype and clength:
975980
mfd = b"multipart/form-data"
976-
key, pdict = _parseHeader(ctype)
981+
key, pdict = _parseContentType(ctype)
977982
# This weird CONTENT-LENGTH param is required by
978983
# cgi.parse_multipart() in some versions of Python 3.7+, see
979984
# bpo-29979. It looks like this will be relaxed and backported, see
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Remove usage of cgi.escape and cgi.parse_header.

‎src/twisted/web/test/test_cgi.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,8 @@
8787
"""
8888

8989
URL_PARAMETER_CGI = """\
90-
import cgi
91-
fs = cgi.FieldStorage()
92-
param = fs.getvalue("param")
90+
import os
91+
param = str(os.environ['QUERY_STRING'])
9392
print("Header: OK")
9493
print("")
9594
print(param)
@@ -384,7 +383,7 @@ def test_urlParameters(self):
384383
return d
385384

386385
def _test_urlParameters_1(self, res):
387-
expected = f"1234{os.linesep}"
386+
expected = f"param=1234{os.linesep}"
388387
expected = expected.encode("ascii")
389388
self.assertEqual(res, expected)
390389

0 commit comments

Comments
 (0)