comparison roundup/cgi/actions.py @ 8580:5cba36e42b8f

chore: refactor replace urlparse with urlsplit and use urllib_ Python docs recommend use of urlsplit() rather than urlparse(). urlsplit() is a little faster and doesn't try to split the path into path and params using the rules from an obsolete RFC. actions.py, demo.py, rest.py, client.py Replace urlparse() with urlsplit() actions.py urlsplit() produces a named tuple with one fewer elements (no .param). So fixup calls to urlunparse() so they have the proper number of elements in the tuple. also merge url filtering for param and path. demo.py, rest.py: Replace imports from urlparse/urllib.parse with roundup.anypy.urllib_ so we use the same interface throughout the code base. test/test_cgi.py: Since actions.py filtering for invali urls not split by path/param, fix tests for improperly quoted url's.
author John Rouillard <rouilj@ieee.org>
date Sun, 19 Apr 2026 22:58:59 -0400
parents 166cb2632315
children
comparison
equal deleted inserted replaced
8579:d2304f4774ae 8580:5cba36e42b8f
90 it's correct as it comes in or it's a ValueError. 90 it's correct as it comes in or it's a ValueError.
91 91
92 Finally paste the whole thing together and return the new url. 92 Finally paste the whole thing together and return the new url.
93 ''' 93 '''
94 94
95 parsed_url_tuple = urllib_.urlparse(url) 95 parsed_url_tuple = urllib_.urlsplit(url)
96 if self.base: 96 if self.base:
97 parsed_base_url_tuple = urllib_.urlparse(self.base) 97 parsed_base_url_tuple = urllib_.urlsplit(self.base)
98 else: 98 else:
99 raise ValueError(self._("Base url not set. Check configuration.")) 99 raise ValueError(self._("Base url not set. Check configuration."))
100 100
101 info = {'url': url, 101 info = {'url': url,
102 'base_url': self.base, 102 'base_url': self.base,
104 'base_netloc': parsed_base_url_tuple.netloc, 104 'base_netloc': parsed_base_url_tuple.netloc,
105 'base_path': parsed_base_url_tuple.path, 105 'base_path': parsed_base_url_tuple.path,
106 'url_scheme': parsed_url_tuple.scheme, 106 'url_scheme': parsed_url_tuple.scheme,
107 'url_netloc': parsed_url_tuple.netloc, 107 'url_netloc': parsed_url_tuple.netloc,
108 'url_path': parsed_url_tuple.path, 108 'url_path': parsed_url_tuple.path,
109 'url_params': parsed_url_tuple.params,
110 'url_query': parsed_url_tuple.query, 109 'url_query': parsed_url_tuple.query,
111 'url_fragment': parsed_url_tuple.fragment} 110 'url_fragment': parsed_url_tuple.fragment}
112 111
113 if parsed_base_url_tuple.scheme == "https": 112 if parsed_base_url_tuple.scheme == "https":
114 if parsed_url_tuple.scheme != "https": 113 if parsed_url_tuple.scheme != "https":
140 139
141 if not allowed_pattern.match(parsed_url_tuple.path): 140 if not allowed_pattern.match(parsed_url_tuple.path):
142 raise ValueError(self._("Path component (%(url_path)s) in %(url)s " 141 raise ValueError(self._("Path component (%(url_path)s) in %(url)s "
143 "is not properly escaped") % info) 142 "is not properly escaped") % info)
144 143
145 if not allowed_pattern.match(parsed_url_tuple.params):
146 raise ValueError(self._("Params component (%(url_params)s) in %(url)s is not properly escaped") % info)
147
148 if not allowed_pattern.match(parsed_url_tuple.query): 144 if not allowed_pattern.match(parsed_url_tuple.query):
149 raise ValueError(self._("Query component (%(url_query)s) in %(url)s is not properly escaped") % info) 145 raise ValueError(self._("Query component (%(url_query)s) in %(url)s is not properly escaped") % info)
150 146
151 if not allowed_pattern.match(parsed_url_tuple.fragment): 147 if not allowed_pattern.match(parsed_url_tuple.fragment):
152 raise ValueError(self._("Fragment component (%(url_fragment)s) in %(url)s is not properly escaped") % info) 148 raise ValueError(self._("Fragment component (%(url_fragment)s) in %(url)s is not properly escaped") % info)
153 149
154 return urllib_.urlunparse(parsed_url_tuple) 150 return urllib_.urlunparse((*parsed_url_tuple[0:3],
151 "", # urlsplit has no .params
152 *parsed_url_tuple[3:]))
155 153
156 name = '' 154 name = ''
157 permissionType = None 155 permissionType = None
158 156
159 def permission(self): 157 def permission(self):
1276 # 4. Define a new redirect_url missing the @...message entries. 1274 # 4. Define a new redirect_url missing the @...message entries.
1277 # This will be redefined if there is a login error to include 1275 # This will be redefined if there is a login error to include
1278 # a new error message 1276 # a new error message
1279 1277
1280 clean_url = self.examine_url(self.form['__came_from'].value) 1278 clean_url = self.examine_url(self.form['__came_from'].value)
1281 redirect_url_tuple = urllib_.urlparse(clean_url) 1279 redirect_url_tuple = urllib_.urlsplit(clean_url)
1282 # now I have a tuple form for the __came_from url 1280 # now I have a tuple form for the __came_from url
1283 try: 1281 try:
1284 query = urllib_.parse_qs(redirect_url_tuple.query) 1282 query = urllib_.parse_qs(redirect_url_tuple.query)
1285 if "@error_message" in query: 1283 if "@error_message" in query:
1286 del query["@error_message"] 1284 del query["@error_message"]
1298 1296
1299 redirect_url = urllib_.urlunparse( 1297 redirect_url = urllib_.urlunparse(
1300 (redirect_url_tuple.scheme, 1298 (redirect_url_tuple.scheme,
1301 redirect_url_tuple.netloc, 1299 redirect_url_tuple.netloc,
1302 redirect_url_tuple.path, 1300 redirect_url_tuple.path,
1303 redirect_url_tuple.params, 1301 "", # urlsplit() has no .params
1304 urllib_.urlencode(list(sorted(query.items())), doseq=True), 1302 urllib_.urlencode(list(sorted(query.items())), doseq=True),
1305 redirect_url_tuple.fragment)) 1303 redirect_url_tuple.fragment))
1306 1304
1307 try: 1305 try:
1308 self.verifyLogin(self.client.user, password) 1306 self.verifyLogin(self.client.user, password)
1316 query['@error_message'] = err.args 1314 query['@error_message'] = err.args
1317 redirect_url = urllib_.urlunparse( 1315 redirect_url = urllib_.urlunparse(
1318 (redirect_url_tuple.scheme, 1316 (redirect_url_tuple.scheme,
1319 redirect_url_tuple.netloc, 1317 redirect_url_tuple.netloc,
1320 redirect_url_tuple.path, 1318 redirect_url_tuple.path,
1321 redirect_url_tuple.params, 1319 "", # urlsplit() has no .params
1322 urllib_.urlencode(list(sorted(query.items())), doseq=True), 1320 urllib_.urlencode(list(sorted(query.items())), doseq=True),
1323 redirect_url_tuple.fragment)) 1321 redirect_url_tuple.fragment))
1324 raise exceptions.Redirect(redirect_url) 1322 raise exceptions.Redirect(redirect_url)
1325 # if no __came_from, send back to base url with error 1323 # if no __came_from, send back to base url with error
1326 return 1324 return
1339 query['@error_message'] = err.args 1337 query['@error_message'] = err.args
1340 redirect_url = urllib_.urlunparse( 1338 redirect_url = urllib_.urlunparse(
1341 (redirect_url_tuple.scheme, 1339 (redirect_url_tuple.scheme,
1342 redirect_url_tuple.netloc, 1340 redirect_url_tuple.netloc,
1343 redirect_url_tuple.path, 1341 redirect_url_tuple.path,
1344 redirect_url_tuple.params, 1342 "", # urlsplit() has no .params
1345 urllib_.urlencode(list(sorted(query.items())), doseq=True), 1343 urllib_.urlencode(list(sorted(query.items())), doseq=True),
1346 redirect_url_tuple.fragment)) 1344 redirect_url_tuple.fragment))
1347 raise exceptions.Redirect(redirect_url) 1345 raise exceptions.Redirect(redirect_url)
1348 raise 1346 raise
1349 1347
1361 query['@ok_message'] = _("Welcome %(username)s!") % { 1359 query['@ok_message'] = _("Welcome %(username)s!") % {
1362 "username": self.client.user, } 1360 "username": self.client.user, }
1363 redirect_url = urllib_.urlunparse((redirect_url_tuple.scheme, 1361 redirect_url = urllib_.urlunparse((redirect_url_tuple.scheme,
1364 redirect_url_tuple.netloc, 1362 redirect_url_tuple.netloc,
1365 redirect_url_tuple.path, 1363 redirect_url_tuple.path,
1366 redirect_url_tuple.params, 1364 "", # urlsplit has no .params
1367 urllib_.urlencode(list(sorted(query.items())), doseq=True), 1365 urllib_.urlencode(list(sorted(query.items())), doseq=True),
1368 redirect_url_tuple.fragment)) 1366 redirect_url_tuple.fragment))
1369 1367
1370 raise exceptions.Redirect(redirect_url) 1368 raise exceptions.Redirect(redirect_url)
1371 1369

Roundup Issue Tracker: http://roundup-tracker.org/