From 0bc554354bb2ae0298e13fa05768a60e4f889fa0 Mon Sep 17 00:00:00 2001 From: Floki Date: Mon, 29 Jun 2026 12:46:01 +0200 Subject: [PATCH] auto-sync: 2026-06-29_10:46:01 --- __pycache__/vault-api.cpython-313.pyc | Bin 0 -> 6849 bytes vault-api.py | 71 ++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 __pycache__/vault-api.cpython-313.pyc create mode 100644 vault-api.py diff --git a/__pycache__/vault-api.cpython-313.pyc b/__pycache__/vault-api.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2641d2ba9bc59b45b1d0325bad0d1d3acb40c4cf GIT binary patch literal 6849 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 q-t!fLibtn4h|&Gr^b=DSRi#l?%JK9{YX67jN literal 0 HcmV?d00001 diff --git a/vault-api.py b/vault-api.py new file mode 100644 index 0000000..175fee3 --- /dev/null +++ b/vault-api.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +import http.server, json, os, urllib.parse, shutil + +VAULT_DIR = '/opt/jarvis-vault' + +class VaultHandler(http.server.BaseHTTPRequestHandler): + def _send(self, data, status=200): + self.send_response(status) + self.send_header('Content-Type', 'application/json') + self.send_header('Access-Control-Allow-Origin', '*') + self.send_header('Access-Control-Allow-Methods', 'GET,PUT,DELETE,OPTIONS') + self.send_header('Access-Control-Allow-Headers', 'Content-Type') + self.end_headers() + self.wfile.write(json.dumps(data).encode()) + + def do_OPTIONS(self): + self._send({}) + + def do_GET(self): + parsed = urllib.parse.urlparse(self.path) + params = urllib.parse.parse_qs(parsed.query) + path = params.get('path', [None])[0] + + if parsed.path == '/tree': + files = [] + for root, dirs, fnames in os.walk(VAULT_DIR): + for f in fnames: + rel = os.path.relpath(os.path.join(root, f), VAULT_DIR) + files.append(rel) + self._send({'files': sorted(files)}) + + elif parsed.path == '/read' and path: + full = os.path.join(VAULT_DIR, path) + if not os.path.realpath(full).startswith(os.path.realpath(VAULT_DIR)): + return self._send({'error': 'Invalid path'}, 400) + if os.path.isfile(full): + with open(full) as f: + self._send({'path': path, 'content': f.read()}) + else: + self._send({'error': 'Not found'}, 404) + else: + self._send({'error': 'Not found'}, 404) + + def do_PUT(self): + parsed = urllib.parse.urlparse(self.path) + params = urllib.parse.parse_qs(parsed.query) + path = params.get('path', [None])[0] + if not path: return self._send({'error': 'Missing path'}, 400) + length = int(self.headers.get('Content-Length', 0)) + content = self.rfile.read(length).decode() if length else '' + full = os.path.join(VAULT_DIR, path) + if not os.path.realpath(full).startswith(os.path.realpath(VAULT_DIR)): + return self._send({'error': 'Invalid'}, 400) + os.makedirs(os.path.dirname(full), exist_ok=True) + with open(full, 'w') as f: f.write(content) + self._send({'saved': True}) + + def do_DELETE(self): + parsed = urllib.parse.urlparse(self.path) + params = urllib.parse.parse_qs(parsed.query) + path = params.get('path', [None])[0] + if not path: return self._send({'error': 'Missing path'}, 400) + full = os.path.join(VAULT_DIR, path) + if not os.path.realpath(full).startswith(os.path.realpath(VAULT_DIR)): + return self._send({'error': 'Invalid'}, 400) + if os.path.isfile(full): os.remove(full) + elif os.path.isdir(full): shutil.rmtree(full) + else: return self._send({'error': 'Not found'}, 404) + self._send({'deleted': True}) + +http.server.HTTPServer(('0.0.0.0', 8801), VaultHandler).serve_forever()