U
    g                     @   sn  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZ	d dl
Z	d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlmZmZ ddlmZmZmZ ddlmZ ddl m!Z!m"Z"m#Z# ddl$m%Z%m&Z& ddl'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 dd	l2m3Z3 dd
l4m5Z5 dddddddhZ6e6ddhB Z7G dd de3Z8dd Z9G dd de)Z:dd Z;de8 fdddddZ<dd  Z=d!d" Z>d#d$ Z?d%d& Z@d'd( ZAd)d* ZBG d+d, d,ZCdd-d.d/ZDG d0d1 d1eCZEG d2d3 d3eCZFG d4d5 d5eCZGd6d7 ZHG d8d9 d9eIZJG d:d; d;ZKd<d= ZLd>d? ZMd@dA ZNdBdC ZOde8 fdDdEZPG dFdG dGeZQG dHdI dIeZReRjST ZUdJdK ZVdLdM ZWdNdO ZXdPdQ ZYdRdS ZZdTdU Z[dVdW Z\dXdY Z]dZd[ Z^dwd]d^Z_d_d` Z`dadb Zadcdd Zbdedf Zcdgdh Zddidj Zedkdl Zfdmdn Zgdodp ZhdxdqdrZiG dsdt dte	jjjkZlG dudv dve	jmjnZodS )y    N)Enumauto   )aes_cbc_decrypt_bytes aes_gcm_decrypt_and_verify_bytesunpad_pkcs7)compat_os_name)!_SECRETSTORAGE_UNAVAILABLE_REASONsecretstoragesqlite3)MultilinePrinterQuietMultilinePrinter)
DownloadErrorYoutubeDLErrorPopenerror_to_strexpand_pathis_path_likesanitize_urlstr_or_nonetry_callwrite_string)
_YDLLogger)normalize_urlbravechromechromiumedgeoperavivaldiwhalefirefoxsafaric                       s6   e Zd Zd fdd	ZG dd deZdd Z  ZS )		YDLLoggerFc                    s   t  j||dS )N)once)superwarning)selfmessage	only_once	__class__ 2/tmp/pip-unpacked-wheel-q5ljy6pj/yt_dlp/cookies.pyr&   7   s    zYDLLogger.warningc                   @   s   e Zd Zd\ZZdd ZdS )zYDLLogger.ProgressBar)g?r   c                 C   s4   t   | j | jkr0| d| d t   | _d S )Nz
[Cookies] r   )time_timer_DELAYZprint_at_line)r'   r(   r,   r,   r-   print=   s    zYDLLogger.ProgressBar.printN)__name__
__module____qualname__r0   r/   r1   r,   r,   r,   r-   ProgressBar:   s   r5   c                 C   sh   | j r"| j jds"| j jdr&dS | j jj}z| s@W dS W n tk
rX   Y dS X | j|ddS )z8Return a context manager with a print method. (Optional)Z
noprogressloggerNF)Zpreserve_output)Z_ydlparamsgetZ
_out_fileserrorisattyBaseExceptionr5   )r'   filer,   r,   r-   progress_barB   s    "

zYDLLogger.progress_bar)F)r2   r3   r4   r&   r   r5   r=   __classcell__r,   r,   r*   r-   r#   6   s   r#   c                 C   s.   t | dr|  }|r|S t }dd |_|S )Nr=   c                 S   s   d S Nr,   )_r,   r,   r-   <lambda>V       z&_create_progress_bar.<locals>.<lambda>)hasattrr=   r   r1   )r6   printerr,   r,   r-   _create_progress_barP   s    

rE   c                   @   s   e Zd ZdS )CookieLoadErrorNr2   r3   r4   r,   r,   r,   r-   rF   Z   s   rF   c           
   	   C   s   zg }|d k	r:t | \}}}}|t||t|||d | d k	rt| }|rVt| } t| }	|rpt| tj	rx|	
  ||	 t|W S  tk
r   tdY nX d S )Nkeyring	containerzfailed to load cookies)_parse_browser_specificationappendextract_cookies_from_browserr#   r   r   YoutubeDLCookieJarosaccessR_OKload_merge_cookie_jars	ExceptionrF   )
Zcookie_fileZbrowser_specificationZydlZcookie_jarsbrowser_nameprofilerI   rJ   is_filenamejarr,   r,   r-   load_cookies^   s$    

