+
    iE                     d   R t ^ RIHt ^ RIt]P                  ! ]4      t^ RI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
IHtHtHtHt RR.t]! 4       t Rt!Rt"Rt#Rt$Rt% ! R R]4      t&]'! 4       t(R t)])! 4       t*R t+]+! 4       t, ! R R]&4      t- ! R R]&4      t.R# )z(passlib.apache - apache password support)with_statementN)warn)excregistry)CryptContext)ExpectedStringError)htdigest)render_bytesto_bytesis_ascii_codec)deprecated_method)
join_bytesunicodeBytesIOPY3HtpasswdFileHtdigestFile   :   #s   :
	 skippedrecordc                   &  a  ] tR t^,t o RtRtRtRtRtRt	Rt
Rt]R 4       t]R 4       tRRRRR]3R ltR	 t]R
 4       t]P(                  R 4       t]R 4       tR tRR ltR tR tR tR tR tRR ltR tR tR t R t!R t"RR lt#R t$Rt%V t&R# ) _CommonFilez0common framework for HtpasswdFile & HtdigestFileNFc                \    RV9   d   \        R4      hV ! R/ VB pVP                  V4       V# )zcreate new object from raw string.

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

:param \*\*kwds:
    all other keywords are the same as in the class constructor
pathz$'path' not accepted by from_string() )	TypeErrorload_string)clsdatakwdsselfs   &&, L/var/www/html/photoedit/myenv/lib/python3.14/site-packages/passlib/apache.pyfrom_string_CommonFile.from_stringK   s5     T>BCC{T{    c                8    V ! R/ VB pVP                  V4       V# )zcreate 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
r   )load)r   r   r    r!   s   &&, r"   	from_path_CommonFile.from_path\   s     {T{		$r%   Tutf-8c                R   V'       g   \        R \        ^R7       RpRpM\        V4      '       g   \        R4      hWPn        W`n        W@n        Wn        ^ V n        V'       g   \        R\        ^R7       RpV'       d   V'       g   V P                  4        R# / V n
        . V n        R# )z``encoding=None`` is deprecated as of Passlib 1.6, and will cause a ValueError in Passlib 1.8, use ``return_unicode=False`` instead.
stacklevelr*   Fz'encoding must be 7-bit ascii compatiblezp``autoload=False`` is deprecated as of Passlib 1.6, and will be removed in Passlib 1.8, use ``new=True`` insteadTN)r   DeprecationWarningr   
ValueErrorencodingreturn_unicodeautosave_path_mtimer'   _records_source)r!   r   newautoloadr2   r0   r1   s   &&&&&&&r"   __init___CommonFile.__init__n   s      9 $3 H"N)) FGG  - 
  P#3 CIIKDMDLr%   c                <   R pV P                   '       d
   VR,          pV P                  '       d   VRV P                  ,          ,          pV P                  R8w  d   VRV P                  ,          ,          pRV P                  P                  \        V 4      V3,          # ) z autosave=Truez path=%rr*   z encoding=%rz<%s 0x%0x%s>)r2   r3   r0   	__class____name__id)r!   tails   & r"   __repr___CommonFile.__repr__   sv    ===$$D:::J++D==G#NT]]22D!8!8"T(D IIIr%   c                    V P                   # N)r3   r!   s   &r"   r   _CommonFile.path   s    zzr%   c                @    WP                   8w  d   ^ V n        Wn         R# )    N)r3   r4   r!   values   &&r"   r   rF      s    JJDK
r%   c                    V P                   # )z7modify time when last loaded (if bound to a local file))r4   rE   s   &r"   mtime_CommonFile.mtime   s     {{r%   c                   V P                   '       g   \        RV ,          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%r is not bound to a local fileFT)r3   RuntimeErrorr4   osr   getmtimer'   rE   s   &r"   load_if_changed_CommonFile.load_if_changed   sR    zzz@4GHH;;;4;;"''*:*:4::*FF		r%   c                   Ve8   \        VR4      ;_uu_ 4       p^ V n        V P                  V4       RRR4       R# V'       gH   \        R\	        V P
                  P                  R7      ,          \        ^R7       V P                  4       # 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# \        RV P
                  P                  ,          4      h  + '       g   i     R# ; i  + '       g   i     R# ; i)a  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

