[1mdiff --git a/README.md b/README.md[m
[1mindex 6c04597..fbccb70 100644[m
[1m--- a/README.md[m
[1m+++ b/README.md[m
[36m@@ -7,7 +7,7 @@[m [mThis is a simple Python script that listens for Titan requests and then adds, up[m
The configuration file ~/.booster/config.json must exist:[m
[m
[31m-{ [m
[32m+[m[32m{[m
"python": "/usr/bin/python3",[m
"git": {[m
"exec": "/usr/bin/git",[m
[36m@@ -18,8 +18,15 @@[m [mThe configuration file ~/.booster/config.json must exist:[m
"cert": "/absolute-path/titan.crt",[m
"key": "/absolute-path/titan.key",[m
"authorized": "/absolute-path/titan-clients.pem",[m
[31m- "file_root": "/absolute-path-where-files-are-kept/",[m
"site_url": "gemini://skyjake.fi",[m
[31m- "root": "/gemlog"[m
[32m+[m[32m "files": {[m
[32m+[m[32m "root": "/absolute-path/capsule-files/",[m
[32m+[m[32m "Gemlog": {[m
[32m+[m[32m "subdir": "gemlog/"[m
[32m+[m[32m },[m
[32m+[m[32m "Title prefix for Git": {[m
[32m+[m[32m "file": "relative-path-of-single-file.gmi"[m
[32m+[m[32m }[m
[32m+[m[32m }[m
}[m
[1mdiff --git a/booster.py b/booster.py[m
[1mindex d4e9d09..a2636da 100755[m
[1m--- a/booster.py[m
[1m+++ b/booster.py[m
[36m@@ -30,11 +30,15 @@[m
[m
[31m-import os, sys, json, subprocess[m
[32m+[m[32mimport os, sys, json, subprocess, time[m
import socket, ssl, OpenSSL.crypto, hashlib[m
from urllib.parse import urlparse[m
pjoin = os.path.join[m
[m
[32m+[m[32mdef append_slash(p):[m
[32m+[m[32m if not p.endswith('/'): return p + '/'[m
[32m+[m[32m return p[m
[32m+[m
#----------------------------------------------------------------------------#[m
#----------------------------------------------------------------------------#[m
[36m@@ -45,9 +49,8 @@[m [mif not os.path.exists(CFG_PATH):[m
print(f'ERROR: Configuration file {CFG_PATH} not found.')[m
sys.exit(1)[m
CONFIG = json.loads(open(CFG_PATH, 'rt').read())[m
[31m-if not CONFIG['root'].endswith('/'):[m
[31m- CONFIG['root'] = CONFIG['root'] + '/'[m
print(json.dumps(CONFIG, indent=2))[m
[32m+[m[32mFILES_ROOT = append_slash(CONFIG['files']['root'])[m
[m
#----------------------------------------------------------------------------#[m
[36m@@ -75,6 +78,7 @@[m [mdef urlenc(q):[m
return q[m
[m
def handle_client(stream):[m
[32m+[m[32m print(time.strftime('%Y-%m-%d %H:%M:%S'))[m
data = bytes()[m
incoming = stream.recv(1024)[m
expected_size = -1[m
[36m@@ -105,54 +109,81 @@[m [mdef handle_client(stream):[m
if len(data) >= expected_size:[m
break[m
incoming = stream.recv(1024)[m
[31m- # process the request[m
[32m+[m
print(f'URL : {req_url}')[m
print(f'Token : {req_token}')[m
print(f'MIME : {req_mime}')[m
print(f'Data : {len(data)} bytes')[m
[32m+[m
parts = urlparse(req_url)[m
path = parts.path[m
[31m- if not path.startswith(CONFIG['root']):[m
[31m- report_error(stream, 51, "invalid path")[m
[31m- return[m
[31m- path = path[len(CONFIG['root']):][m
[31m- if path.startswith('.'):[m
[32m+[m[32m file_path = None[m
[32m+[m[32m msg_path = None[m
[32m+[m[32m if (path.startswith('.') or[m
[32m+[m[32m os.path.basename(path).startswith('.') or[m
[32m+[m[32m '..' in path):[m
report_error(stream, 61, "access is not authorized")[m
return[m
[31m- file_path = pjoin(CONFIG['file_root'], path)[m
[31m- view_url = '%s/%s%s' % (CONFIG['site_url'], CONFIG['root'], path)[m
[32m+[m
[32m+[m[32m # Are we allowed to edit this path?[m
[32m+[m[32m msg_prefix = ''[m
[32m+[m[32m for file_group in CONFIG['files']:[m
[32m+[m[32m group = CONFIG['files'][file_group][m
[32m+[m[32m if type(group) != dict: continue[m
[32m+[m[32m if 'subdir' in group:[m
[32m+[m[32m auth_prefix = append_slash(group['subdir'])[m
[32m+[m[32m msg_path = path[len(auth_prefix):][m
[32m+[m[32m elif 'file' in group:[m
[32m+[m[32m auth_prefix = '/' + group['file'][m
[32m+[m[32m msg_path = os.path.basename(path)[m
[32m+[m[32m if path.startswith(auth_prefix):[m
[32m+[m[32m file_path = os.path.normpath(FILES_ROOT + path)[m
[32m+[m[32m if not file_path.startswith(FILES_ROOT) or \[m
[32m+[m[32m os.path.isdir(file_path):[m
[32m+[m[32m report_error(stream, 61, "access is not authorized")[m
[32m+[m[32m return[m
[32m+[m[32m msg_prefix = f'{file_group}: '[m
[32m+[m[32m break[m
[32m+[m[32m if not file_path:[m
[32m+[m[32m report_error(stream, 61, "unauthorized location")[m
[32m+[m[32m return[m
[32m+[m
[32m+[m[32m # Process the request.[m
[32m+[m[32m is_new = not os.path.exists(file_path)[m
[32m+[m[32m view_url = '%s%s' % (CONFIG['site_url'], path)[m
response = '# Booster log\n'[m
[31m- is_new = not os.path.exists(file_path)[m
[31m- GIT = CONFIG['git'][m
if not is_new and req_token == 'DELETE':[m
response += f'* deleting file: {file_path}\n'[m
os.remove(file_path)[m
[31m- git_msg = GIT['message_prefix'] + 'Removed ' + path[m
[32m+[m[32m git_msg = msg_prefix + 'Removed ' + msg_path[m
else:[m
if is_new:[m
response += f'* creating a new file: {file_path}\n'[m
[31m- git_msg = GIT['message_prefix'] + 'Added ' + path[m
[32m+[m[32m git_msg = msg_prefix + 'Added ' + msg_path[m
else:[m
response += f'* updating file: {file_path}\n'[m
[31m- git_msg = GIT['message_prefix'] + 'Updated ' + path[m
[32m+[m[32m git_msg = msg_prefix + 'Updated ' + msg_path[m
# write the data[m
response += f'* writing %d bytes\n' % len(data)[m
dst = open(file_path, 'wb')[m
dst.write(data)[m
dst.close()[m
[31m- # update indices[m
[31m- os.chdir(CONFIG['file_root'])[m
[32m+[m
[32m+[m[32m # Update Gemlog indices.[m
[32m+[m[32m GEMLOG_SUBDIR = CONFIG['files']['Gemlog']['subdir'][m
[32m+[m[32m os.chdir(pjoin(FILES_ROOT, GEMLOG_SUBDIR))[m
response += f'* updating indices\n'[m
response += run_command([CONFIG['python'], ".makeindex.py"])[m
response += '* committing changes to Git repository\n'[m
if is_new:[m
[31m- response += run_command([GIT['exec'], 'add', file_path])[m
[31m- response += run_command([GIT['exec'], 'commit', '-a', '-m', git_msg])[m
[32m+[m[32m response += run_command([CONFIG['git'], 'add', file_path])[m
[32m+[m[32m response += run_command([CONFIG['git'], 'commit', '-a', '-m', git_msg])[m
response += "\n"[m
response += f"=> {view_url} View the page\n"[m
response += f"=> gemini://warmedal.se/~antenna/submit?%s Notify Antenna" %\[m
[31m- urlenc('%s%s' % (CONFIG['site_url'], CONFIG['root']))[m
[31m- # compose a response[m
[32m+[m[32m urlenc('%s%s' % (CONFIG['site_url'], GEMLOG_SUBDIR))[m
[32m+[m
[32m+[m[32m # Send the response.[m
stream.sendall(('20 text/gemini; charset=utf-8\r\n%s' %[m
response).encode('utf-8'))[m
[m
text/plain
This content has been proxied by September (ba2dc).