Bubble [main]

Unquote names in URLs

=> 57167e78ea5ef7d2b4bb16a85d1b77794d2b3949

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

This content has been proxied by September (3851b).