mirror of
https://git.exozy.me/a/fuwuqi.git
synced 2024-06-02 13:29:28 +00:00
88 lines
3.1 KiB
Python
88 lines
3.1 KiB
Python
from base64 import b64decode
|
|
from cryptography.hazmat.primitives import hashes, serialization
|
|
from cryptography.hazmat.primitives.asymmetric import padding
|
|
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
|
from json import dump, load, loads
|
|
from re import search
|
|
from requests import get, post
|
|
from os.path import isfile
|
|
from urllib.parse import quote_plus
|
|
|
|
|
|
def collection_append(file, item):
|
|
with open(file) as f:
|
|
collection = load(f)
|
|
collection['totalItems'] += 1
|
|
collection['orderedItems'].append(item)
|
|
with open(file, 'w') as f:
|
|
dump(collection, f)
|
|
|
|
|
|
class fuwuqi(SimpleHTTPRequestHandler):
|
|
def do_POST(self):
|
|
body = self.rfile.read(int(self.headers['Content-Length']))
|
|
activity = loads(body)
|
|
print(activity)
|
|
print(self.headers)
|
|
print(self.path)
|
|
|
|
# Get actor public key
|
|
keyid = search('keyId="(.*?)"', self.headers['Signature']).group(1)
|
|
actorfile = f'users/{quote_plus(keyid)}'
|
|
if not isfile(actorfile):
|
|
with open(actorfile, 'w') as f:
|
|
f.write(get(keyid).text)
|
|
with open(actorfile) as f:
|
|
pubkeypem = load(f)['publicKey']['publicKeyPem'].encode('utf8')
|
|
pubkey = serialization.load_pem_public_key(pubkeypem, None)
|
|
|
|
# Assemble headers
|
|
headers = search('headers="(.*?)"', self.headers['Signature']).group(1)
|
|
message = ''
|
|
for header in headers.split():
|
|
headerval = self.headers[header]
|
|
message += f'{header}: {headerval}\n'
|
|
|
|
# Verify HTTP signature
|
|
signature = search('signature="(.*?)"', self.headers['Signature']).group(1)
|
|
pubkey.verify(
|
|
b64decode(signature),
|
|
message[:-1].encode('utf8'),
|
|
padding.PKCS1v15(),
|
|
hashes.SHA256()
|
|
)
|
|
|
|
# Make sure activity doer matches HTTP signature
|
|
actor = keyid.removesuffix('#main-key')
|
|
if 'actor' in activity and activity['actor'] != actor:
|
|
self.send_response(401)
|
|
return
|
|
if 'attributedTo' in activity and activity['attributedTo'] != actor:
|
|
self.send_response(401)
|
|
return
|
|
|
|
username = search('^/users/(.*)\.(in|out)box$', self.path).group(1)
|
|
if self.path.endswith('inbox'):
|
|
# S2S
|
|
id = activity['id'].split('/')[-1]
|
|
with open(f'users/{username}/{id}', 'w') as f:
|
|
dump(activity, f)
|
|
elif self.path.endswith('outbox'):
|
|
# C2S
|
|
collection_append(f'users/{username}.outbox', activity)
|
|
|
|
if activity['type'] == 'Create':
|
|
id = activity['id'].split('/')[-1]
|
|
with open(f'users/{username}.statuses/{id}', 'w') as f:
|
|
dump(activity['object'], f)
|
|
print(self.headers)
|
|
print(body)
|
|
resp = post('https://social.exozy.me/inbox', headers=self.headers, data=body)
|
|
print(resp)
|
|
print(resp.text)
|
|
|
|
self.send_response(200)
|
|
|
|
|
|
ThreadingHTTPServer(('localhost', 4200), fuwuqi).serve_forever()
|