+
    ¢THim›  ã                  ór  a € 0 t $ R t^ RIHt ^ RIt^ RIHt ^ RIHt ^ RIH	t	H
t
HtHtHtHtHt ^ RIHt ^ RIHt ]	'       d   ^ RIHtHt ^ R	IHt ^ R
IHtHt ^ RIHt ^ RIHt ^ RI H!t! ^ RI"H#t#H$t$H%t% ^ RI&H't' RR.t(])! 4       t*Rt+Rt,Rt-Rt.R]/R&   Rt0R]/R&   ]! R4      t1]	'       d-   ]]2]R,          ]33,          ]2]R,          ]13,          3,          t4MRt4 ! R R]]1,          4      t5]6! 4       t7R]/R&   R  t8]8! 4       t9R! t:]:! 4       t; ! R" R]5]3,          4      t< ! R# R]5]2]3]33,          ,          4      t=R# )$zApache password support)ÚannotationsN)ÚBytesIO)ÚPathLike)ÚTYPE_CHECKINGÚAnyÚGenericÚLiteralÚTypeVarÚUnionÚcast)Úwarn)Úlogger)ÚIterableÚIterator)ÚSelf)ÚexcÚregistry)ÚCryptContext)ÚExpectedStringError)Úhtdigest)Úis_ascii_codecÚrender_bytesÚto_bytes)Ú
join_bytesÚHtpasswdFileÚHtdigestFileó   :ó   #s   :
	 ÚskippedzLiteral['skipped']Ú_SKIPPEDÚrecordzLiteral['record']Ú_RECORDÚ_TRecordKeyc                  ór  € ] tR t^6tRtR/R R llt]R R l4       t]R R l4       tR	 R
 lt	]
R R l4       t]P                  R R l4       t]
R R l4       tR R ltR0R R lltR R ltR R ltR R ltR R ltR R ltR0R R  lltR! R" ltR# R$ ltR% tR& R' ltR( R) ltR1R* R+ lltR, R- ltR.tR# )2Ú_CommonFilez0Common framework for HtpasswdFile & HtdigestFileNc               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )é   ÚpathúPathLike | NoneÚnewÚboolÚautosaveÚencodingÚstrÚreturn_unicodeÚreturnÚNone© )Úformats   "Ú0/usr/lib/python3/dist-packages/passlib/apache.pyÚ__annotate__Ú_CommonFile.__annotate__9   sF   € ÷ "ñ "àð"ð ð"ð ð	"ð
 ð"ð ð"ð 
ñ"ó    c                	ó  € V'       g   \        R 4      h\        V4      '       g   \        R4      hW@n        WPn        W0n        Wn        ^ V n        / V n        . V n	        V'       d   V'       g   V P                  4        R# R# R# )z'encoding' is requiredz'encoding must be 7-bit ascii compatibleN)Ú	TypeErrorr   Ú
ValueErrorr,   r.   r+   Ú_pathÚ_mtimeÚ_recordsÚ_sourceÚload)Úselfr'   r)   r+   r,   r.   s   &&&&&&r3   Ú__init__Ú_CommonFile.__init__9   ss   € ÷ ÜÐ4Ó5Ð5Ü˜h×'Ò'ô ÐFÓGÐGð !Œà,Ôà ŒØŒ
ØˆŒð 13ˆŒð ,.ˆŒ÷ ŸØ�I‰IŽKñ ‰4r6   c               ó$   € V ^8„  d   QhRRRRRR/# )r&   Údataústr | bytesÚkwargsr   r/   r   r1   )r2   s   "r3   r4   r5   ^   s!   € ÷ ñ ˜{ð °cð ¸dñ r6   c                ó\   € RV9   d   \        R4      hV ! R/ VB pVP                  V4       V# )zÂcreate new object from raw string.

:type data: str or bytes
:arg data:
    database to load, as single string.

:param \*\*kwds:
    all other keywords are the same as in the class constructor
r'   z$'path' not accepted by from_string()r1   )r8   Úload_string)ÚclsrC   rE   Úinstances   &&, r3   Úfrom_stringÚ_CommonFile.from_string]   s6   € ð �VÔÜÐBÓCÐCÙ‘=˜‘=ˆØ×Ñ˜TÔ"Øˆr6   c               ó$   € V ^8„  d   QhRRRRRR/# )r&   r'   r   Úkwdsr   r/   r   r1   )r2   s   "r3   r4   r5   o   s!   € ÷ ñ ˜Xð ¨sð °tñ r6   c                ó8   € V ! R/ VB pVP                  V4       V# )zËcreate new object from file, without binding object to file.

:type path: str
:arg path:
    local filepath to load from

:param \*\*kwds:
    all other keywords are the same as in the class constructor
r1   )r>   )rH   r'   rM   r?   s   &&, r3   Ú	from_pathÚ_CommonFile.from_pathn   s   € ñ ‰{�T‰{ˆØ�	‰	�$ŒØˆr6   c               ó   € V ^8„  d   QhRR/# )r&   r/   r-   r1   )r2   s   "r3   r4   r5      s   € ÷ Dñ D˜#ñ Dr6   c                	ó0  € R pV P                   '       d
   VR,          pV P                  '       d   VRV P                  : 2,          pV P                  R8w  d   VRV P                  : 2,          pRV P                  P                   R\        V 4      R V R2# )	Ú z autosave=Truez path=úutf-8z
 encoding=Ú<z 0xÚ0xÚ>)r+   r:   r,   Ú	__class__Ú__name__Úid)r?   Útails   & r3   Ú__repr__Ú_CommonFile.__repr__   s…   € ØˆØ�=�=ˆ=ØÐ$Õ$ˆDØ�:�:ˆ:Ø�f˜TŸZ™Z™NÐ+Õ+ˆDØ�=‰=˜GÔ#Ø�j §¡Ñ 1Ð2Õ2ˆDØ�4—>‘>×*Ñ*Ð+¨3¬r°$«x¸¨m¸D¸6ÀÐCÐCr6   c               ó   € V ^8„  d   QhRR/# )r&   r/   r(   r1   )r2   s   "r3   r4   r5   Œ   s   € ÷ ñ �oñ r6   c                	ó   € V P                   # ©N)r:   ©r?   s   &r3   r'   Ú_CommonFile.path‹   s   € à�z‰zÐr6   c               ó    € V ^8„  d   QhRRRR/# )r&   Úvaluer(   r/   r0   r1   )r2   s   "r3   r4   r5   �   s   € ÷ ñ ˜/ð ¨dñ r6   c                	ó@   € WP                   8w  d   ^ V n        Wn         R# )é    N)r:   r;   ©r?   rd   s   &&r3   r'   rb   �   s   € à—J‘JÔØˆDŒKØŽ