rY   rH   c                C   sN   | dkrt |||S | dkr&t||S | tkr<t| |||S td|  d S )Nr!   r"   zunknown browser: )_extract_firefox_cookies_extract_safari_cookiesCHROMIUM_BASED_BROWSERS_extract_chrome_cookies
ValueError)rU   rV   r6   rI   rJ   r,   r,   r-   rM   u   s    
rM   c                    s  | d ts|d t S d kr2tt }n$trBg}nfddt D }dtt	|}t
t|}|d krtd| |d| d d } d	krDtjtj|d
}tj|rt|tjstd| t|dd}t|dg }	W 5 Q R X t fdd|	D d }t|tsDtd  dtjddl}
d }zHt ||
}t|tr|d  d|  |!dd| d| df n* dkr|d |!d n
|!d t }t"|}|# }t$|}t%|D ]t\}\}}}}}}|&d|dd |d t'j(j)d!||d d"|t*||+d#|t*|||d"d d i d$}|,| qW 5 Q R X | d%t$| d& |W W  5 Q R  S |d k	r|j  X W 5 Q R X d S )'NzExtracting cookies from firefoxzzCannot extract cookies from firefox without sqlite3 support. Please use a Python interpreter compiled with sqlite3 supportc                    s   g | ]}t j| qS r,   )rO   pathjoin).0r_   )rV   r,   r-   
<listcomp>   s     z,_extract_firefox_cookies.<locals>.<listcomp>z, z+could not find firefox cookies database in Extracting cookies from: "")Nnonezcontainers.jsonz"could not read containers.json in utf8encoding
identitiesc                 3   s6   | ].   d t fddfkr  dV  qdS )namec                      s   t d d  S )NzuserContext([^\.]+)\.labelZl10nID)re	fullmatchgroupr,   contextr,   r-   rA      rB   z4_extract_firefox_cookies.<locals>.<genexpr>.<lambda>ZuserContextIdN)r8   r   )ra   )rJ   rn   r-   	<genexpr>   s      z+_extract_firefox_cookies.<locals>.<genexpr>z"could not find firefox container "z" in containers.jsonyt_dlpprefixz-Only loading cookies from firefox container "z", ID zzSELECT host, name, value, path, expiry, isSecure FROM moz_cookies WHERE originAttributes LIKE ? OR originAttributes LIKE ?z%userContextId=z&%re   z3Only loading cookies not belonging to any containerztSELECT host, name, value, path, expiry, isSecure FROM moz_cookies WHERE NOT INSTR(originAttributes,"userContextId=")zASELECT host, name, value, path, expiry, isSecure FROM moz_cookiesLoading cookie  6d/r   F.versionrj   valueportport_specifieddomaindomain_specifieddomain_initial_dotr_   path_specifiedsecureexpiresdiscardcommentcomment_urlrest
Extracted z cookies from firefox)-infor   r&   rN   list_firefox_browser_dirs_is_pathr`   maprepr_newest_firefox_cookie_dbsFileNotFoundErrordebugrO   r_   dirnameisfilerP   rQ   openjsonrR   r8   next
isinstanceintr^   tempfileTemporaryDirectory
connectionclose_open_database_copyexecuterE   fetchalllen	enumerater1   http	cookiejarCookiebool
startswith
set_cookie)rV   rJ   r6   Zsearch_rootssearch_rootcookie_database_pathZcontainer_idZcontainers_pathZ
containersri   tmpdircursorrX   r=   tabletotal_cookie_countihostrj   rz   r_   Zexpiry	is_securecookier,   )rJ   rV   r-   rZ      s    







            
rZ   c                   c   sL   t jdkrtjdV  n.t jdkr4tjdV  nttjjdE d H  d S )Ncygwinwin32z"%APPDATA%\Mozilla\Firefox\Profilesdarwinz.~/Library/Application Support/Firefox/Profiles)z~/.mozilla/firefoxz&~/snap/firefox/common/.mozilla/firefoxz/~/.var/app/org.mozilla.firefox/.mozilla/firefox)sysplatformrO   r_   
expandvars
expanduserr   r,   r,   r,   r-   r      s
    

r   c              	   c   s>   t tjj| D ]*}dD ] }ttj||dE d H  qqd S )N) z*/zProfiles/*/zcookies.sqlite)r   rO   r_   abspathglobiglobr`   )rootsrootpatternr,   r,   r-   r      s    r   c              
   C   s  t jdkrtjd}tjd}tj|dtj|dtj|dtj|dtj|dtj|d	tj|d
d|  }nt jdkrtjd}tj|dtj|dtj|dtj|dtj|dtj|dtj|dd|  }ndt }tj|dtj|dtj|dtj|dtj|dtj|dtj|dd|  }dddt jdkrrdndt jdkrdndt jdkrdnddd|  }dh}||| |kdS ) Nr   z%LOCALAPPDATA%z	%APPDATA%z%BraveSoftware\Brave-Browser\User DatazGoogle\Chrome\User DatazChromium\User DatazMicrosoft\Edge\User DatazOpera Software\Opera StablezVivaldi\User DatazNaver\Naver Whale\User Data)r   r   r   r   r   r   r    r   z~/Library/Application SupportzBraveSoftware/Brave-BrowserzGoogle/ChromeZChromiumzMicrosoft Edgezcom.operasoftware.OperaZVivaldizNaver/Whalezgoogle-chromer   zmicrosoft-edger   r   znaver-whaleZBraveZChromeZOperaZWhale)browser_dirkeyring_namesupports_profiles)r   r   rO   r_   r   r`   r   _config_home)rU   Zappdata_localZappdata_roamingr   Zappdataconfigr   Zbrowsers_without_profilesr,   r,   r-   $_get_chromium_based_browser_settings   sf    



r   c                 C   s  | d|   ts,|d|  d t S t| }|d krF|d }n^t|rp|}|d rftj|n||d< n4|d rtj	|d |}n|
|  d |d }tt|d|}|d krtd|  d	| d
|d| d
 t|d |d ||d}tjdd}d }	zzPt||}	t|	j_t|	d}
d|
krBdnd}|	d| d t }d}d}t|}|	 }t|}t|D ]b\}}|d|dd|d t|f| \}}|s|d7 }qn|s|d7 }|| qW 5 Q R X |dkrd| d}nd}| dt| d|  |  |j ! }||d< |d |  |W W dW  5 Q R  S  t"k
r } z2t#d!kr|j$d"krd#}|
| t%| W 5 d }~X Y nX W 5 |	d k	r|	j  X W 5 Q R X d S )$NzExtracting cookies from zCannot extract cookies from zW without sqlite3 support. Please use a Python interpreter compiled with sqlite3 supportr   r   z does not support profilesZCookieszcould not find z cookies database in "rd   rc   r   rI   rq   rr   cookiesr   r   zBSELECT host_key, name, value, encrypted_value, path, expires_utc, z FROM cookiesr   rt   ru   rv   r    (z could not be decrypted)r   r   z cookies from Zunencryptedzcookie version breakdown: nt   zgCould not copy Chrome cookie database. See  https://github.com/yt-dlp/yt-dlp/issues/7271  for more info)&r   r   r&   rN   r   r   rO   r_   r   r`   r9   r   _find_filesr   r   get_cookie_decryptorr   r   r   r   r   bytesZtext_factory_get_column_namesr   rE   r   r   r   r1   _process_chrome_cookier   _cookie_countscopyPermissionErrorr   errnor   )rU   rV   rI   r6   r   r   r   	decryptorr   r   Zcolumn_namesZsecure_columnrX   Zfailed_cookiesZunencrypted_cookiesr=   r   r   r   lineis_encryptedr   Zfailed_messagecountsr9   r(   r,   r,   r-   r]     st    







