Compare commits
No commits in common. "e7dfc359f5e2eb47e872fe339105f4da968f246e" and "cb3433e93c266124c79a23bfaa3e2299631ec858" have entirely different histories.
e7dfc359f5
...
cb3433e93c
|
@ -1,6 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Share a text file to shrlok.
|
|
||||||
cat <(printf '{"type":"txt"}\0') "$1" \
|
|
||||||
| socat - UNIX-CONNECT:/run/shrlok/shr.sock \
|
|
||||||
| sed 's|/var/www/files|https://files.dece.space|' \
|
|
||||||
; echo
|
|
2
shrlok/shr-txt.py
Normal file
2
shrlok/shr-txt.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
|
@ -1,27 +1,4 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""shrlok server: receive text/files from a socket, put them on a Web server.
|
|
||||||
|
|
||||||
The server expects messages with the following format to come through the
|
|
||||||
socket:
|
|
||||||
|
|
||||||
1. a length, as ASCII digits,
|
|
||||||
2. a null byte,
|
|
||||||
3. a JSON object containing at least the "type" key with a known value,
|
|
||||||
4. another null byte,
|
|
||||||
5. the text or file itself.
|
|
||||||
|
|
||||||
The length is of the JSON object + the null char + the content itself.
|
|
||||||
|
|
||||||
Example, with \\0 representing a null byte:
|
|
||||||
|
|
||||||
28\\0{"type":"txt"}\\0hello shrlok!
|
|
||||||
|
|
||||||
The content is 13 bytes (assuming no LF at the end), the header is 14 bytes,
|
|
||||||
plus the null byte it is 13 + 14 + 1 = 28 bytes, thus the prefixed length.
|
|
||||||
|
|
||||||
After the content is succesfully retrieved and put on an appropriate location,
|
|
||||||
the server will reply the file path through the socket and close the connection.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
|
@ -52,9 +29,11 @@ HTML_TEMPLATE = """\
|
||||||
class Handler(socketserver.StreamRequestHandler):
|
class Handler(socketserver.StreamRequestHandler):
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
data = self.receive_input()
|
fragments = []
|
||||||
|
while (chunk := self.request.recv(4096)):
|
||||||
|
fragments.append(chunk)
|
||||||
|
data = b"".join(fragments)
|
||||||
|
|
||||||
# Extract header.
|
|
||||||
try:
|
try:
|
||||||
first_zero = data.index(b"\0")
|
first_zero = data.index(b"\0")
|
||||||
header_data, data = data[:first_zero], data[first_zero + 1:]
|
header_data, data = data[:first_zero], data[first_zero + 1:]
|
||||||
|
@ -63,38 +42,17 @@ class Handler(socketserver.StreamRequestHandler):
|
||||||
print("Bad header.")
|
print("Bad header.")
|
||||||
return
|
return
|
||||||
|
|
||||||
file_name = None
|
|
||||||
if header.get("type") == "txt":
|
if header.get("type") == "txt":
|
||||||
file_name = write_text(data, title=header.get("title"))
|
file_name = write_text(data, title=header.get("title"))
|
||||||
else:
|
else:
|
||||||
print("Unknown type.")
|
print("Unknown type.")
|
||||||
if file_name is None:
|
return
|
||||||
|
|
||||||
|
if not file_name:
|
||||||
return
|
return
|
||||||
|
|
||||||
print(f"{len(data)} bytes — {header} — '{file_name}'.")
|
print(f"{len(data)} bytes — {header} — '{file_name}'.")
|
||||||
try:
|
|
||||||
self.request.sendall(file_name.encode())
|
self.request.sendall(file_name.encode())
|
||||||
except BrokenPipeError:
|
|
||||||
print("Broken pipe.")
|
|
||||||
|
|
||||||
def receive_input(self):
|
|
||||||
length = None
|
|
||||||
data = b""
|
|
||||||
while True:
|
|
||||||
chunk = self.request.recv(4096)
|
|
||||||
if not chunk:
|
|
||||||
break
|
|
||||||
data += chunk
|
|
||||||
if length is None:
|
|
||||||
try:
|
|
||||||
first_zero = data.index(b"\0")
|
|
||||||
except ValueError:
|
|
||||||
return b""
|
|
||||||
length_data, data = data[:first_zero], data[first_zero + 1:]
|
|
||||||
length = int(length_data.decode())
|
|
||||||
if len(data) >= length: # retrieval completed
|
|
||||||
break
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def write_text(data: bytes, title=None):
|
def write_text(data: bytes, title=None):
|
||||||
|
@ -134,7 +92,6 @@ def main():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with socketserver.UnixStreamServer(socket_path, Handler) as server:
|
with socketserver.UnixStreamServer(socket_path, Handler) as server:
|
||||||
os.chmod(socket_path, 0o664)
|
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("Stopping server.")
|
print("Stopping server.")
|
||||||
|
|
Reference in a new issue