r6   c               ó   € V ^8„  d   QhRR/# )r&   r/   Úfloatr1   )r2   s   "r3   r4   r5   –   s   € ÷ ñ �uñ r6   c                ó   € V P                   # )z7modify time when last loaded (if bound to a local file))r;   ra   s   &r3   ÚmtimeÚ_CommonFile.mtime•   s   € ð �{‰{Ðr6   c               ó   € V ^8„  d   QhRR/# )r&   r/   r*   r1   )r2   s   "r3   r4   r5   š   s   € ÷ ñ  ñ r6   c                ó   € V P                   '       g   \        V : R24      hV P                  '       d;   V P                  \        P                  P                  V P                   4      8X  d   R# V P                  4        R# )zBReload from ``self.path`` only if file has changed since last loadz is not bound to a local fileFT)r:   ÚRuntimeErrorr;   Úosr'   Úgetmtimer>   ra   s   &r3   Úload_if_changedÚ_CommonFile.load_if_changedš   sT   € à�z�zˆzÜ $¡Ð)FÐGÓHÐHØ�;�;ˆ;˜4Ÿ;™;¬"¯'©'×*:Ñ*:¸4¿:¹:Ó*FÔFÙØ�	‰	ŒÙr6   c               ó    € V ^8„  d   QhRRRR/# )r&   r'   r(   r/   r*   r1   )r2   s   "r3   r4   r5   £   s   € ÷ ñ ˜ð °Dñ r6   c                ó   € Ve8   \        VR4      ;_uu_ 4       p^ V n        V P                  V4       RRR4       R# V P                  '       di   \        V P                  R4      ;_uu_ 4       p\        P
                  P                  V P                  4      V n        V P                  V4       RRR4       R# \        V P                  P                   R24      h  + '       g   i     R# ; i  + '       g   i     R# ; i)zŽLoad state from local file.
If no path is specified, attempts to load from ``self.path``.

:type path: str
:arg path: local file to load from
NÚrbz0().path is not set, an explicit path is requiredT)
Úopenr;   Ú_load_linesr:   rp   r'   rq   ro   rX   rY   ©r?   r'   Úfhs   && r3   r>   Ú_CommonFile.load£   sÉ   € ð ÒÜ�d˜D×!Ô! RØ�”Ø× Ñ  Ô$÷ "ñ ð �Z�ZˆZÜ�d—j‘j $×'Ô'¨2Ü Ÿg™g×.Ñ.¨t¯z©zÓ:�”Ø× Ñ  Ô$÷ (ñ ô Ø—>‘>×*Ñ*Ð+Ð+[Ð\óð ÷ "Ö!ñ ú÷ (Ö'ñ ús   ™CÁ,A C,ÃC)	Ã,C=	c               ó    € V ^8„  d   QhRRRR/# )r&   rC   rD   r/   r0   r1   )r2   s   "r3   r4   r5   ¸   s   € ÷ Iñ I ð I°ñ Ir6   c           	     óp   € ^ V n         V P                  \        \        WP                  R4      4      4       R# )z@Load state from unicode or bytes string, replacing current staterC   N)r;   rx   r   r   r,   )r?   rC   s   &&r3   rG   Ú_CommonFile.load_string¸   s'   € àˆŒØ×Ñœ¤¨$·±¸vÓ!FÓGÖHr6   c               ó    € V ^8„  d   QhRRRR/# )r&   ÚlineszIterable[bytes]r/   r0   r1   )r2   s   "r3   r4   r5   ½   s   € ÷ *ñ * ð *°Tñ *r6   c                ó   € / p. pRp\        V4       F¿  w  rVVP                  4       pV'       d   VP                  \        4      '       d   WF,          pKB  V P	                  We^,           4      w  r‰W‚9   d"   \
        P                  ! RV4       WF,          pKƒ  V'       d   VP                  \        V34       RpW’V&   VP                  \        V34       KÁ  	  VP                  4       '       d   VP                  \        V34       W n        W0n        R# )zload from sequence of listsr6   z1username occurs multiple times in source file: %rN)Ú	enumerateÚlstripÚ
startswithÚ_BHASHÚ_parse_recordr   ÚwarningÚappendr   r!   Úrstripr<   r=   )
r?   r€   ÚrecordsÚsourcer   ÚidxÚlineÚtmpÚkeyrd   s
   &&        r3   rx   Ú_CommonFile._load_lines½   sè   € àˆØ%'ˆØˆÜ" 5Ö)‰IˆCð —+‘+“-ˆCß˜#Ÿ.™.¬×0Ò0Ø•�Ùð ×+Ñ+¨D¸µ'Ó:‰JˆCð Œ~Ü—’ØGØôð •�Ù÷ Ø—‘œx¨Ð1Ô2Ø�ð !�C‰LØ�M‰Mœ7 C˜.Ö)ñ; *ð@ �>‰>×ÒØ�M‰Mœ8 WÐ-Ô.ð  ŒØŽr6   c               ó$   € V ^8„  d   QhRRRRRR/# )r&   r    ÚbytesÚlinenoÚintr/   ztuple[_TRecordKey, Any]r1   )r2   s   "r3   r4   r5   é   s)   € ÷ Gñ GØðGØ%(ðGà	 ñGr6   c                ó   € \        R4      h)z)parse line of file into (key, value) pairú!should be implemented in subclass©ÚNotImplementedError)r?   r    r“   s   &&&r3   r†   Ú_CommonFile._parse_recordé   s   € ô "Ð"EÓFÐFr6   c               ó$   € V ^8„  d   QhRRRRRR/# )r&   r�   r"   rd   r   r/   r*   r1   )r2   s   "r3   r4   r5   ï   s!   € ÷ ñ ˜{ð °3ð ¸4ñ r6   c                ó�   € WP                   9   pW P                   V&   V'       g"   V P                  P                  \        V34       V# )z{