r]   c           	      C   s   |  }|  }|  }|  }| o(|}|rH| |}|d krH|d fS |sPd }|tjjd||d d|t||d|t|||dd d i dfS )Nr   Frw   rx   )decodedecryptr   r   r   r   r   )	r   Zhost_keyrj   rz   encrypted_valuer_   Zexpires_utcr   r   r,   r,   r-   r   ^  s:    

            r   c                   @   s   e Zd ZdZi Zdd ZdS )ChromeCookieDecryptoraf  
    Overview:

        Linux:
        - cookies are either v10 or v11
            - v10: AES-CBC encrypted with a fixed key
                - also attempts empty password if decryption fails
            - v11: AES-CBC encrypted with an OS protected key (keyring)
                - also attempts empty password if decryption fails
            - v11 keys can be stored in various places depending on the activate desktop environment [2]

        Mac:
        - cookies are either v10 or not v10
            - v10: AES-CBC encrypted with an OS protected key (keyring) and more key derivation iterations than linux
            - not v10: 'old data' stored as plaintext

        Windows:
        - cookies are either v10 or not v10
            - v10: AES-GCM encrypted with a key which is encrypted with DPAPI
            - not v10: encrypted with DPAPI

    Sources:
    - [1] https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/os_crypt/
    - [2] https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/os_crypt/sync/key_storage_linux.cc
        - KeyStorageLinux::CreateService
    c                 C   s   t dd S )Nz"Must be implemented by sub classes)NotImplementedError)r'   r   r,   r,   r-   r     s    zChromeCookieDecryptor.decryptN)r2   r3   r4   __doc__r   r   r,   r,   r,   r-   r   v  s   r   r   c                C   s6   t jdkrt||S t jdkr(t| |S t|||dS )Nr   )r   r   r   )r   r   MacChromeCookieDecryptorWindowsChromeCookieDecryptorLinuxChromeCookieDecryptor)browser_rootbrowser_keyring_namer6   rI   r,   r,   r-   r     s
    



r   c                   @   s<   e Zd ZddddZejdd Zedd Zd	d
 Z	dS )r   Nr   c                C   s<   || _ | d| _| d| _dddd| _|| _|| _d S )Ns   peanutsrB   r   )v10v11other)_logger
derive_key_v10_key
_empty_keyr   _browser_keyring_name_keyring)r'   r   r6   rI   r,   r,   r-   __init__  s    z#LinuxChromeCookieDecryptor.__init__c                 C   s(   t | j| j| j}|d krd S | |S r?   )_get_linux_keyring_passwordr   r   r   r   )r'   passwordr,   r,   r-   _v11_key  s    z#LinuxChromeCookieDecryptor._v11_keyc                 C   s   t | ddddS )N	   saltysaltr      salt
iterations
key_lengthpbkdf2_sha1r   r,   r,   r-   r     s    z%LinuxChromeCookieDecryptor.derive_keyc                 C   s   |dd }|dd }|dkrH| j d  d7  < t|| j| jf| jS |dkr| j d  d7  < | jdkr| jjdd	d
 dS t|| j| jf| jS | jjd| dd	d
 | j d  d7  < dS dS )a  

        following the same approach as the fix in [1]: if cookies fail to decrypt then attempt to decrypt
        with an empty password. The failure detection is not the same as what chromium uses so the
        results won't be perfect

        References:
            - [1] https://chromium.googlesource.com/chromium/src/+/bbd54702284caca1f92d656fdcadf2ccca6f4165%5E%21/
                - a bugfix to try an empty password as a fallback
        N      v10r   r   s   v11r   z(cannot decrypt v11 cookies: no key foundTr)   zunknown cookie version: "rd   r   )r   _decrypt_aes_cbc_multir   r   r   r   r&   r'   r   ry   
ciphertextr,   r,   r-   r     s    
z"LinuxChromeCookieDecryptor.decrypt)
r2   r3   r4   r   	functoolscached_propertyr   staticmethodr   r   r,   r,   r,   r-   r     s   

