[1mdiff --git a/50_bubble.py b/50_bubble.py[m
[1mindex eb92cea..73855ec 100644[m
[1m--- a/50_bubble.py[m
[1m+++ b/50_bubble.py[m
[36m@@ -415,7 +415,7 @@[m [mBubble is open source:[m
return 30, '/add-cert/' + clean_query(req)[m
[m
if req.path.startswith(self.path + 'add-cert/'):[m
[31m- m = re.search('/add-cert/([\w-]+)$', req.path)[m
[32m+[m[32m m = re.search('/add-cert/([\w%-]+)$', req.path)[m
if not m:[m
return 59, 'Bad request'[m
[m
[36m@@ -423,7 +423,7 @@[m [mBubble is open source:[m
return 11, 'Password:'[m
[m
password = urlparse.unquote(req.query)[m
[31m- user = db.get_user(name=m[1], password=password)[m
[32m+[m[32m user = db.get_user(name=urlparse.unquote(m[1]), password=password)[m
[m
if not user or user.password_expiry() == 0:[m
return 51, 'Not found'[m
[1mdiff --git a/feeds.py b/feeds.py[m
[1mindex eb19ccb..dbef487 100644[m
[1m--- a/feeds.py[m
[1m+++ b/feeds.py[m
[36m@@ -1,4 +1,5 @@[m
import re[m
[32m+[m[32mimport urllib.parse as urlparse[m
from model import User, Post, Segment, Subspace, Commit, Crossref, \[m
FOLLOW_SUBSPACE, FOLLOW_USER, FOLLOW_POST, \[m
MUTE_SUBSPACE, MUTE_USER, MUTE_POST[m
[36m@@ -12,13 +13,13 @@[m [mdef make_post_page_or_configure_feed(session):[m
db = session.db[m
req = session.req[m
path = req.path[len(session.path):][m
[31m- found = re.match(r'(u|s)/([\w-]+)(/(post|compose|image|file|issues|admin|tag))?(/([\w\d-]+)(.*))?', path)[m
[32m+[m[32m found = re.match(r'(u|s)/([\w%-]+)(/(post|compose|image|file|issues|admin|tag))?(/([\w\d-]+)(.*))?', path)[m
if not found:[m
return 59, 'Bad request'[m
[m
# Set up the feed parameters.[m
session.feed_type = found.group(1)[m
[31m- url_name = found.group(2)[m
[32m+[m[32m url_name = urlparse.unquote(found.group(2))[m
action = found.group(4)[m
arg = found.group(6)[m
arg2 = found.group(7)[m
[1mdiff --git a/subspace.py b/subspace.py[m
[1mindex 25ba42e..9bfb631 100644[m
[1m--- a/subspace.py[m
[1m+++ b/subspace.py[m
[36m@@ -1,6 +1,7 @@[m
import datetime[m
import io[m
import time[m
[32m+[m[32mimport urllib.parse as urlparse[m
import zipfile[m
from model import Search, Segment, User, Subspace, Post[m
from utils import *[m
[36m@@ -260,11 +261,11 @@[m [mdef make_search_page(session):[m
[m
LIMIT = 30[m
[m
[31m- m = re.match(r'(/([us])/([\w-]+))?/search(/(\d+))?', req.path)[m
[32m+[m[32m m = re.match(r'(/([us])/([\w%-]+))?/search(/(\d+))?', req.path)[m
if not m:[m
return 59, 'Bad request'[m
if m[2] or m[3]:[m
[31m- ident = m[3][m
[32m+[m[32m ident = urlparse.unquote(m[3])[m
scope = db.get_subspace(name=ident)[m
if m[2] == 'u' and not scope.owner:[m
return 51, 'Not found'[m
[36m@@ -514,16 +515,16 @@[m [mclass GempubArchive:[m
src = entry.page[m
src_post_id = entry.post_id[m
[m
[31m- user_pattern = re.compile(r'^=>\s*/u/([\w-]+)\s')[m
[32m+[m[32m user_pattern = re.compile(r'^=>\s*/u/([\w%-]+)\s')[m
post_pattern = re.compile(r'^=>\s*/([us])/' + self.subspace.name + r'/(\d+)\s')[m
[31m- file_pattern = re.compile(r'^=>\s*/([us])/[\w-]+/(image|file)/(\d+)[^ ]*\s')[m
[32m+[m[32m file_pattern = re.compile(r'^=>\s*/([us])/[\w%-]+/(image|file)/(\d+)[^ ]*\s')[m
root_pattern = re.compile(r'^=>\s*/([^ ]*)\s')[m
rewritten = [][m
[m
for line in src.split('\n'):[m
m = user_pattern.search(line)[m
if m:[m
[31m- line = f'=> ../../users/{m[1]}.gmi ' + line[m.end():][m
[32m+[m[32m line = f'=> ../../users/{urlparse.unquote(m[1])}.gmi ' + line[m.end():][m
rewritten.append(line)[m
continue[m
[m
[36m@@ -687,10 +688,10 @@[m [mdef export_gempub_archive(session):[m
return 60, 'Login required'[m
[m
# Determine subspace to export.[m
[31m- m = re.search(r'/export/(s/)?([\w-]+).gpub$', req.path)[m
[32m+[m[32m m = re.search(r'/export/(s/)?([\w%-]+).gpub$', req.path)[m
if not m or not m[2]:[m
return 59, 'Bad request'[m
[31m- name = m[2][m
[32m+[m[32m name = urlparse.unquote(m[2])[m
subspace = db.get_subspace(name=name)[m
is_user = m[1] is None[m
[m
[1mdiff --git a/user.py b/user.py[m
[1mindex 730aa8d..cebe2ea 100644[m
[1m--- a/user.py[m
[1m+++ b/user.py[m
[36m@@ -102,15 +102,15 @@[m [mdef user_actions(session):[m
elif re.search(r'^(follow|unfollow|mute|unmute)/', req.path[len(session.path):]):[m
if not session.user:[m
return 60, 'Login required'[m
[31m- found = re.match(r'(follow|unfollow|mute|unmute)/(post/(\d+)|([\w-]+)|(u/[\w-]+)|(s/[\w-]+))$',[m
[32m+[m[32m found = re.match(r'(follow|unfollow|mute|unmute)/(post/(\d+)|([\w%-]+)|(u/[\w%-]+)|(s/[\w%-]+))$',[m
req.path[len(session.path):])[m
if not found:[m
return 59, 'Bad request'[m
action = found[1][m
post_id = found[3][m
[31m- u_name = found[4][m
[31m- u_sub = found[5][m
[31m- s_sub = found[6][m
[32m+[m[32m u_name = urlparse.unquote(found[4])[m
[32m+[m[32m u_sub = urlparse.unquote(found[5])[m
[32m+[m[32m s_sub = urlparse.unquote(found[6])[m
is_follow = action in ('follow', 'unfollow')[m
if u_name != None:[m
target_type = FOLLOW_USER if is_follow else MUTE_USER[m
text/plain
This content has been proxied by September (ba2dc).