helper for setting record which takes care of inserting source line if needed;

:returns:
    bool if key already present
)r<   r=   rˆ   r!   )r?   r�   rd   Úexistings   &&& r3   Ú_set_recordÚ_CommonFile._set_recordï   s:   € ð Ÿ-™-Ñ'ˆØ"�‰�cÑßØ�L‰L×Ñ¤¨# Ô/Øˆr6   c               ó   € V ^8„  d   QhRR/# )r&   r/   r0   r1   )r2   s   "r3   r4   r5   ü   s   € ÷ ñ ˜4ñ r6   c                óv   € V P                   '       d'   V P                  '       d   V P                  4        R# R# R# )z0subclass helper to call save() after any changesN)r+   r:   Úsavera   s   &r3   Ú	_autosaveÚ_CommonFile._autosaveü   s#   € à�=�=ˆ=˜TŸZŸZ˜ZØ�I‰IŽKñ (‰=r6   c               ó    € V ^8„  d   QhRRRR/# )r&   r'   r(   r/   r0   r1   )r2   s   "r3   r4   r5     s   € ÷ ñ ˜ð °Dñ r6   c                ó¬  € Ve?   \        VR4      ;_uu_ 4       pVP                  V P                  4       4       RRR4       R# V P                  '       dL   V P	                  V P                  4       \
        P                  P                  V P                  4      V n        R# \        V P                  P                   R24      h  + '       g   i     R# ; i)zXSave current state to file.
If no path is specified, attempts to save to ``self.path``.
NÚwbz#().path is not set, cannot autosave)rw   Ú
writelinesÚ_iter_linesr:   r¡   rp   r'   rq   r;   ro   rX   rY   ry   s   && r3   r¡   Ú_CommonFile.save  s˜   € ð ÒÜ�d˜D×!Ô! RØ—‘˜d×.Ñ.Ó0Ô1÷ "Ñ!à�Z�ZˆZØ�I‰I�d—j‘jÔ!ÜŸ'™'×*Ñ*¨4¯:©:Ó6ˆDŽKäØ—>‘>×*Ñ*Ð+Ð+NÐOóð ÷ "×!Ð!ús   ™ CÃC	c               ó   € V ^8„  d   QhRR/# )r&   r/   r’   r1   )r2   s   "r3   r4   r5     s   € ÷ .ñ .˜5ñ .r6   c                ó4   € \        V P                  4       4      # )z)Export current state as a string of bytes)r   r¨   ra   s   &r3   Ú	to_stringÚ_CommonFile.to_string  s   € ä˜$×*Ñ*Ó,Ó-Ð-r6   c               ó   € V ^8„  d   QhRR/# )r&   r/   zIterator[Any]r1   )r2   s   "r3   r4   r5     s   € ÷ Tñ T˜]ñ Tr6   c              #  óL  "  € V P                   p \        V4      pV P                   Fc  w  r4V\        8X  d   Vx € K  V\        8X  g   Q h\        RV4      pWA9  d   K7  V P                  WAV,          4      x €  VP                  V4       Ke  	   V'       d   Q RV: 24       hR# 5i)z#iterator yielding lines of databaser"   z%failed to write all records: missing=N)r<   Úsetr=   r   r!   r   Ú_render_recordÚremove)r?   rŠ   ÚpendingÚactionÚcontents   &    r3   r¨   Ú_CommonFile._iter_lines  s¦   é € ð —-‘-ˆØÜ˜'“lˆGØ#Ÿ|œ|‰OˆFØœÔ!à”à¤Ô(Ð(Ð(ÜØ! 7ó�ð
 Ô)ñ Ø×)Ñ)¨'¸7Õ3CÓDÒDØØ—N‘N 7Ö+ñ%  ,ð& ÷ ÐSÐ"GÈÁ{Ð SÓS�;‘wùs   ‚BB$ÂB$c                ó   € \        R4      h)z,given key/value pair, encode as line of filer–   r—   )r?   r�   rd   s   &&&r3   r±   Ú_CommonFile._render_record;  s   € ä!Ð"EÓFÐFr6   c               ó    € V ^8„  d   QhRRRR/# )r&   ÚuserrD   r/   r’   r1   )r2   s   "r3   r4   r5   ?  s   € ÷ 0ñ 0 ð 0°ñ 0r6   c                ó&   € V P                  VR4      # )z)user-specific wrapper for _encode_field()rº   ©Ú_encode_field©r?   rº   s   &&r3   Ú_encode_userÚ_CommonFile._encode_user?  s   € à×!Ñ! $¨Ó/Ð/r6   c               ó    € V ^8„  d   QhRRRR/# )r&   ÚrealmrD   r/   r’   r1   )r2   s   "r3   r4   r5   C  s   € ÷ 2ñ 2Ø ð2à	ñ2r6   c                ó&   € V P                  VR4      # )z*realm-specific wrapper for _encode_field()rÂ   r¼   ©r?   rÂ   s   &&r3   Ú_encode_realmÚ_CommonFile._encode_realmC  s   € ð ×!Ñ! %¨Ó1Ð1r6   c               ó    € V ^8„  d   QhRRRR/# )r&   rd   rD   r/   r’   r1   )r2   s   "r3   r4   r5   I  s   € ÷ ñ  ;ð À%ñ r6   c                ó„  € \        V\        4      '       d   VP                  V P                  4      pM!\        V\        4      '       g   \        W4      h\        V4      ^ÿ8”  d   \        V RV: 24      h\        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   \        V RV: 24      hV# )aÓ  convert field to internal representation.