r   c                   @   s(   e Zd Zdd Zedd Zdd ZdS )r   c                 C   s8   || _ t||}|d krd n| || _ddd| _d S Nr   )r   r   )r   _get_mac_keyring_passwordr   r   r   )r'   r   r6   r   r,   r,   r-   r     s    
z!MacChromeCookieDecryptor.__init__c                 C   s   t | ddddS )Nr   i  r   r   r   r   r,   r,   r-   r     s    z#MacChromeCookieDecryptor.derive_keyc                 C   s|   |d d }|dd  }|dkrb| j d  d7  < | jd krP| jjddd d S t|| jf| jS | j d  d7  < |S d S )	Nr   r   r   r   (cannot decrypt v10 cookies: no key foundTr   r   )r   r   r   r&   r   r   r,   r,   r-   r     s    
z MacChromeCookieDecryptor.decryptN)r2   r3   r4   r   r  r   r   r,   r,   r,   r-   r     s   
r   c                   @   s   e Zd Zdd Zdd ZdS )r   c                 C   s"   || _ t||| _ddd| _d S r  )r   _get_windows_v10_keyr   r   )r'   r   r6   r,   r,   r-   r     s    z%WindowsChromeCookieDecryptor.__init__c           	      C   s   |d d }|dd  }|dkr| j d  d7  < | jd krP| jjddd d S d}d	}|}|d | }|||  }|| d  }t|| j||| jS | j d
  d7  < t|| j S d S )Nr   r   r   r   r  Tr      r   r   )r   r   r   r&   _decrypt_aes_gcm_decrypt_windows_dpapir   )	r'   r   ry   r   Znonce_lengthZauthentication_tag_lengthZraw_ciphertextnonceauthentication_tagr,   r,   r-   r     s     
z$WindowsChromeCookieDecryptor.decryptN)r2   r3   r4   r   r   r,   r,   r,   r-   r     s   r   c              	   C   s   t jdkrtdt j | r@tj| }tj|stdnBtjd}tj|s|d tjd}tj|stdt	|d}|
 }W 5 Q R X t||d	}|d
t| d |S )Nr   zunsupported platform: z(custom safari cookies database not foundz'~/Library/Cookies/Cookies.binarycookiesz Trying secondary cookie locationzP~/Library/Containers/com.apple.Safari/Data/Library/Cookies/Cookies.binarycookiesz&could not find safari cookies databaserb)r6   r   z cookies from safari)r   r   r^   rO   r_   r   r   r   r   r   readparse_safari_cookiesr   r   )rV   r6   Zcookies_pathfZcookies_datarX   r,   r,   r-   r[     s"    


r[   c                   @   s   e Zd ZdS )ParserErrorNrG   r,   r,   r,   r-   r  2  s   r  c                   @   s^   e Zd Zdd Zdd Zdd Zddd	Zdd
dZdd ZdddZ	dddZ
dddZdS )
DataParserc                 C   s   || _ d| _|| _d S )Nr   )_datar   r   )r'   datar6   r,   r,   r-   r   7  s    zDataParser.__init__c                 C   sR   |dk rt d| d| j| }|t| jkr8t d| j| j| }|| _|S )Nr   zinvalid read of  byteszreached end of input)r  r   r   r  )r'   	num_bytesendr  r,   r,   r-   
read_bytes<  s    
zDataParser.read_bytesc                 C   s6   |  t|}||kr2td| d| d| dd S )Nzunexpected value: z != r   ))r  r   r  )r'   Zexpected_valuer(   rz   r,   r,   r-   expect_bytesF  s    zDataParser.expect_bytesFc                 C   s"   |rdnd}t || dd S )Nz>Iz<I   r   structunpackr  r'   
big_endianZdata_formatr,   r,   r-   	read_uintK  s    zDataParser.read_uintc                 C   s"   |rdnd}t || dd S )Nz>dz<d   r   r  r  r,   r,   r-   read_doubleO  s    zDataParser.read_doublec                 C   s4   g }|  d}|dkr$d| S || qd S )Nr       rB   )r  r`   r   rL   )r'   buffercr,   r,   r-   read_cstringS  s
    
zDataParser.read_cstringunknownc              
   C   sJ   |dkr.| j d| d| d| | n|dk rFtd| dd S )Nr   z	skipping z bytes (z): zinvalid skip of r  )r   r   r  r  )r'   r  descriptionr,   r,   r-   skip\  s    &zDataParser.skipc                 C   s   |  || j | d S r?   )r)  r   )r'   offsetr(  r,   r,   r-   skip_tob  s    zDataParser.skip_toc                 C   s   |  t| j| d S r?   )r+  r   r  )r'   r(  r,   r,   r-   skip_to_ende  s    zDataParser.skip_to_endN)F)F)r'  )r'  )r'  )r2   r3   r4   r   r  r  r   r"  r&  r)  r+  r,  r,   r,   r,   r-   r  6  s   


	

r  c              	   C   s.   t tjdddddtjjdtj| d  S )Ni  r   r   )tzinfo)seconds)r   dtdatetimetimezoneutc	timedelta	timestamp)r4  r,   r,   r-   _mac_absolute_time_to_posixi  s    r5  c                    sB   t | |  dd  jdd} fddt|D }| jfS )Ns   cookzdatabase signatureTr  c                    s   g | ]} j d dqS )Tr6  r   ra   r@   pr,   r-   rb   q  s     z0_parse_safari_cookies_header.<locals>.<listcomp>)r  r  r   ranger   )r  r6   Znumber_of_pages
page_sizesr,   r9  r-   _parse_safari_cookies_headerm  s
    
r=  c           	   	      s   t | |  dd   } fddt|D }|dkrV|dt|  d d S  |d d t|\}t|D ]L\}}|	d	|d
d|d
  |d t