:type force: bool
:param force:
    if ``force=False``, only load from ``self.path`` if file
    has changed since last load.

    .. deprecated:: 1.6
        This keyword will be removed in Passlib 1.8;
        Applications should use :meth:`load_if_changed` instead.
Nrbz%(name)s.load(force=False) is deprecated as of Passlib 1.6,and will be removed in Passlib 1.8; use %(name)s.load_if_changed() instead.)namer,   z2%s().path is not set, an explicit path is requiredT)openr4   _load_linesr   dictr=   r>   r.   rR   r3   rP   r   rQ   rO   )r!   r   forcefhs   &&& r"   r'   _CommonFile.load   s	     dD!!R  $ ""   ; 4>>2234 $	3
 ''))ZZZdjj$''2 gg..tzz:  $ (  S#~~66 7 8 8 "!"  (' s   D+;A D?+D<	?E	c                t    \        WP                  R4      p^ V n        V P                  \	        V4      4       R# )z@Load state from unicode or bytes string, replacing current stater   N)r
   r0   r4   rX   r   )r!   r   s   &&r"   r   _CommonFile.load_string   s+    mmV4'r%   c                0   V P                   p/ p. pRp\        V4       F  w  rgVP                  4       pV'       d   VP                  \        4      '       d   WW,          pKB  V! Wv^,           4      w  rW9   d'   \
        P                  RV	,          4       WW,          pK  V'       d   VP                  \        V34       RpWV	&   VP                  \        V	34       K  	  VP                  4       '       d   VP                  \        V34       W0n        W@n        R# )zload from sequence of listsr%   z1username occurs multiple times in source file: %rN)_parse_record	enumeratelstrip
startswith_BHASHlogwarningappend_SKIPPED_RECORDrstripr5   r6   )r!   linesparserecordssourcer   idxlinetmpkeyrJ   s   &&         r"   rX   _CommonFile._load_lines   s    """5)IC ++-C#..00 tU+JC ~ORUUV x12 !CLMM7C.)5 *: >>MM8W-.  r%   c                    \        R4      h)z)parse line of file into (key, value) pair!should be implemented in subclassNotImplementedError)r!   r   linenos   &&&r"   r`   _CommonFile._parse_record      !"EFFr%   c                    V P                   pW9   pW#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
)r5   r6   rg   ri   )r!   rr   rJ   rm   existings   &&&  r"   _set_record_CommonFile._set_record  s9     --NLL#/r%   c                v    V P                   '       d'   V P                  '       d   V P                  4        R# R# R# )z0subclass helper to call save() after any changesN)r2   r3   saverE   s   &r"   	_autosave_CommonFile._autosave!  s#    ===TZZZIIK (=r%   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# \        RV P                  P                  ,          4      h  + '       g   i     R# ; i)zXSave current state to file.
If no path is specified, attempts to save to ``self.path``.
Nwbz%%s().path is not set, cannot autosave)rW   
writelines_iter_linesr3   r   rP   r   rQ   r4   rO   r=   r>   )r!   r   r[   s   && r"   r   _CommonFile.save&  s     dD!!Rd..01 "!ZZZIIdjj!''**4::6DKF#~~66 7 8 8 "!!s    CC	c                4    \        V P                  4       4      # )z)Export current state as a string of bytes)r   r   rE   s   &r"   	to_string_CommonFile.to_string4  s    $**,--r%   c              #  4  "   V P                   p \        V4      pV P                   FW  w  r4V\        8X  d   Vx  K  V\        8X  g   Q hWA9  d   K+  V P                  WAV,          4      x   VP                  V4       KY  	   V'       d   Q RV: 24       hR# 5i)z#iterator yielding lines of databasez%failed to write all records: missing=N)r5   setr6   rh   ri   _render_recordremove)r!   rm   pendingactioncontents   &    r"   r   _CommonFile._iter_lines@  s      --'lG#||OF!((() ))'73CDDNN7+  ,  VW VV;ws   BBBc                    \        R4      h)z,given key/value pair, encode as line of fileru   rv   )r!   rr   rJ   s   &&&r"   r   _CommonFile._render_record[  rz   r%   c                &    V P                  VR4      # )z)user-specific wrapper for _encode_field()user_encode_fieldr!   r   s   &&r"   _encode_user_CommonFile._encode_userb  s    !!$//r%   c                &    V P                  VR4      # )z*realm-specific wrapper for _encode_field()realmr   r!   r   s   &&r"   _encode_realm_CommonFile._encode_realmf  s    !!%11r%   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rD   )_INVALID_FIELD_CHARS).0cs   & r"   	<genexpr>,_CommonFile._encode_field.<locals>.<genexpr>  s     8%Q((%   TFz contains invalid characters: )	
isinstancer   encoder0   bytesr   lenr/   any)r!   rJ   params   &&&r"   r   _CommonFile._encode_fieldj  s    " eW%%LL/EE5))%e33u:#U, - -38%83338%888#U- . .r%   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 unicode or bytes, as appropriate.
zexpected value to be bytes)r   r   r1   decoder0   rI   s   &&r"   _decode_field_CommonFile._decode_field  sA     %''E)EE'<<..Lr%   )r4   r3   r5   r6   r2   r0   r1   )NTrD   )field)'r>   
__module____qualname____firstlineno____doc__r0   r1   r3   r4   r2   r5   r6   classmethodr#   r(   r   r9   rA   propertyr   setterrL   rR   r'   r   rX   r`   r}   r   r   r   r   r   r   r   r   r   __static_attributes____classdictcell__)__classdict__s   @r"   r   r   ,   s    : H N EF H H G
     " !edU!#!FJ   