internal representation is always bytes. byte strings are left as-is,
unicode strings encoding using file's default encoding (or ``utf-8``
if no encoding has been specified).

:raises UnicodeEncodeError:
    if unicode value cannot be encoded using default encoding.

:raises ValueError:
    if resulting byte string contains a forbidden character,
    or is too long (>255 bytes).

:returns:
    encoded identifer as bytes
z! must be at most 255 characters: c              3  ó2   "  € T F  q\         9   x € K  	  R # 5ir`   )Ú_INVALID_FIELD_CHARS)Ú.0Úcs   & r3   Ú	<genexpr>Ú,_CommonFile._encode_field.<locals>.<genexpr>a  s   é € Ð8±%¨QÔ(Ö(³%ùó   ‚TFz contains invalid characters: )	Ú
isinstancer-   Úencoder,   r’   r   Úlenr9   Úany)r?   rd   Úparams   &&&r3   r½   Ú_CommonFile._encode_fieldI  s›   € ô" �eœS×!Ò!Ø—L‘L §¡Ó/‰EÜ˜E¤5×)Ò)Ü% eÓ3Ð3äˆu‹:˜ÔÜ ˜wÐ&GÈÁyÐQÓRÐRß‹3Ñ8±%Ó8�3�3Š3Ñ8±%Ó8×8Ò8Ü ˜wÐ&DÀUÁIÐNÓOÐOØˆr6   c               ó    € V ^8„  d   QhRRRR/# )r&   rd   r’   r/   zbytes | strr1   )r2   s   "r3   r4   r5   e  s   € ÷ ñ  5ð ¨[ñ r6   c                óš   € \        V\        4      '       g   Q R4       hV P                  '       d   VP                  V P                  4      # V# )a  decode field from internal representation to format
returns by users() method, etc.

:raises UnicodeDecodeError:
    if unicode value cannot be decoded using default encoding.
    (usually indicates wrong encoding set for file).

:returns:
    field as str or bytes, as appropriate.
zexpected value to be bytes)rÐ   r’   r.   Údecoder,   rg   s   &&r3   Ú_decode_fieldÚ_CommonFile._decode_fielde  sA   € ô ˜%¤×'Ò'ÐEÐ)EÓEÐ'Ø××ÐØ—<‘< §¡Ó.Ð.Øˆr6   )r;   r:   r<   r=   r+   r,   r.   )NFFrT   Tr`   )Úfield)rY   Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r@   ÚclassmethodrJ   rO   r\   Úpropertyr'   Úsetterrk   rr   r>   rG   rx   r†   r�   r¢   r¡   r¬   r¨   r±   r¿   rÅ   r½   rÙ   Ú__static_attributes__r1   r6   r3   r$   r$   6   sÎ   † Ù:÷"ðH ôó ðð  ôó ðõ Dð ôó ðð 
‡[�[ôó ðð
 ôó ðõ÷õ*Iõ
*õXGõõ÷
õ.õTò>Gõ0õ2÷÷8ñ r6   r$   zset[str]Ú_warn_no_bcryptc            	     óÊ  € R p R F#  p\         P                  ! V4      '       g   K!  Tp  M	  \         P                  ! R4      '       d   RMR p\        P	                  4        V'       g   \        P                  . R	O4       \        T;'       g    RRT;'       g    T ;'       g    RT ;'       g    RT;'       g    RRR7      pVP                  VR,          VR,          R7       V# )
NÚbcryptÚsha256_cryptÚportable_apache_24Úhost_apache_24Úapr_md5_crypt)rè   Úportable_apache_22ré   Úhost_apache_22Úlinux_apache_24Úlinux_apache_22)ÚportableÚhost)ræ   rç   )rè   ré   rí   rï   rð   )r   Úhas_os_crypt_supportÚhas_backendrä   ÚclearÚupdateÚdict)Ú	host_bestÚnameræ   Údefaultss       r3   Ú_init_default_schemesrù   Ž  s×   € à€IÛ*ˆÜ×(Ò(¨×.Ô.ØˆIÙñ +ô "×-Ò-¨h×7Ò7‰X¸T€FÜ×ÑÔßÜ×Ñòô	
ô à!×4Ð4 _Ø*à×=Ð= ×=Ð=¨oØ ×3Ð3 Oà×0Ð0 .Ø&ô
€Hð ‡O�OØÐ.Õ/ØÐ&Õ'ð ô ð €Or6   c                 óô   € . ROp V P                  \        P                  ! 4       4       V R,          R.,           V ,           p\        \	        V 4      VP
                  R7      p \        V \        R,          RR7      # )ræ   rê   :Né   N)r�   rë   Ú2y)ÚschemesÚdefaultÚbcrypt__ident)ræ   rç   Úsha512_cryptÚ	des_cryptrê   Ú	ldap_sha1Ú	plaintext)Úextendr   Úget_supported_os_crypt_schemesÚsortedr°   Úindexr   Úhtpasswd_defaults)rý   Ú	preferreds     r3   Ú_init_htpasswd_contextr
  ¿  sj   € ò€Gð( ‡N�N”8×:Ò:Ó<Ô=ð ˜•˜Ð/Õ/°'Õ9€IÜ”S˜“\ y§¡Ô7€Gô Øä!Ð"6Õ7àôð r6   c                  ól   a € ] tR tRtRtRR]3V 3R lltR tR tR R lt	R	 t
R
 tR tR tR tRtV ;t# )r   ié  a]  class for reading & writing Htpasswd files.

The class constructor accepts the following arguments:

:type path: filepath
:param path:

    Specifies path to htpasswd file, use to implicitly load from and save to.

    This class has two modes of operation:

    1. It can be "bound" to a local file by passing a ``path`` to the class
       constructor. In this case it will load the contents of the file when
       created, and the :meth:`load` and :meth:`save` methods will automatically
       load from and save to that file if they are called without arguments.

    2. Alternately, it can exist as an independant object, in which case
       :meth:`load` and :meth:`save` will require an explicit path to be
       provided whenever they are called. As well, ``autosave`` behavior
       will not be available.

       This feature is new in Passlib 1.6, and is the default if no
       ``path`` value is provided to the constructor.

    This is also exposed as a readonly instance attribute.

:type new: bool
:param new:

    Normally, if *path* is specified, :class:`HtpasswdFile` will
    immediately load the contents of the file. However, when creating
    a new htpasswd file, applications can set ``new=True`` so that
    the existing file (if any) will not be loaded.

    .. versionadded:: 1.6
        This feature was previously enabled by setting ``autoload=False``.
        That alias was removed in Passlib 1.8

:type autosave: bool
:param autosave:

    Normally, any changes made to an :class:`HtpasswdFile` instance
    will not be saved until :meth:`save` is explicitly called. However,
    if ``autosave=True`` is specified, any changes made will be
    saved to disk immediately (assuming *path* has been set).

    This is also exposed as a writeable instance attribute.

:type encoding: str
:param encoding:

    Optionally specify character encoding used to read/write file
    and hash passwords. Defaults to ``utf-8``, though ``latin-1``
    is the only other commonly encountered encoding.

    This is also exposed as a readonly instance attribute.

:type default_scheme: str
:param default_scheme:
    Optionally specify default scheme to use when encoding new passwords.

    This can be any of the schemes with builtin Apache support,
    OR natively supported by the host OS's :func:`crypt.crypt` function.

    * Builtin schemes include ``"bcrypt"`` (apache 2.4+), ``"apr_md5_crypt"`,
      and ``"des_crypt"``.

    * Schemes commonly supported by Unix hosts
      include ``"bcrypt"``, ``"sha256_crypt"``, and ``"des_crypt"``.

    In order to not have to sort out what you should use,
    passlib offers a number of aliases, that will resolve
    to the most appropriate scheme based on your needs:

    * ``"portable"``, ``"portable_apache_24"`` -- pick scheme that's portable across hosts
      running apache >= 2.4. **This will be the default as of Passlib 2.0**.

    * ``"portable_apache_22"`` -- pick scheme that's portable across hosts
      running apache >= 2.4. **This is the default up to Passlib 1.9**.

    * ``"host"``, ``"host_apache_24"`` -- pick strongest scheme supported by
       apache >= 2.4 and/or host OS.

    * ``"host_apache_22"`` -- pick strongest scheme supported by
       apache >= 2.2 and/or host OS.

    .. versionadded:: 1.6
        This keyword was previously named ``default``. That alias
        was removed in Passlib 1.8.

    .. versionchanged:: 1.6.3

        Added support for ``"bcrypt"``, ``"sha256_crypt"``, and ``"portable"`` alias.

    .. versionchanged:: 1.7

        Added apache 2.4 semantics, and additional aliases.

:type context: :class:`~passlib.context.CryptContext`
:param context:
    :class:`!CryptContext` instance used to create
    and verify the hashes found in the htpasswd file.
    The default value is a pre-built context which supports all
    of the hashes officially allowed in an htpasswd file.

    This is also exposed as a readonly instance attribute.

    .. warning::

        This option may be used to add support for non-standard hash
        formats to an htpasswd file. However, the resulting file
        will probably not be usable by another application,
        and particularly not by Apache.

Loading & Saving
================
.. automethod:: load
.. automethod:: load_if_changed
.. automethod:: load_string
.. automethod:: save
.. automethod:: to_string

Inspection
================
.. automethod:: users
.. automethod:: check_password
.. automethod:: get_hash

Modification
================
.. automethod:: set_password
.. automethod:: delete

Alternate Constructors
======================
.. automethod:: from_string

Attributes
==========
.. attribute:: path

    Path to local file that will be used as the default
    for all :meth:`load` and :meth:`save` operations.
    May be written to, initialized by the *path* constructor keyword.

.. attribute:: autosave

    Writeable flag indicating whether changes will be automatically
    written to *path*.

Errors
======
:raises ValueError:
    All of the methods in this class will raise a :exc:`ValueError` if
    any user name contains a forbidden character (one of ``:\r\n\t\x00``),
    or is longer than 255 characters.
Nc                	óæ   <€ V'       dQ   V\         9   d   \        R V: 2\        P                  4       \        P                  W"4      pVP                  VR7      pW0n        \        SV `$  ! V3/ VB  R# )zNHtpasswdFile: no bcrypt backends available, using fallback for default scheme )rþ   N)
rä   r   r   ÚPasslibSecurityWarningr  ÚgetÚcopyÚcontextÚsuperr@   )r?   r'   Údefault_schemer  rM   rX   s   &&&&,€r3   r@   ÚHtpasswdFile.__init__Š  sk   ø€ ÷ Ø¤Ô0Üð9Ø9GÑ8JðLä×.Ñ.ôô
 /×2Ñ2°>ÓRˆNØ—l‘l¨>�lÓ:ˆGØŒÜ‰Ò˜Ñ& Ô&r6   c                	ó�   € VP                  4       P                  \        4      p\        V4      ^8w  d   \	        RV,          4      hV# )r&   z/malformed htpasswd file (error reading line %d)©r‰   ÚsplitÚ_BCOLONrÒ   r9   )r?   r    r“   Úresults   &&& r3   r†   ÚHtpasswdFile._parse_record™  s;   € à—‘“×&Ñ&¤wÓ/ˆÜˆv‹;˜!ÔÜÐNÐQWÕWÓXÐXØˆr6   c                	ó   € \        R W4      # )z%s:%s
©r   )r?   rº   Úhashs   &&&r3   r±   ÚHtpasswdFile._render_record   s   € Ü˜I tÓ2Ð2r6   c               ó   € V ^8„  d   QhRR/# )r&   r/   zlist[bytes | str]r1   )r2   s   "r3   r4   ÚHtpasswdFile.__annotate__£  s   € ÷ Dñ DÐ(ñ Dr6   c                ó`   € V P                    Uu. uF  qP                  V4      NK  	  up# u upi )z&
Return list of all users in database
)r<   rÙ   r¾   s   & r3   ÚusersÚHtpasswdFile.users£  s)   € ð 6:·]²]ÓC±]¨T×"Ñ" 4Ö(±]ÑCÐCùÒCs   �+c                óZ   € V P                   P                  V4      pV P                  W4      # )aL  Set password for user; adds user if needed.