| |d  ||} | qxW 5 Q R X  d d S )Ns      zpage signaturec                    s   g | ]}   qS r,   r7  r8  r9  r,   r-   rb   y  s     z._parse_safari_cookies_page.<locals>.<listcomp>r   za cookies page of size z has no cookieszunknown page header fieldrt   ru   rv   zspace between recordszspace in between pages)r  r  r   r;  r   r   r+  rE   r   r1   _parse_safari_cookies_recordr  r,  )	r  rX   r6   Znumber_of_cookiesZrecord_offsetsr=   r   Zrecord_offsetZrecord_lengthr,   r9  r-   _parse_safari_cookies_pageu  s    

r?  c                 C   sJ  t | |}| }|dd | }t|d@ }|dd | }| }| }	| }
|dd t| }t| }zL|| | }|| | }||	 | }||
 | }W n& tk
r   |j	ddd	 | Y S X ||d
 t
jjd||d d|t||d|t|||dd d i d}|| |S )Nr  zunknown record field 1r   zunknown record field 2r!  zunknown record field 3z;failed to parse Safari cookie because UTF-8 decoding failedTr   zspace at the end of the recordr   Frw   rx   )r  r   r)  r   r5  r"  r+  r&  UnicodeDecodeErrorr&   r   r   r   r   r   )r  rX   r6   r:  Zrecord_sizeflagsr   Zdomain_offsetZname_offsetZpath_offsetZvalue_offsetZexpiration_dateZ_creation_dater}   rj   r_   rz   r   r,   r,   r-   r>    s\    





            
r>  c                 C   sX   |dkrt  }t| |\}}t| |d |}|D ]}t|||| q2|d |S )a9  
    References:
        - https://github.com/libyal/dtformats/blob/main/documentation/Safari%20Cookies.asciidoc
            - this data appears to be out of date but the important parts of the database structure is the same
            - there are a few bytes here and there which are skipped during parsing
    Nfooter)rN   r=  r  r?  r  r,  )r  rX   r6   r<  Z
body_startr:  Z	page_sizer,   r,   r-   r    s    
r  c                   @   s^   e Zd ZdZe Ze Ze Ze Ze Z	e Z
e Ze Ze Ze Ze Ze Ze ZdS )_LinuxDesktopEnvironmentzu
    https://chromium.googlesource.com/chromium/src/+/refs/heads/main/base/nix/xdg_util.h
    DesktopEnvironment
    N)r2   r3   r4   r   r   OTHERCINNAMONDEEPINGNOMEKDE3KDE4KDE5KDE6PANTHEONUKUIUNITYXFCELXQTr,   r,   r,   r-   rC    s   rC  c                   @   s.   e Zd ZdZe Ze Ze Ze Ze Z	dS )_LinuxKeyringz
    https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/os_crypt/sync/key_storage_util_linux.h
    SelectedLinuxBackend
    N)
r2   r3   r4   r   r   KWALLETKWALLET5KWALLET6GNOMEKEYRING	BASICTEXTr,   r,   r,   r-   rQ    s   rQ  c                 C   s<  |  dd}|  dd}|dk	rlttj|dD ] }|dkrh|dk	r\d|kr\tj  S tj  S q4|dkrztj  S |dkrtj  S |d	krtj	  S |d
kr|  dd}|dkrtj
  S |dkrtj  S |dkrtj  S |d| d tj  S q4|dkrtj  S |dkr0tj  S |dkrDtj  S |dkr4tj  S q4|d| d n|dk	r|dkrtjS |dkrtjS |dkrtjS |dkrd| krtjS tjS n<d|ks|dkrtjS |dkrtjS |d| d n0d| krtjS d | kr6d| kr0tjS tjS tjS )!zy
    https://chromium.googlesource.com/chromium/src/+/refs/heads/main/base/nix/xdg_util.cc
    GetDesktopEnvironment
    ZXDG_CURRENT_DESKTOPNZDESKTOP_SESSION:ZUnityzgnome-fallbackZDeepinrG  z
X-CinnamonZKDEZKDE_SESSION_VERSION564zunknown KDE version: "z". Assuming KDE4ZPantheonrO  rM  ZLXQtz1XDG_CURRENT_DESKTOP is set to an unknown value: "rd   Zdeepin)ZmateZgnome)Zkde4z
kde-plasmaZkdeZxfceZxubuntuZukuiz-DESKTOP_SESSION is set to an unknown value: "ZGNOME_DESKTOP_SESSION_IDZKDE_FULL_SESSION)r8   r   strstripsplitrC  rG  rN  rF  rE  rJ  rK  rI  r   rL  rO  rM  rP  rH  rD  )envr6   Zxdg_current_desktopZdesktop_sessionpartZkde_versionr,   r,   r-   _get_linux_desktop_environment  sp    
























r`  c                 C   sz   t tj| }| d|j  |tjkr0tj}nF|tj	krBtj
}n4|tjkrTtj}n"|tjtjtjfkrptj}ntj}|S )aG  
    SelectBackend in [1]

    There is currently support for forcing chromium to use BASIC_TEXT by creating a file called
    `Disable Local Encryption` [1] in the user data dir. The function to write this file (`WriteBackendUse()` [1])
    does not appear to be called anywhere other than in tests, so the user would have to create this file manually
    and so would be aware enough to tell yt-dlp to use the BASIC_TEXT keyring.

    References:
        - [1] https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/os_crypt/sync/key_storage_util_linux.cc
    zdetected desktop environment: )r`  rO   environr   rj   rC  rI  rQ  rR  rJ  rS  rK  rT  rH  rP  rD  rV  rU  )r6   Zdesktop_environmentZlinux_keyringr,   r,   r-   _choose_linux_keyring.  s     


  rb  c           	   
   C   s   d}z| t jkrd}d}n0| t jkr.d}d}n| t jkrBd}d}nt| tjdd	d
