import glob import os import shutil import sqlite3 import tempfile import time FIREFOX_COOKIE_PATHS = [ "~/.mozilla/firefox/*/cookies.sqlite", "~/snap/firefox/common/.mozilla/firefox/*/cookies.sqlite", "~/.var/app/org.mozilla.firefox/.mozilla/firefox/*/cookies.sqlite", "~/.var/app/org.mozilla.firefox/config/mozilla/firefox/*/cookies.sqlite", ] NO_COOKIE_MSG = ( "Bitte in Firefox bei tralgo.app einloggen und " "'Für 30 Tage merken' aktivieren." ) EXPIRED_MSG = ( "Deine tralgo.app Sitzung ist abgelaufen. " "Bitte erneut in Firefox einloggen und 'Für 30 Tage merken' aktivieren." ) def find_cookies(): """Return (dict of cookie name→value, error_str). On success error_str is None; on failure dict is None.""" all_dbs = [] for pattern in FIREFOX_COOKIE_PATHS: all_dbs.extend(glob.glob(os.path.expanduser(pattern))) if not all_dbs: return None, NO_COOKIE_MSG best_expiry = -1 best_cookies = None for db_path in all_dbs: tmp = None try: tmp = tempfile.mktemp(suffix="_tralgo_cookies.sqlite") shutil.copy2(db_path, tmp) cookies = _read_tralgo_cookies(tmp) if not cookies: continue max_expiry = max(v["expiry"] for v in cookies.values()) if max_expiry > best_expiry: best_expiry = max_expiry best_cookies = cookies except Exception: pass finally: if tmp and os.path.exists(tmp): try: os.unlink(tmp) except OSError: pass if best_cookies is None: return None, NO_COOKIE_MSG now = int(time.time()) if best_expiry < now: return None, EXPIRED_MSG return {name: data["value"] for name, data in best_cookies.items()}, None def _read_tralgo_cookies(db_path): conn = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True) try: cur = conn.cursor() cur.execute( "SELECT name, value, expiry FROM moz_cookies " "WHERE host LIKE '%tralgo.app%' " "AND (name LIKE 'wordpress_logged_in%' OR name LIKE 'wp2fa_device%')" ) rows = cur.fetchall() finally: conn.close() if not rows: return {} return {row[0]: {"value": row[1], "expiry": row[2]} for row in rows}