:returns:
    * ``True`` if existing user was updated.
    * ``False`` if user account was added.

.. versionchanged:: 1.6
    This method was previously called ``update``, it was renamed
    to prevent ambiguity with the dictionary method.
    The old alias was removed in Passlib 1.8.
)r  r  Úset_hash)r?   rº   Úpasswordr  s   &&& r3   Úset_passwordÚHtpasswdFile.set_passwordµ  s'   € ð �|‰|× Ñ  Ó*ˆØ�}‰}˜TÓ(Ð(r6   c                ól   €  V P                   V P                  V4      ,          #   \         d     R# i ; i)zÍReturn hash stored for user, or ``None`` if user not found.

.. versionchanged:: 1.6
    This method was previously named ``find``, it was renamed
    for clarity. The old name was removed in Passlib 1.8.
N)r<   r¿   ÚKeyErrorr¾   s   &&r3   Úget_hashÚHtpasswdFile.get_hashÄ  s3   € ð	Ø—=‘= ×!2Ñ!2°4Ó!8Õ9Ð9øÜô 	Úð	ús   ‚!$ ¤3²3c                óÌ   € \        V\        4      '       d   VP                  V P                  4      pV P	                  V4      pV P                  W4      pV P                  4        V# )z³
semi-private helper which allows writing a hash directly;
adds user if needed.

