| Server IP : 54.37.205.81 / Your IP : 216.73.216.76 Web Server : nginx/1.22.1 System : Linux vps-249481fa 6.1.0-50-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.176-1 (2026-07-02) x86_64 User : debian ( 1000) PHP Version : 8.2.32 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /proc/1006327/root/opt/ots-api/ |
Upload File : |
from flask import Flask, request, jsonify
import subprocess
import os
import hashlib
API_TOKEN = "jb8lmJTpKUYl3n7nqhRTiCtwDutzfLWBFvmz2HNcbcg"
BASE = "/var/copyrightchain"
PENDING = f"{BASE}/pending"
OTS = f"{BASE}/ots"
ANCHORED = f"{BASE}/anchored"
LOGS = f"{BASE}/logs"
app = Flask(__name__)
def auth(req) -> bool:
return req.headers.get("Authorization", "") == f"Bearer {API_TOKEN}"
def ensure_dirs():
os.makedirs(PENDING, exist_ok=True)
os.makedirs(OTS, exist_ok=True)
os.makedirs(ANCHORED, exist_ok=True)
os.makedirs(LOGS, exist_ok=True)
def is_hex64(s: str) -> bool:
if not isinstance(s, str) or len(s) != 64:
return False
for c in s:
if c not in "0123456789abcdefABCDEF":
return False
return True
def stamp_digest(digest: str):
"""
Create pending/<digest>.txt containing the digest itself (newline-terminated),
then run 'ots stamp' on it, move results to OTS folder.
"""
ensure_dirs()
digest = digest.strip().lower()
txt_name = f"{digest}.txt"
txt_path = os.path.join(PENDING, txt_name)
# Write only the hash string as the notarized content
with open(txt_path, "wb") as f:
f.write((digest + "\n").encode("utf-8"))
r = subprocess.run(["ots", "stamp", txt_path], capture_output=True, text=True)
if r.returncode != 0:
return None, {
"error": "ots_stamp_failed",
"code": r.returncode,
"stderr": (r.stderr or "")[-500:],
"stdout": (r.stdout or "")[-500:]
}
stamped = []
ots_src = txt_path + ".ots"
if os.path.exists(ots_src):
ots_dst = os.path.join(OTS, os.path.basename(ots_src))
os.rename(ots_src, ots_dst)
stamped.append(os.path.basename(ots_dst))
# Move the .txt to /ots/ too
os.rename(txt_path, os.path.join(OTS, txt_name))
return {
"stamped": stamped,
"digest": digest,
"txt": txt_name,
"mode": "hash"
}, None
@app.route("/stamp", methods=["POST"])
def stamp():
if not auth(request):
return jsonify({"error": "unauthorized"}), 401
# --- 1) HASH-only JSON mode ---
if request.is_json:
data = request.get_json(silent=True) or {}
h = (data.get("hash") or "").strip()
if not is_hex64(h):
return jsonify({"error": "invalid_hash"}), 400
res, err = stamp_digest(h)
if err:
return jsonify(err), 500
return jsonify(res), 200
# --- 2) Backward compatibility: multipart file upload mode ---
up = request.files.get("file")
if up is None:
return jsonify({"error": "missing_file_or_json_hash"}), 400
raw = up.read()
if not raw:
return jsonify({"error": "empty_file"}), 400
# If uploaded content is exactly a 64-hex digest, use it directly.
# Otherwise compute sha256(file_bytes).
try:
s = raw.decode("utf-8", errors="ignore").strip()
except Exception:
s = ""
if is_hex64(s):
digest = s.lower()
else:
digest = hashlib.sha256(raw).hexdigest()
# IMPORTANT: even in file mode, we stamp ONLY the digest (not the file bytes)
res, err = stamp_digest(digest)
if err:
return jsonify(err), 500
res["mode"] = "file_to_hash"
return jsonify(res), 200
@app.route("/upgrade", methods=["POST"])
def upgrade():
if not auth(request):
return jsonify({"error": "unauthorized"}), 401
ensure_dirs()
upgraded = []
pending = []
failed = []
for f in os.listdir(OTS):
if not f.endswith(".ots"):
continue
path = os.path.join(OTS, f)
r = subprocess.run(["ots", "upgrade", path], capture_output=True, text=True)
out = (r.stdout or "")
err = (r.stderr or "")
if r.returncode == 0:
upgraded.append(f)
else:
tail_msg = (err + "\n" + out).strip()
tail_msg = tail_msg[-600:]
if ("Timestamp not complete" in tail_msg) or ("Pending confirmation" in tail_msg):
pending.append({"file": f, "message": tail_msg})
else:
failed.append({"file": f, "code": r.returncode, "message": tail_msg})
return jsonify({"upgraded": upgraded, "pending": pending, "failed": failed}), 200
@app.route("/status", methods=["GET"])
def status():
ensure_dirs()
return jsonify({
"pending": os.listdir(PENDING),
"ots": os.listdir(OTS),
"anchored": os.listdir(ANCHORED)
})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)