#!/usr/bin/env python3
import http.server, socketserver, urllib.parse, json, time, os, sys

ROOT = os.path.dirname(os.path.abspath(__file__))
LOG = os.path.join(ROOT, 'collect.log')
REPORT_URL = 'https://www.wyysgfizke.com:8821/index/Mitmreport/report'
os.makedirs(ROOT, exist_ok=True)

def _route_dir(body, ios_dir, adr_dir):
    """按记录内 platform 字段分目录：Android -> adr_*，其余（iOS）-> 原 ios 目录"""
    try:
        if json.loads(body.decode('utf-8', 'replace')).get('platform') == 'Android':
            return adr_dir
    except Exception:
        pass
    return ios_dir

class H(http.server.BaseHTTPRequestHandler):
    def log_message(self, fmt, *args):
        try: open(os.path.join(ROOT,'access.log'),'a').write(time.strftime('%H:%M:%S')+' '+fmt%args+'\n')
        except Exception: pass
    def _send(self, code, body):
        self.send_response(code)
        self.send_header('Content-Type', 'application/json')
        self.send_header('Content-Length', str(len(body)))
        self.end_headers()
        self.wfile.write(body)
    def do_GET(self):
        p = urllib.parse.urlsplit(self.path)
        path = p.path
        if path.endswith('/collect') or '/collect?' in path:
            q = urllib.parse.parse_qs(p.query)
            rec = {'time': int(time.time()*1000), 'label': (q.get('label') or [''])[0],
                   'data': (q.get('data') or [''])[0], 'ua': self.headers.get('User-Agent'),
                   'ref': self.headers.get('Referer')}
            with open(LOG, 'a') as f:
                f.write(json.dumps(rec, ensure_ascii=False) + '\n')
            print(json.dumps(rec, ensure_ascii=False), flush=True)
            self._send(200, b'{"ok":1}'); return
        if path == '/':
            path = '/stage2.html'
        fp = os.path.normpath(os.path.join(ROOT, path.lstrip('/')))
        if os.path.isfile(fp) and fp.startswith(ROOT) and not fp.endswith('.log') and '/.' not in fp:
            data = open(fp, 'rb').read()
            self.send_response(200)
            self.send_header('Content-Length', str(len(data)))
            self.end_headers(); self.wfile.write(data); return
        self.send_response(404); self.end_headers(); self.wfile.write(b'not found')
    def do_POST(self):
        p = urllib.parse.urlsplit(self.path)
        if p.path.endswith('/save_capture'):
            try:  # 纯抓包变体：只本地落盘，不写 .curl 不转发；Android 分流 adr_capture/
                n = int(self.headers.get('Content-Length') or 0)
                body = self.rfile.read(n) if n > 0 else b''
                d = os.path.join(ROOT, _route_dir(body, 'capture_reports', 'adr_capture'))
                os.makedirs(d, exist_ok=True)
                now = time.time()
                ts = time.strftime('%Y%m%d_%H%M%S', time.localtime(now)) + '_%03d' % int((now % 1) * 1000)
                with open(os.path.join(d, ts + '.json'), 'wb') as f:
                    f.write(body)
                self._send(200, b'{"ok":1}'); return
            except Exception as e:
                self._send(500, json.dumps({'ok': 0, 'err': str(e)}).encode()); return
        if p.path.endswith('/save_mitm'):
            try:
                n = int(self.headers.get('Content-Length') or 0)
                body = self.rfile.read(n) if n > 0 else b''
                d = os.path.join(ROOT, _route_dir(body, 'mitm_reports', 'adr_mitm'))
                os.makedirs(d, exist_ok=True)
                now = time.time()
                ts = time.strftime('%Y%m%d_%H%M%S', time.localtime(now)) + '_%03d' % int((now % 1) * 1000)
                fp = os.path.join(d, ts + '.json')
                with open(fp, 'wb') as f:
                    f.write(body)
                curl = "curl -X POST '%s' -H 'Content-Type: application/json' --data-binary @'%s'\n" % (REPORT_URL, fp)
                with open(os.path.join(d, ts + '.curl'), 'w') as f:
                    f.write(curl)
                self._send(200, b'{"ok":1}'); return
            except Exception as e:
                self._send(500, json.dumps({'ok': 0, 'err': str(e)}).encode()); return
        self.send_response(404); self.end_headers(); self.wfile.write(b'not found')

if __name__ == '__main__':
    port = int(sys.argv[1]) if len(sys.argv) > 1 else 18083
    socketserver.TCPServer.allow_reuse_address = True
    with socketserver.ThreadingTCPServer(('0.0.0.0', port), H) as srv:
        print('serving on', port, flush=True)
        srv.serve_forever()