[[ 
  "H((TG"
8.W6G02: r%   r   c            	         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_backend_warn_no_bcryptclearupdaterY   )	host_bestrV   r   defaultss       r"   _init_default_schemesr     s     I*((..I + "--h77XTF  G 	H !44_* ====o 33O 00.&H" OO./&'   Or%   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)rr   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     r"   _init_htpasswd_contextr     sn    G0 NN8::<= //'9IS\y7G  ""67  r%   c                      a a ] tR tRt oRtRR]3V 3R lltR tR tR t	R t
]! R	R
RR7      R 4       tR tR t]! R	R
RR7      R 4       tR tR t]! R	R
RR7      R 4       tRtV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 has been deprecated, and will be 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
        has been deprecated, and will be 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.

:param autoload:
    Set to ``False`` to prevent the constructor from automatically
    loaded the file from disk.

    .. deprecated:: 1.6
        This has been replaced by the *new* keyword.
        Instead of setting ``autoload=False``, you should use
        ``new=True``. Support for this keyword will be removed
        in Passlib 1.8.

:param default:
    Change the default algorithm used to hash new passwords.

    .. deprecated:: 1.6
        This has been renamed to *default_scheme* for clarity.
        Support for this alias will be removed in Passlib 1.8.

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                H  < R V9   d$   \        R\        ^R7       VP                  R 4      pV'       dT   V\        9   d"   \        RV,          \        P
                  4       \        P                  W"4      pVP                  VR7      pW0n	        \        \        V `2  ! V3/ VB  R# )r   z{``default`` is deprecated as of Passlib 1.6, and will be removed in Passlib 1.8, it has been renamed to ``default_scheem``.r,   zPHtpasswdFile: no bcrypt backends available, using fallback for default scheme %r)r   N)r   r.   popr   r   PasslibSecurityWarningr   getcopycontextsuperr   r9   )r!   r   default_schemer   r    r=   s   &&&&,r"   r9   HtpasswdFile.__init__  s     * $3 "XXi0N0 <>LM//1 /22>RNll>l:GlD*4848r%   c                    VP                  4       P                  \        4      p\        V4      ^8w  d   \	        RV,          4      hV# )   z/malformed htpasswd file (error reading line %d)rj   split_BCOLONr   r/   )r!   r   rx   results   &&& r"   r`   HtpasswdFile._parse_record  sA    &&w/v;!N%& ' 'r%   c                    \        R W4      # )z%s:%s
r	   )r!   r   hashs   &&&r"   r   HtpasswdFile._render_record  s    It22r%   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
)r5   r   r   s   & r"   usersHtpasswdFile.users  s)     6:]]C]T""4(]CCCs   +c                Z    V P                   P                  V4      pV P                  W4      # )ac  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 is deprecated, and will be removed in Passlib 1.8.
)r   r   set_hash)r!   r   passwordr   s   &&& r"   set_passwordHtpasswdFile.set_password  s'     ||  *}}T((r%   1.61.8r   
deprecatedremovedreplacementc                $    V P                  W4      # zset password for userr   r!   r   r   s   &&&r"   r   HtpasswdFile.update  s       00r%   c                l     V P                   V P                  V4      ,          #   \         d     R# i ; i)zReturn 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 is deprecated, and will be removed
    in Passlib 1.8.
N)r5   r   KeyErrorr   s   &&r"   get_hashHtpasswdFile.get_hash  s3    	==!2!24!899 		s   !$ 33c                    \         '       d2   \        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   strr   r0   r   r}   r   )r!   r   r   r|   s   &&& r"   r   HtpasswdFile.set_hash  sV     3:dC((;;t}}-D  &##D/r%   r  c                $    V P                  V4      # zreturn hash for userr  r   s   &&r"   findHtpasswdFile.find1  s     }}T""r%   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)r5   r   r  r   r   s   &&r"   deleteHtpasswdFile.delete8  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 is deprecated, and will be removed in Passlib 1.8.
N)
r   r5   r   r   r   r   r0   r   verify_and_updater   )r!   r   r   r   oknew_hashs   &&&   r"   check_passwordHtpasswdFile.check_passwordF  s       &}}  &<h((  t}}5H||55hE(&==((("*MM$NN	r%   r  c                $    V P                  W4      # zverify password for userr  r
  s   &&&r"   verifyHtpasswdFile.verifye  s     ""422r%   )r   )r>   r   r   r   r   htpasswd_contextr9   r`   r   r   r   r   r   r  r   r  r  r  r$  r   r   __classcell__r=   r   s   @@r"   r   r     s     mp !?O 9$3D$) %#13131$ %#-/#/#