d| |dgdtjtj	d\}}}|r|
d |W S |d|  d | W S W n: tk
r } z|
d|  | W Y S d}~X Y nX dS )ag   The name of the wallet used to store network passwords.

    https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/os_crypt/sync/kwallet_dbus.cc
    KWalletDBus::NetworkWallet
    which does a dbus call to the following function:
    https://api.kde.org/frameworks/kwallet/html/classKWallet_1_1Wallet.html
    Wallet::NetworkWallet
    Z	kdewalletzorg.kde.kwalletdz/modules/kwalletdzorg.kde.kwalletd5z/modules/kwalletd5zorg.kde.kwalletd6z/modules/kwalletd6z	dbus-sendz	--sessionz--print-reply=literalz--dest=zorg.kde.KWallet.networkWalletT)textstdoutstderrzfailed to read NetworkWalletzNetworkWallet = "rd   z)exception while obtaining NetworkWallet: N)rQ  rR  rS  rT  r^   r   run
subprocessPIPEDEVNULLr&   r   r\  rT   )	rI   r6   Zdefault_walletZservice_nameZwallet_pathrd  r@   
returncodeer,   r,   r-   _get_kwallet_network_walletK  s@    	


    
rl  c              
   C   s  | d|j  tdd kr.|d dS t||}ztjdd|  dd|  d|gtj	tj
d	\}}}|r|d
| d W dS | dr| d W dS | d |dW S W n> tk
 r } z|dt|  W Y dS d }~X Y nX d S )Nz,using kwallet-query to obtain password from zkwallet-queryzkwallet-query command not found. KWallet and kwallet-query must be installed to read from KWallet. kwallet-query should beincluded in the kwallet package for your distributionrB   z--read-password Safe Storagez--folderz Keysrd  re  z&kwallet-query failed with return code z7. Please consult the kwallet-query man page for detailss   failed to readz@failed to read password from kwallet. Using empty string insteadzpassword found   
z!exception running kwallet-query: )r   rj   shutilwhichr9   rl  r   rf  rg  rh  ri  lowerr   rstriprT   r&   r   )r   rI   r6   Znetwork_walletrd  r@   rj  rk  r,   r,   r-   _get_kwallet_passwordt  s8    

   
	
rt  c              
   C   s   t s|dt  dS tt  \}t |}| D ].}| |  dkr:|	   W  5 Q R  S q:|d W 5 Q R  dS Q R X d S )Nzsecretstorage not available rB   rm  zfailed to read from keyring)
r
   r9   r	   
contextlibclosingZ	dbus_initZget_default_collectionZget_all_itemsZ	get_labelZ
get_secret)r   r6   concolitemr,   r,   r-   _get_gnome_keyring_password  s    

rz  c                 C   s~   |rt | nt|}|d|j  |t jt jt jfkrFt| ||S |t jkrZt	| |S |t j
krhd S dsztd| d S )NzChosen keyring: FzUnknown keyring )rQ  rb  r   rj   rR  rS  rT  rt  rU  rz  rV  AssertionError)r   rI   r6   r,   r,   r-   r     s    


r   c              
   C   s   | d zNtjdddd| d|  dgtjtjd\}}}|rN|d	 W d S |d
W S  tk
r } z|dt	|  W Y d S d }~X Y nX d S )Nz@using find-generic-password to obtain password from OSX keychainsecurityzfind-generic-passwordz-wz-az-srm  rn  zfind-generic-password failedro  z)exception running find-generic-password: )
r   r   rf  rg  rh  ri  r&   rs  rT   r   )r   r6   rd  r@   rj  rk  r,   r,   r-   r    s(    
   
r  c              	   C   s   t t| d|}|dkr&|d dS |d| d t|dd}t|}W 5 Q R X z|d d	 }W n  tk
r   |d
 Y dS X t	|}d}|
|s|d dS t|t|d |S )z
    References:
        - [1] https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/os_crypt/sync/os_crypt_win.cc
    zLocal StateNzcould not find local state filezFound local state file at "rd   rf   rg   Zos_cryptencrypted_keyzno encrypted key in Local States   DPAPIzinvalid key)r   r   r9   r   r   r   rR   KeyErrorbase64	b64decoder   r	  r   )r   r6   r_   r  r  Z
base64_keyr}  rs   r,   r,   r-   r    s$    




r  c                 C   s   t d| |||S )Nsha1)hashlibpbkdf2_hmac)r   r   r   r   r,   r,   r-   r     s    r                      c              	   C   sP   |D ]8}t t| ||}z| W   S  tk
r:   Y qX q|jddd d S )Nz\failed to decrypt cookie (AES-CBC) because UTF-8 decoding failed. Possibly the key is wrong?Tr   )r   r   r   r@  r&   )r   keysr6   Zinitialization_vectorkey	plaintextr,   r,   r-   r     s    r   c                 C   sl   zt | |||}W n$ tk
r6   |jddd Y d S X z
| W S  tk
rf   |jddd Y d S X d S )Nz[failed to decrypt cookie (AES-GCM) because the MAC check failed. Possibly the key is wrong?Tr   z\failed to decrypt cookie (AES-GCM) because UTF-8 decoding failed. Possibly the key is wrong?)r   r^   r&   r   r@  )r   r  r
  r  r6   r  r,   r,   r-   r     s    