.. warning::
    does not (currently) do any validation of the hash string

.. versionadded:: 1.7
)rÐ   r-   rÑ   r,   r¿   r�   r¢   )r?   rº   r  rœ   s   &&& r3   r$  ÚHtpasswdFile.set_hashÐ  sR   € ô �dœC× Ò Ø—;‘;˜tŸ}™}Ó-ˆDØ× Ñ  Ó&ˆØ×#Ñ# DÓ/ˆØ�‰ÔØˆr6   c                ó„   €  V P                   V P                  V4       T P                  4        R#   \         d     R# i ; i)zcDelete user's entry.

:returns:
    * ``True`` if user deleted.
    * ``False`` if user not found.
FT)r<   r¿   r)  r¢   r¾   s   &&r3   ÚdeleteÚHtpasswdFile.deleteã  sA   € ð	Ø—‘˜d×/Ñ/°Ó5Ð6ð 	�‰ÔÙøô ô 	Úð	ús   ‚0 °?¾?c                ó~  € V P                  V4      pV P                  P                  V4      pVf   R# \        V\        4      '       d   VP                  V P                  4      pV P                  P                  W#4      w  rEV'       d5   Ve1   WP                  9   g   Q hWPP                  V&   V P                  4        V# )aÞ  
Verify password for specified user.
If algorithm marked as deprecated by CryptContext, will automatically be re-hashed.

:returns:
    * ``None`` if user not found.
    * ``False`` if user found, but password does not match.
    * ``True`` if user found and password matches.

.. versionchanged:: 1.6
    This method was previously called ``verify``, it was renamed
    to prevent ambiguity with the :class:`!CryptContext` method.
    The old alias was removed in Passlib 1.8.
N)
r¿   r<   r  rÐ   r-   rÑ   r,   r  Úverify_and_updater¢   )r?   rº   r%  r  ÚokÚnew_hashs   &&&   r3   Úcheck_passwordÚHtpasswdFile.check_passwordñ  sš   € ð × Ñ  Ó&ˆØ�}‰}× Ñ  Ó&ˆØŠ<ÙÜ�h¤×$Ò$ð  —‘ t§}¡}Ó5ˆHØ—|‘|×5Ñ5°hÓE‰ˆß�(Ò&àŸ=™=Ô(Ð(Ð(Ø"*�M‰M˜$ÑØ�N‰NÔØˆ	r6   )r  )rY   rÜ   rÝ   rÞ   rß   Úhtpasswd_contextr@   r†   r±   r!  r&  r*  r$  r/  r5  rã   Ú__classcell__©rX   s   @r3   r   r   é  sG   ø† ñ\ðB ¨Ð6F÷'òò3õDò$)ò
òò&÷ð r6   c                  ó¦   a € ] tR tRtRtRtRV 3R lltR tR tR t	R t
R	 tR
 tRR ltR]3R ltRR ltR]3R ltRR ltR tR]3R ltRtV ;t# )r   i  aÚ  class for reading & writing Htdigest files.

The class constructor accepts the following arguments:

:type path: filepath
:param path:

    Specifies path to htdigest file, use to implicitly load from and save to.

    This class has two modes of operation:

    1. It can be "bound" to a local file by passing a ``path`` to the class
       constructor. In this case it will load the contents of the file when
       created, and the :meth:`load` and :meth:`save` methods will automatically
       load from and save to that file if they are called without arguments.

    2. Alternately, it can exist as an independant object, in which case
       :meth:`load` and :meth:`save` will require an explicit path to be
       provided whenever they are called. As well, ``autosave`` behavior
       will not be available.

       This feature is new in Passlib 1.6, and is the default if no
       ``path`` value is provided to the constructor.

    This is also exposed as a readonly instance attribute.

:type default_realm: str
:param default_realm:

    If ``default_realm`` is set, all the :class:`HtdigestFile`
    methods that require a realm will use this value if one is not
    provided explicitly. If unset, they will raise an error stating
    that an explicit realm is required.

    This is also exposed as a writeable instance attribute.

    .. versionadded:: 1.6

:type new: bool
:param new:

    Normally, if *path* is specified, :class:`HtdigestFile` will
    immediately load the contents of the file. However, when creating
    a new htpasswd file, applications can set ``new=True`` so that
    the existing file (if any) will not be loaded.

    .. versionadded:: 1.6
        This feature was previously enabled by setting ``autoload=False``.
        That alias was removed in Passlib 1.8