> %#35353 3r%   c                     a a ] tR tRt o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RR7      R 4       tRR ltR]3R lt]! RRRR7      R 4       tRR ltR tR]3R lt]! RRRR7      R 4       tRtVtV ;t# )r   ir  aN  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 has been deprecated, and will be 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.

:param autoload:
    Set to ``False`` to prevent the constructor from automatically
    loaded the file from disk.

    .. deprecated:: 1.6
        This has been replaced by the *new* keyword.
        Instead of setting ``autoload=False``, you should use
        ``new=True``. Support for this keyword will be removed
        in Passlib 1.8.

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                >   < W n         \        \        V `  ! V3/ VB  R # rD   )default_realmr   r   r9   )r!   r   r+  r    r=   s   &&&,r"   r9   HtdigestFile.__init__  s    *lD*4848r%   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   rx   r   r   r   r   s   &&&    r"   r`   HtdigestFile._parse_record  sS    &&w/v;!N%& ' '"T}d""r%   c                $    Vw  r4\        R W4V4      # )z	%s:%s:%s
r   )r!   rr   r   r   r   s   &&&  r"   r   HtdigestFile._render_record  s    L$t<<r%   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+  r   r   s   &&r"   _require_realmHtdigestFile._require_realm  s1    =&&E} !E F Fr%   c                H    V P                  V4      pV P                  VR 4      # )r   )r2  r   r   s   &&r"   r   HtdigestFile._encode_realm  s%    ##E*!!%11r%   c                F    V P                  V4      V P                  V4      3# rD   )r   r   r!   r   r   s   &&&r"   _encode_keyHtdigestFile._encode_key#  s#      &(:(:5(AAAr%   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)   Nr   )r   rr   s   & r"   r   &HtdigestFile.realms.<locals>.<genexpr>,  s     5}VV}r   )r   r5   r   )r!   realmsr   s   &  r"   r>  HtdigestFile.realms*  s7    5t}}557=>ve""5)v>>>s   =c                    V P                  V4      pV P                   Uu. uF+  pV^,          V8X  g   K  V P                  V^ ,          4      NK-  	  up# u upi )zReturn list of all users in specified realm.