r  c           	         s   ddl  ddl G  fddd j} | }| ||}| } jj |ddddd |}|sd}|	| t
| |j|j} jj|j |S )zt
    References:
        - https://docs.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptunprotectdata
    r   Nc                       s(   e Zd Zd jjfd  jfgZdS )z)_decrypt_windows_dpapi.<locals>.DATA_BLOBcbDatapbDataN)r2   r3   r4   ZwintypesZDWORDPOINTERc_char_fields_r,   ctypesr,   r-   	DATA_BLOB  s   
r  z_Failed to decrypt with DPAPI. See  https://github.com/yt-dlp/yt-dlp/issues/10927  for more info)r  Zctypes.wintypes	Structurecreate_string_buffersizeofwindllZcrypt32ZCryptUnprotectDatabyrefr9   r   	string_atr  r  kernel32Z	LocalFree)	r   r6   r  r$  Zblob_inZblob_outretr(   resultr,   r  r-   r	    s,    
	
r	  c                   C   s   t jdt jdS )NXDG_CONFIG_HOMEz	~/.config)rO   ra  r8   r_   r   r,   r,   r,   r-   r   1  s    r   c                 C   s,   t j|d}t| | t|}| S )Nztemporary.sqlite)rO   r_   r`   rp  r   r   connectr   )Zdatabase_pathr   Zdatabase_copy_pathconnr,   r,   r-   r   5  s    
r   c                 C   s$   |  d| d }dd |D S )NzPRAGMA table_info(r  c                 S   s   g | ]}|d    qS )r   )r   )ra   rowr,   r,   r-   rb   ?  s     z%_get_column_names.<locals>.<listcomp>)r   r   )r   Z
table_nameZ
table_infor,   r,   r-   r   =  s    r   c                 C   s   t | dd d dS )Nc                 S   s   t | jS r?   )rO   lstatst_mtime)r_   r,   r,   r-   rA   C  rB   z_newest.<locals>.<lambda>)r  default)max)filesr,   r,   r-   r   B  s    r   c           	   
   c   sv   d}t |`}t| D ]N\}}}|D ]>}|d7 }|d| d|dd ||kr&tj||V  q&qW 5 Q R X d S )Nr   r   zSearching for "z": ru   z files searched)rE   rO   walkr1   r_   r`   )	r   filenamer6   r   r=   Z	curr_rootr@   r  r<   r,   r,   r-   r   F  s    
r   c                 C   s:   t  }| D ]*}|D ]}|| q|jd k	r
|j|_q
|S r?   )rN   r   r  )ZjarsZ
output_jarrX   r   r,   r,   r-   rS   R  s    

rS   c                    s"   t  fddtjjtjjfD S )Nc                 3   s   | ]}|r| kV  qd S r?   r,   )ra   seprz   r,   r-   rp   ]  s      z_is_path.<locals>.<genexpr>)anyrO   r_   r  altsepr  r,   r  r-   r   \  s    r   c                 C   s\   | t krtd|  d|dtkr4td| d|d k	rPtt|rPt|}| |||fS )Nzunsupported browser: "rd   zunsupported keyring: ")N)SUPPORTED_BROWSERSr^   SUPPORTED_KEYRINGSr   r   )rU   rV   rI   rJ   r,   r,   r-   rK   `  s    rK   c                	       s~   e Zd ZdZded Zeed Zddddd	d
dddh	Zd
dhZ	e
de d e d ejejB Z fddZ  ZS )LenientSimpleCookiez1More lenient version of http.cookies.SimpleCookiez\w\dz!#$%&'*+-.:^_`|~z(),/<=>?@[]{}r   r_   r   r}   zmax-ager   httponlyry   samesitez
        \s*                            # Optional whitespace at start of cookie
        (?P<key>                       # Start of group 'key'
        [au  ]+?# Any word of at least one letter
        )                              # End of group 'key'
        (                              # Optional group: there may not be a value.
        \s*=\s*                          # Equal Sign
        (                                # Start of potential value
        (?P<val>                           # Start of group 'val'
        "(?:[^\\"]|\\.)*"                    # Any doublequoted string
        |                                    # or
        \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT # Special case for "expires" attr
        |                                    # or
        [a	  ]*     # Any word or empty string
        )                                  # End of group 'val'
        |                                  # or
        (?P<bad>(?:\\;|[^;])*?)            # 'bad' group fallback for invalid values
        )                                # End of potential value
        )?                             # End of optional value group
        \s*                            # Any number of spaces.
        (\s+|;|$)                      # Ending either at space, semicolon, or EOS.
        c                    s  t |tst |S d }| j|D ]}|dr:d }q&|dd\}}d}|drh|dd  }d}| }|| j	kr|d krq&|d kr|| j
krd }q&d}n| |\}}|||< q&|rd }q&|d k	r| |tj }| |\}	}
|||	|
 || |< q&d }q&d S )Nbadr  valF$r   T)r   r[  r%   rR   _COOKIE_PATTERNfinditerrm   r   rr  	_RESERVED_FLAGSvalue_decoder8   r   r   Morselset)r'   r  morselmatchr  rz   Zis_attributeZ	lower_keyr@   
real_valuecoded_valuer*   r,   r-   rR     s>    







zLenientSimpleCookie.load)r2   r3   r4   r   rk   escapeZ_LEGAL_KEY_CHARSZ_LEGAL_VALUE_CHARSr  r  compileASCIIVERBOSEr  rR   r>   r,   r,   r*   r-   r  j  s4   
r  c                       s   e Zd ZdZdZdZdZeddZ	d fdd		Z
ed
d ZejddddZdd ZdddZdddZdd Zdd Z fddZ  ZS ) rN   z]
    See [1] for cookie file format.

    1. https://curl.haxx.se/docs/http-cookies.html
    z