:type autosave: bool
:param autosave:

    Normally, any changes made to an :class:`HtdigestFile` instance
    will not be saved until :meth:`save` is explicitly called. However,
    if ``autosave=True`` is specified, any changes made will be
    saved to disk immediately (assuming *path* has been set).

    This is also exposed as a writeable instance attribute.

:type encoding: str
:param encoding:

    Optionally specify character encoding used to read/write file
    and hash passwords. Defaults to ``utf-8``, though ``latin-1``
    is the only other commonly encountered encoding.

    This is also exposed as a readonly instance attribute.

Loading & Saving
================
.. automethod:: load
.. automethod:: load_if_changed
.. automethod:: load_string
.. automethod:: save
.. automethod:: to_string

Inspection
==========
.. automethod:: realms
.. automethod:: users
.. automethod:: check_password(user[, realm], password)
.. automethod:: get_hash

Modification
============
.. automethod:: set_password(user[, realm], password)
.. automethod:: delete
.. automethod:: delete_realm

Alternate Constructors
======================
.. automethod:: from_string

Attributes
==========
.. attribute:: default_realm

    The default realm that will be used if one is not provided
    to methods that require it. By default this is ``None``,
    in which case an explicit realm must be provided for every
    method call. Can be written to.

.. attribute:: path

    Path to local file that will be used as the default
    for all :meth:`load` and :meth:`save` operations.
    May be written to, initialized by the *path* constructor keyword.

.. attribute:: autosave

    Writeable flag indicating whether changes will be automatically
    written to *path*.

Errors
======
:raises ValueError:
    All of the methods in this class will raise a :exc:`ValueError` if
    any user name or realm contains a forbidden character (one of ``:\r\n\t\x00``),
    or is longer than 255 characters.
Nc                	ó6   <€ W n         \        SV `  ! V3/ VB  R # r`   )Údefault_realmr  r@   )r?   r'   r<  rM   rX   s   &&&,€r3   r@   ÚHtdigestFile.__init__–  s   ø€ Ø*ÔÜ‰Ò˜Ñ& Ô&r6   c                	ó    € VP                  4       P                  \        4      p\        V4      ^8w  d   \	        RV,          4      hVw  rEpWE3V3# )rû   z/malformed htdigest file (error reading line %d)r  )r?   r    r“   r  rº   rÂ   r  s   &&&    r3   r†   ÚHtdigestFile._parse_recordš  sM   € Ø—‘“×&Ñ&¤wÓ/ˆÜˆv‹;˜!ÔÜÐNÐQWÕWÓXÐXØ"Ñˆ�TØˆ}˜dÐ"Ð"r6   c                	ó$   € Vw  r4\        R W4V4      # )z	%s:%s:%s
r  )r?   r�   r  rº   rÂ   s   &&&  r3   r±   ÚHtdigestFile._render_record¡  s   € Ø‰ˆÜ˜L¨$°tÓ<Ð<r6   c                	óD   € Vf   V P                   pVf   \        R4      hV# )NzGyou must specify a realm explicitly, or set the default_realm attribute)r<  r8   rÄ   s   &&r3   Ú_require_realmÚHtdigestFile._require_realm¥  s0   € ØŠ=Ø×&Ñ&ˆEØŠ}Üð9óð ð ˆr6   c                	óH   € V P                  V4      pV P                  VR 4      # )rÂ   )rC  r½   rÄ   s   &&r3   rÅ   ÚHtdigestFile._encode_realm¯  s%   € Ø×#Ñ# EÓ*ˆØ×!Ñ! %¨Ó1Ð1r6   c                	óF   € V P                  V4      V P                  V4      3# r`   )r¿   rÅ   )r?   rº   rÂ   s   &&&r3   Ú_encode_keyÚHtdigestFile._encode_key³  s#   € Ø× Ñ  Ó&¨×(:Ñ(:¸5Ó(AÐAÐAr6   c                ó„   € \        R V P                   4       4      pV Uu. uF  q P                  V4      NK  	  up# u upi )z%Return list of all realms in databasec              3  ó2   "  € T F  q^,          x € K  	  R# 5i)é   Nr1   )rË   r�   s   & r3   rÍ   Ú&HtdigestFile.realms.<locals>.<genexpr>¸  s   é € Ð5¡} ˜—V’V£}ùrÏ   )r°   r<   rÙ   )r?   ÚrealmsrÂ   s   &  r3   rN  ÚHtdigestFile.realms¶  s7   € äÑ5 t§}¢}Ó5Ó5ˆÙ7=Ó>±v¨e×"Ñ" 5Ö)±vÑ>Ð>ùÒ>s   ¡=c                ó°   € V P                  V4      pV P                   Uu. uF*  q"^,          V8X  g   K  V P                  V^ ,          4      NK,  	  up# u upi )z–Return list of all users in specified realm.

* uses ``self.default_realm`` if no realm explicitly provided.
* returns empty list if realm not found.
)rÅ   r<   rÙ   )r?   rÂ   r�   s   && r3   r!  ÚHtdigestFile.users»  sK   € ð ×"Ñ" 5Ó)ˆØ6:·m²mÓW±m¨sÈ1ÅvÐQVÁÔ*�×"Ñ" 3 q¥6Ö*±mÑWÐWùÒWs
    A´Ac                ó¦   € V\         J d   RTr2V P                  V4      p\        P                  ! W1W P                  R7      pV P                  WV4      # )a_  Set password for user; adds user & realm if needed.

If ``self.default_realm`` has been set, this may be called
with the syntax ``set_password(user, password)``,
otherwise it must be called with all three arguments:
``set_password(user, realm, password)``.

:returns:
    * ``True`` if existing user was updated
    * ``False`` if user account added.
N©r,   )Ú_UNSETrC  r   r  r,   r$  ©r?   rº   rÂ   r%  r  s   &&&& r3   r&  ÚHtdigestFile.set_passwordÜ  sH   € ð ”vÓà" E�8Ø×#Ñ# EÓ*ˆÜ�}Š}˜X¨U¿]¹]ÔKˆØ�}‰}˜T¨$Ó/Ð/r6   c                óœ   € V P                  W4      pV P                  P                  V4      pVf   R# VP                  V P                  4      # )a=  Return :class:`~passlib.hash.htdigest` hash stored for user.