* uses ``self.default_realm`` if no realm explicitly provided.
* returns empty list if realm not found.
)r   r5   r   )r!   r   rr   s   && r"   r   HtdigestFile.users/  sW     ""5)6:mm $msq6U? +""3q6*m $ 	$ $s
   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r0   )_UNSETr2  r   r   r0   r   r!   r   r   r   r   s   &&&& r"   r   HtdigestFile.set_passwordQ  sH     v"E8##E*}}XU]]K}}T$//r%   r  r  r   r  c                &    V P                  WV4      # r  r	  r!   r   r   r   s   &&&&r"   r   HtdigestFile.updated  s       h77r%   c                    V P                  W4      pV P                  P                  V4      pVf   R# \        '       d   VP	                  V P
                  4      pV# )aX  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 deprecated, and will be removed
    in Passlib 1.8.
N)r8  r5   r   r   r   r0   )r!   r   r   rr   r   s   &&&  r"   r  HtdigestFile.get_hashj  sL     t+}}  %<3;;t}}-Dr%   c                    V\         J d   RTr2\        '       d2   \        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)	rD  r   r   r  r   r0   r8  r}   r   )r!   r   r   r   rr   r|   s   &&&&  r"   r   HtdigestFile.set_hash}  sd     6>43:dC((;;t}}-Dt+##C.r%   r  c                $    V P                  W4      # r  r  r7  s   &&&r"   r  HtdigestFile.find  s     }}T))r%   c                    V P                  W4      p V P                  V T P                  4        R#   \         d     R# i ; i)zDelete 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)r8  r5   r  r   )r!   r   r   rr   s   &&& r"   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 )zDelete 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   r5   r   r   )r!   r   rm   rr   keyss   &&   r"   delete_realmHtdigestFile.delete_realm  sc     ""5)--&:wa&E/w:C 4y	 ;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      # )a  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 is deprecated, and will be removed in Passlib 1.8.
NrC  )rD  r   r   r5   r   r   r$  r0   rE  s   &&&& r"   r  HtdigestFile.check_password  sm    $ v"E8  &""5)}}  $.<xt(,7 	7r%   r  c                &    V P                  WV4      # r"  r#  rH  s   &&&&r"   r$  HtdigestFile.verify  s     ""499r%   )r+  )NNrD   )r>   r   r   r   r   r+  r9   r`   r   r2  r   r8  r>  r   rD  r   r   r   r  r   r  r  rT  r  r$  r   r   r'  r(  s   @@r"   r   r   r  s     B^ M
9#=2B?
$D (,f 0& %#13838& $(f 4 %#-/*/*
" *. 7: %#35:5: :r%   )/r   
__future__r   logging	getLoggerr>   re   rP   warningsr   passlibr   r   passlib.contextr   passlib.excr   passlib.hashr   passlib.utilsr	   r
   r   passlib.utils.decorr   passlib.utils.compatr   r   r   r   __all__objectrD  r   rd   r   rh   ri   r   r   r   r   r   r   r&  r   r   r   r%   r"   <module>rg     s    .
 & g''1 	  " ( + ! @ @ 1 B B  

	 &  

j& jJ %&R *+ *Z *+ X3; X3Bm:; m:r%   