#HttpOnly_   zO# Netscape HTTP Cookie File
# This file is generated by yt-dlp.  Do not edit.

ZCookieFileEntry)Zdomain_nameZinclude_subdomainsr_   Z
https_only
expires_atrj   rz   Nc                    s.   t  jd|| t|r$t|}|| _d S )N)N)r%   r   r   rO   fspathr  )r'   r  argskwargsr*   r,   r-   r     s    
zYoutubeDLCookieJar.__init__c                 C   s   | rdS dS )NTRUEFALSEr,   )Zcndnr,   r,   r-   _true_or_false  s    z!YoutubeDLCookieJar._true_or_falseFwritec             	   c   sJ   t |r2t||rdnddd}|V  W 5 Q R X n|r@|d |V  d S )Nwrzutf-8rg   r   )r   r   truncate)r'   r<   r  r  r,   r,   r-   r     s    
zYoutubeDLCookieJar.openc                 C   s   t   }| D ]}|s|js|s*||r*q|j|j }}|d krJd| }}|dd|j| 	|j
d|j| 	|jt|jdd||f qd S )Nr   z{}
	rw   )r  )r.   r   
is_expiredrj   rz   r  formatr`   r}   r  r   r_   r   r   r   )r'   r  ignore_discardignore_expiresnowr   rj   rz   r,   r,   r-   _really_save  s(    


 zYoutubeDLCookieJar._really_saveTc              	   C   sx   |dkr&| j dk	r| j }nttjj| D ]}|jdkr*d|_q*| j|dd }|| j | 	||| W 5 Q R X dS )z
        Save cookies to a file.
        Code is taken from CPython 3.6
        https://github.com/python/cpython/blob/8d999cbf4adea053be6dbb612b9844635c4dfb8e/Lib/http/cookiejar.py#L2091-L2117 Nr   Tr  )
r  r^   r   r   MISSING_FILENAME_TEXTr   r   r  _HEADERr  )r'   r  r  r  r   r  r,   r,   r-   save  s    

zYoutubeDLCookieJar.savec           
         s  |dkr& j dk	r j }nttjj fdd}t } |}|D ]~}z||| W qJ tjj	k
r } zD|
  dd dkrtj	dtd| d	|d
 W Y qJW 5 d}~X Y qJX qJW 5 Q R X |d  ||||  D ]}	|	jdkrd|	_d|	_qdS )zLoad cookies from a file.Nc                    s   |   jr| t jd  } |  ds0|  s4| S | d}t| jkrbtjdt|  j	| }|j
r|j
 stjd|j
 | S )N#r  zinvalid length zinvalid expires at )r   _HTTPONLY_PREFIXr   r\  r]  
_ENTRY_LENr   r   	LoadError_CookieFileEntryr  isdigit)r   Zcookie_listr   r'   r,   r-   prepare_line  s    

z-YoutubeDLCookieJar.load.<locals>.prepare_line r   z[{"zCookies file must be Netscape formatted, not JSON. See  https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlpz+WARNING: skipping cookie file entry due to z: 
T)r  r^   r   r   r  ioStringIOr   r  r  r\  r   seek_really_loadr   r   )
r'   r  r  r  r  cfr  r   rk  r   r,   r  r-   rR     s.    
&


zYoutubeDLCookieJar.loadc                 C   s(   t jtt|}| | |dS )z-Generate a Cookie HTTP header for a given urlr   )urllibrequestRequestr   r   add_cookie_header
get_header)r'   urlZ
cookie_reqr,   r,   r-   get_cookie_headerF  s    
z$YoutubeDLCookieJar.get_cookie_headerc                 C   s0   t t  | j_| _| tjtt	|S )z1Generate a list of Cookie objects for a given url)
r   r.   _policy_now_cookies_for_requestr  r  r  r   r   )r'   r  r,   r,   r-   get_cookies_for_urlL  s    z&YoutubeDLCookieJar.get_cookies_for_urlc              
      s0   t t t j||W  5 Q R  S Q R X d S r?   )ru  suppressr~  r%   clear)r'   r  r  r*   r,   r-   r  S  s    zYoutubeDLCookieJar.clear)N)NTT)NTT)r2   r3   r4   r   r  r  r  collections
namedtupler  r   r  r  ru  contextmanagerr   r  r  rR   r  r  r  r>   r,   r,   r*   r-   rN     s&   
	

3rN   )r  )NNN)pr  r  ru  r0  r/  r   r   r  http.cookiejarr   http.cookiesr  r   rO   rk   rp  r  rg  r   r   r.   urllib.requestr  enumr   r   Zaesr   r   r   compatr   Zdependenciesr	   r
   r   Z
minicursesr   r   utilsr   r   r   r   r   r   r   r   r   r   Zutils._utilsr   Zutils.networkingr   r\   r  r#   rE   rF   rY   rM   rZ   r   r   r   r]   r   r   r   r   r   r   r[   rT   r  r  r5  r=  r?  r>  r  rC  rQ  __members__r  r  r`  rb  rl  rt  rz  r   r  r  r   r   r  r	  r   r   r   r   r   rS   r   rK   r   SimpleCookier  r   MozillaCookieJarrN   r,   r,   r,   r-   <module>   s   0
E<H"3 %3*
G)+
#


[