* uses ``self.default_realm`` if no realm explicitly provided.
* returns ``None`` if user or realm not found.

.. versionchanged:: 1.6
    This method was previously named ``find``, it was renamed
    for clarity. The old name is was removed Passlib 1.8.
N)rH  r<   r  rØ   r,   )r?   rº   rÂ   r�   r  s   &&&  r3   r*  ÚHtdigestFile.get_hashï  sC   € ð ×Ñ˜tÓ+ˆØ�}‰}× Ñ  Ó%ˆØŠ<ÙØ�{‰{˜4Ÿ=™=Ó)Ð)r6   c                óæ   € V\         J d   RTr2\        V\        4      '       d   VP                  V P                  4      pV P                  W4      pV P                  WC4      pV P                  4        V# )ax  
semi-private helper which allows writing a hash directly;
adds user & realm if needed.

If ``self.default_realm`` has been set, this may be called
with the syntax ``set_hash(user, hash)``,
otherwise it must be called with all three arguments:
``set_hash(user, realm, hash)``.

.. warning::
    does not (currently) do any validation of the hash string

.. versionadded:: 1.7
N)rT  rÐ   r-   rÑ   r,   rH  r�   r¢   )r?   rº   rÂ   r  r�   rœ   s   &&&&  r3   r$  ÚHtdigestFile.set_hashÿ  s`   € ð ”6‹>à �4ä�dœC× Ò Ø—;‘;˜tŸ}™}Ó-ˆDØ×Ñ˜tÓ+ˆØ×#Ñ# CÓ.ˆØ�‰ÔØˆr6   c                óˆ   € V P                  W4      p V P                  V T P                  4        R#   \         d     R# i ; i)z¹Delete user's entry for specified realm.

if realm is not specified, uses ``self.default_realm``.

:returns:
    * ``True`` if user deleted,
    * ``False`` if user not found in realm.
FT)rH  r<   r)  r¢   )r?   rº   rÂ   r�   s   &&& r3   r/  ÚHtdigestFile.delete  sH   € ð ×Ñ˜tÓ+ˆð	Ø—‘˜cÐ"ð 	�‰ÔÙøô ô 	Úð	ús   “2 ²AÁ Ac                óÒ   € V P                  V4      pV P                  pV Uu. uF  q3^,          V8X  g   K  VNK  	  ppV F  pW# K  	  V P                  4        \        V4      # u upi )z™Delete all users for specified realm.

if realm is not specified, uses ``self.default_realm``.

:returns: number of users deleted (0 if realm not found)
)rÅ   r<   r¢   rÒ   )r?   rÂ   rŠ   r�   Úkeyss   &&   r3   Údelete_realmÚHtdigestFile.delete_realm+  sc   € ð ×"Ñ" 5Ó)ˆØ—-‘-ˆÙ&Ó:™w˜¨a­&°E©/—�™wˆÐ:ÛˆCØ’ñ à�‰ÔÜ�4‹yÐùò	 ;s
   ¢A$¶A$c                óê   € V\         J d   RTr2V P                  V4      pV P                  V4      pV P                  P	                  W34      pVf   R# \
        P                  ! W4WV P                  R7      # )ak  Verify password for specified user + realm.

If ``self.default_realm`` has been set, this may be called
with the syntax ``check_password(user, password)``,
otherwise it must be called with all three arguments:
``check_password(user, realm, password)``.

:returns:
    * ``None`` if user or realm not found.
    * ``False`` if user found, but password does not match.
    * ``True`` if user found and password matches.

.. versionchanged:: 1.6
    This method was previously called ``verify``, it was renamed
    to prevent ambiguity with the :class:`!CryptContext` method.
    The old alias was removed in Passlib 1.8.
NrS  )rT  r¿   rÅ   r<   r  r   Úverifyr,   rU  s   &&&& r3   r5  ÚHtdigestFile.check_password:  sh   € ð$ ”vÓà" E�8Ø× Ñ  Ó&ˆØ×"Ñ" 5Ó)ˆØ�}‰}× Ñ  $ Ó/ˆØŠ<ÙÜ�Š˜x¨tÀTÇ]Á]ÔSÐSr6   )r<  )NNr`   )rY   rÜ   rÝ   rÞ   rß   r<  r@   r†   r±   rC  rÅ   rH  rN  r!  rT  r&  r*  r$  r/  r_  r5  rã   r8  r9  s   @r3   r   r     sv   ø† ñxðD €M÷'ò#ò=òò2òBò?ô
XðB (,°fô 0ô&*ð  $(¨fô ô6ò"ð *.¸÷ Tò Tr6   )>Ú__conditional_annotations__rß   Ú
__future__r   rp   Úior   r   Útypingr   r   r   r   r	   r
   r   Úwarningsr   Úpasslib._loggingr   Úcollections.abcr   r   Útyping_extensionsr   Úpasslibr   r   Úpasslib.contextr   Úpasslib.excr   Úpasslib.hashr   Úpasslib.utilsr   r   r   Úpasslib.utils.compatr   Ú__all__ÚobjectrT  r  r…   rÊ   r   Ú__annotations__r!   r"   Útupler’   Ú_SourceTypesr$   r°   rä   rù   r  r
  r7  r   r   )rd  s   @r3   Ú<module>rw     sC  øðÜ õ #ã 	Ý Ý ß M× MÑ MÝ å #çß2å&ç !Ý (Ý +Ý !ß @Ñ @Ý +ð Øð€ñ
 
‹€à
€Ø	€ð &Ð ð  )€Ð
Ó (Ø%€Ð	Ó %Ù�mÓ$€çØØˆg�iÕ  %Ð'Õ(Øˆg�hÕ Ð,Õ-ð	/õ�Lð
 €Lô}�'˜+Õ&ô }ñj
  ›E€�Ó !ò*ñ\ *Ó+Ð ò#ñN *Ó+Ð ôe�;˜uÕ%ô eôP	CT�;˜u U¨E \Õ2Õ3ö CTr6   