diff options
author | bashonly <88596187+bashonly@users.noreply.github.com> | 2022-08-30 16:54:46 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-30 22:24:46 +0530 |
commit | 9bd13fe5bbe1df6bb01d4edb68f2c63a4812bf94 (patch) | |
tree | 89c3d7b12a98260c0360f569c86dc9e9b2d23c1d /yt_dlp/cookies.py | |
parent | 459262ac97c039a426f51f3fb3a5d780de5b9dca (diff) | |
download | hypervideo-pre-9bd13fe5bbe1df6bb01d4edb68f2c63a4812bf94.tar.lz hypervideo-pre-9bd13fe5bbe1df6bb01d4edb68f2c63a4812bf94.tar.xz hypervideo-pre-9bd13fe5bbe1df6bb01d4edb68f2c63a4812bf94.zip |
[cookies] Support firefox container in `--cookies-from-browser` (#4753)
Authored by: bashonly
Diffstat (limited to 'yt_dlp/cookies.py')
-rw-r--r-- | yt_dlp/cookies.py | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/yt_dlp/cookies.py b/yt_dlp/cookies.py index 1a164bb31..c5fb5ab68 100644 --- a/yt_dlp/cookies.py +++ b/yt_dlp/cookies.py @@ -3,6 +3,7 @@ import contextlib import http.cookiejar import json import os +import re import shutil import struct import subprocess @@ -24,7 +25,7 @@ from .dependencies import ( sqlite3, ) from .minicurses import MultilinePrinter, QuietMultilinePrinter -from .utils import Popen, YoutubeDLCookieJar, error_to_str, expand_path +from .utils import Popen, YoutubeDLCookieJar, error_to_str, expand_path, try_call CHROMIUM_BASED_BROWSERS = {'brave', 'chrome', 'chromium', 'edge', 'opera', 'vivaldi'} SUPPORTED_BROWSERS = CHROMIUM_BASED_BROWSERS | {'firefox', 'safari'} @@ -85,8 +86,9 @@ def _create_progress_bar(logger): def load_cookies(cookie_file, browser_specification, ydl): cookie_jars = [] if browser_specification is not None: - browser_name, profile, keyring = _parse_browser_specification(*browser_specification) - cookie_jars.append(extract_cookies_from_browser(browser_name, profile, YDLLogger(ydl), keyring=keyring)) + browser_name, profile, keyring, container = _parse_browser_specification(*browser_specification) + cookie_jars.append( + extract_cookies_from_browser(browser_name, profile, YDLLogger(ydl), keyring=keyring, container=container)) if cookie_file is not None: is_filename = YoutubeDLCookieJar.is_path(cookie_file) @@ -101,9 +103,9 @@ def load_cookies(cookie_file, browser_specification, ydl): return _merge_cookie_jars(cookie_jars) -def extract_cookies_from_browser(browser_name, profile=None, logger=YDLLogger(), *, keyring=None): +def extract_cookies_from_browser(browser_name, profile=None, logger=YDLLogger(), *, keyring=None, container=None): if browser_name == 'firefox': - return _extract_firefox_cookies(profile, logger) + return _extract_firefox_cookies(profile, container, logger) elif browser_name == 'safari': return _extract_safari_cookies(profile, logger) elif browser_name in CHROMIUM_BASED_BROWSERS: @@ -112,7 +114,7 @@ def extract_cookies_from_browser(browser_name, profile=None, logger=YDLLogger(), raise ValueError(f'unknown browser: {browser_name}') -def _extract_firefox_cookies(profile, logger): +def _extract_firefox_cookies(profile, container, logger): logger.info('Extracting cookies from firefox') if not sqlite3: logger.warning('Cannot extract cookies from firefox without sqlite3 support. ' @@ -126,6 +128,20 @@ def _extract_firefox_cookies(profile, logger): else: search_root = os.path.join(_firefox_browser_dir(), profile) + container_id = None + if container is not None: + containers_path = os.path.join(search_root, 'containers.json') + if not os.path.isfile(containers_path) or not os.access(containers_path, os.R_OK): + raise FileNotFoundError(f'could not read containers.json in {search_root}') + with open(containers_path, 'r') as containers: + identities = json.load(containers).get('identities', []) + container_id = next((context.get('userContextId') for context in identities if container in ( + context.get('name'), + try_call(lambda: re.fullmatch(r'userContext([^\.]+)\.label', context['l10nID']).group()) + )), None) + if not isinstance(container_id, int): + raise ValueError(f'could not find firefox container "{container}" in containers.json') + cookie_database_path = _find_most_recently_used_file(search_root, 'cookies.sqlite', logger) if cookie_database_path is None: raise FileNotFoundError(f'could not find firefox cookies database in {search_root}') @@ -135,7 +151,18 @@ def _extract_firefox_cookies(profile, logger): cursor = None try: cursor = _open_database_copy(cookie_database_path, tmpdir) - cursor.execute('SELECT host, name, value, path, expiry, isSecure FROM moz_cookies') + origin_attributes = '' + if isinstance(container_id, int): + origin_attributes = f'^userContextId={container_id}' + logger.debug( + f'Only loading cookies from firefox container "{container}", ID {container_id}') + try: + cursor.execute( + 'SELECT host, name, value, path, expiry, isSecure FROM moz_cookies WHERE originAttributes=?', + (origin_attributes, )) + except sqlite3.OperationalError: + logger.debug('Database exception, loading all cookies') + cursor.execute('SELECT host, name, value, path, expiry, isSecure FROM moz_cookies') jar = YoutubeDLCookieJar() with _create_progress_bar(logger) as progress_bar: table = cursor.fetchall() @@ -948,11 +975,11 @@ def _is_path(value): return os.path.sep in value -def _parse_browser_specification(browser_name, profile=None, keyring=None): +def _parse_browser_specification(browser_name, profile=None, keyring=None, container=None): if browser_name not in SUPPORTED_BROWSERS: raise ValueError(f'unsupported browser: "{browser_name}"') if keyring not in (None, *SUPPORTED_KEYRINGS): raise ValueError(f'unsupported keyring: "{keyring}"') if profile is not None and _is_path(profile): profile = os.path.expanduser(profile) - return browser_name, profile, keyring + return browser_name, profile, keyring, container |