#!/usr/bin/env python3 import json, psycopg2, re, socket, time CONFIG_DB_CONNECT = "host=127.0.0.1 port=5432 user=minetest password=PASSWORD dbname=minetest-world" CONFIG_LISTEN = ("0.0.0.0", 8060) RECBUF = 1024 p_clen = re.compile("\r?\ncontent-length: *(\d+)\r?\n?", re.IGNORECASE) p_stmt = re.compile("^(x|y|z)(<|>|=|<=|>=)-?\d{1,5}$") def send_response(client, code, resp): try: content_raw = json.dumps(resp).encode() except TypeError: content_raw = json.dumps({"error": "non_ascii_resp"}).encode() mime = "text/json" client.sendall(("HTTP/1.1 "+code+"\r\nContent-type: "+mime+"; charset=UTF-8\r\nAccess-Control-Allow-Origin: *\r\nContent-length: "+str(len(content_raw))+"\r\n\r\n").encode()+content_raw) client.close() if __name__ == "__main__": conn = psycopg2.connect(CONFIG_DB_CONNECT) server_addr = CONFIG_LISTEN if ":" in server_addr[0]: # IPv6 sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) else: # IPv4 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.settimeout(5) sock.bind(server_addr) sock.listen(1) print("Server started at "+str(server_addr)) while True: try: client, addr = sock.accept() except socket.timeout: continue # Get request paquet = b"" header = b"" content = b"" content_len = 0 resp = {} lf = 0 while True: raw = client.recv(RECBUF) if raw: paquet += raw if lf >= 0: for c in raw: if c == 10:# LF lf += 1 elif c != 13:# CR lf = 0 if lf > 1: parts = paquet.split(b"\r\n\r\n") header = parts[0] content = parts[1] try: content_len = int(p_clen.search(header.decode()).group(1)) except (AttributeError, ValueError): content_len = 0 break if lf > 1: break else: break while len(content) < content_len: raw = client.recv(RECBUF) paquet += raw content += raw # Get URL httpreq = paquet.split(b"\n") try: url = httpreq[0].split(b" ")[1].decode().split("/") except IndexError: send_response(client, "400 Bad Request", {"error": "bad_http"}) continue while "" in url: url.remove("") urll = len(url) if len(url) > 6: send_response(client, "400 Bad Request", {"error": "too_many_statements"}) continue if len(url) == 0: send_response(client, "400 Bad Request", {"error": "no_statement"}) continue stmts = [] bad = False for stmt in url: if not p_stmt.match(stmt): bad = True break stmts.append("pos"+stmt) if bad: send_response(client, "400 Bad Request", {"error": "bad_statement"}) continue req = " AND ".join(stmts) cur = conn.cursor() cur.execute("SELECT * FROM blocks WHERE "+req+" LIMIT 1000;") resp["blocks"] = [] while True: block = cur.fetchone() if not block: break resp["blocks"].append([block[0], block[1], block[2], block[3].hex()]) print(req) # Send response send_response(client, "200 OK", resp) time.sleep(.2)