
    gE                     b   S r SSKJr  SSKr\R                  " \5      rSSKrSSKJ	r	  SSK
JrJr  SSKJr  SSKJr  SSKJr  SS	KJrJrJr  SS
KJr  SSKJrJrJrJr  SS/r\" 5       r Sr!Sr"Sr#Sr$Sr% " S S\5      r&\'" 5       r(S r)\)" 5       r*S r+\+" 5       r, " S S\&5      r- " S S\&5      r.g)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                      \ rS rSrSrSrSrSrSrSr	Sr
Sr\S 5       r\S 5       rSSSSS\4S	 jrS
 r\S 5       r\R(                  S 5       r\S 5       rS rSS jrS rS rS rS rS rSS jrS rS rS r S r!S r"S S jr#S r$Sr%g)!_CommonFile,   z0common framework for HtpasswdFile & HtdigestFileNFc                 Z    SU;   a  [        S5      eU " S0 UD6nUR                  U5        U$ )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       G/home/matz/Project1/venv/lib/python3.13/site-packages/passlib/apache.pyfrom_string_CommonFile.from_stringK   s5     T>BCC{T{    c                 8    U " S0 UD6nUR                  U5        U$ )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                 8   U(       d  [        S[        SS9  SnSnO[        U5      (       d  [        S5      eXPl        X`l        X@l        Xl        SU l        U(       d  [        S[        SS9  S	nU(       a  U(       d  U R                  5         g 0 U l
        / U l        g )
Nz``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 compatibler   zp``autoload=False`` is deprecated as of Passlib 1.6, and will be removed in Passlib 1.8, use ``new=True`` insteadT)r   DeprecationWarningr   
ValueErrorencodingreturn_unicodeautosave_path_mtimer)   _records_source)r#   r   newautoloadr5   r3   r4   s          r$   __init___CommonFile.__init__n   s      9 $3 H"N)) FGG  - 
  P#3 CIIKDMDLr'   c                    SnU R                   (       a  US-  nU R                  (       a  USU R                  -  -  nU R                  S:w  a  USU R                  -  -  nSU R                  R                  [        U 5      U4-  $ )N z autosave=Truez path=%rr,   z encoding=%rz<%s 0x%0x%s>)r5   r6   r3   	__class____name__id)r#   tails     r$   __repr___CommonFile.__repr__   sr    ==$$D::J++D==G#NT]]22D!8!8"T(D IIIr'   c                     U R                   $ N)r6   r#   s    r$   r   _CommonFile.path   s    zzr'   c                 <    XR                   :w  a  SU l        Xl         g )Nr   )r6   r7   r#   values     r$   r   rI      s    JJDK
r'   c                     U R                   $ )z7modify time when last loaded (if bound to a local file))r7   rH   s    r$   mtime_CommonFile.mtime   s     {{r'   c                     U R                   (       d  [        SU -  5      eU R                  (       a8  U R                  [        R                  R                  U R                   5      :X  a  gU R                  5         g)zBReload from ``self.path`` only if file has changed since last loadz%r is not bound to a local fileFT)r6   RuntimeErrorr7   osr   getmtimer)   rH   s    r$   load_if_changed_CommonFile.load_if_changed   sN    zz@4GHH;;4;;"''*:*:4::*FF		r'   c                 T   Ub.  [        US5       nSU l        U R                  U5        SSS5        g	U(       d=  [        S[	        U R
                  R                  S9-  [        SS9  U R                  5       $ U R                  (       a_  [        U R                  S5       n[        R                  R                  U R                  5      U l        U R                  U5        SSS5        g	[        SU R
                  R                  -  5      e! , (       d  f       g	= f! , (       d  f       g	= f)
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rbr   z%(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.   r/   z2%s().path is not set, an explicit path is requiredT)openr7   _load_linesr   dictr@   rA   r1   rT   r6   rR   r   rS   rQ   )r#   r   forcefhs       r$   r)   _CommonFile.load   s     dD!R  $ ""   ; 4>>2234 $	3
 ''))ZZdjj$'2 gg..tzz:  $ (  S#~~66 7 8 8 "!"  (' s   DA D
D
D'c                 r    [        XR                  S5      nSU l        U R                  [	        U5      5        g)z@Load state from unicode or bytes string, replacing current stater!   r   N)r   r3   r7   rZ   r   )r#   r!   s     r$   r   _CommonFile.load_string   s+    mmV4'r'   c                    U R                   n0 n/ nSn[        U5       H  u  pgUR                  5       nU(       a  UR                  [        5      (       a  XW-  nM<  U" XvS-   5      u  pX;   a  [
        R                  SU	-  5        XW-  nMl  U(       a  UR                  [        U45        SnXU	'   UR                  [        U	45        M     UR                  5       (       a  UR                  [        U45        X0l        X@l        g)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rstripr8   r9   )r#   linesparserecordssourcer   idxlinetmpkeyrL   s              r$   rZ   _CommonFile._load_lines   s    """5)IC ++-C#..00 tU+JC ~ORUUV x12 !CLMM7C.)5 *: >>MM8W-.  r'   c                     [        S5      e)z)parse line of file into (key, value) pair!should be implemented in subclassNotImplementedError)r#   r   linenos      r$   rc   _CommonFile._parse_record      !"EFFr'   c                 ~    U R                   nX;   nX#U'   U(       d!  U R                  R                  [        U45        U$ )z{
helper for setting record which takes care of inserting source line if needed;

:returns:
    bool if key already present
)r8   r9   rj   rl   )r#   ru   rL   rp   existings        r$   _set_record_CommonFile._set_record  s9     --NLL#/r'   c                 l    U R                   (       a#  U R                  (       a  U R                  5         ggg)z0subclass helper to call save() after any changesN)r5   r6   saverH   s    r$   	_autosave_CommonFile._autosave!  s    ==TZZIIK (=r'   c                    Ub5  [        US5       nUR                  U R                  5       5        SSS5        gU R                  (       aJ  U R	                  U R                  5        [
        R                  R                  U R                  5      U l        g[        SU R                  R                  -  5      e! , (       d  f       g= f)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)rY   
writelines_iter_linesr6   r   rR   r   rS   r7   rQ   r@   rA   )r#   r   r]   s      r$   r   _CommonFile.save&  s     dD!Rd..01 "!ZZIIdjj!''**4::6DKF#~~66 7 8 8 "!s    B66
Cc                 4    [        U R                  5       5      $ )z)Export current state as a string of bytes)r   r   rH   s    r$   	to_string_CommonFile.to_string4  s    $**,--r'   c              #   "  #    U R                   n [        U5      nU R                   HP  u  p4U[        :X  a  Uv   M  U[        :X  d   eXA;  a  M(  U R                  XAU   5      v    UR                  U5        MR      U(       a   SU< 35       eg7f)z#iterator yielding lines of databasez%failed to write all records: missing=N)r8   setr9   rk   rl   _render_recordremove)r#   rp   pendingactioncontents        r$   r   _CommonFile._iter_lines@  s      --'lG#||OF!((() ))'73CDDNN7+  ,  VW VV;ws   BBc                     [        S5      e)z,given key/value pair, encode as line of filerx   ry   )r#   ru   rL   s      r$   r   _CommonFile._render_record[  r}   r'   c                 &    U R                  US5      $ )z)user-specific wrapper for _encode_field()user_encode_fieldr#   r   s     r$   _encode_user_CommonFile._encode_userb  s    !!$//r'   c                 &    U R                  US5      $ )z*realm-specific wrapper for _encode_field()realmr   r#   r   s     r$   _encode_realm_CommonFile._encode_realmf  s    !!%11r'   c                 <   [        U[        5      (       a  UR                  U R                  5      nO [        U[        5      (       d  [        X5      e[        U5      S:  a  [        U< SU< 35      e[        S U 5       5      (       a  [        U< SU< 35      eU$ )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   #    U  H  o[         ;   v   M     g 7frG   )_INVALID_FIELD_CHARS).0cs     r$   	<genexpr>,_CommonFile._encode_field.<locals>.<genexpr>  s     8%Q((%s   z contains invalid characters: )	
isinstancer   encoder3   bytesr   lenr2   any)r#   rL   params      r$   r   _CommonFile._encode_fieldj  s    " eW%%LL/EE5))%e33u:#U, - -8%888#U- . .r'   c                     [        U[        5      (       d   S5       eU R                  (       a  UR                  U R                  5      $ U$ )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   r4   decoder3   rK   s     r$   _decode_field_CommonFile._decode_field  s>     %''E)EE'<<..Lr'   )r7   r6   r8   r9   r5   r3   r4   )NTrG   )field)&rA   
__module____qualname____firstlineno____doc__r3   r4   r6   r7   r5   r8   r9   classmethodr%   r*   r   r<   rD   propertyr   setterrN   rT   r)   r   rZ   rc   r   r   r   r   r   r   r   r   r   r   __static_attributes__r   r'   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            	         S n S H"  n[         R                  " U5      (       d  M   Un   O   [         R                  " S5      (       a  SOS n[        R	                  5         U(       d  [        R                  / SQ5        [        U=(       d    SSU=(       d    U =(       d    SU =(       d    SU=(       d    SSS9nUR                  US   US   S	9  U$ )
N)bcryptsha256_cryptr   )portable_apache_24host_apache_24linux_apache_24portablehostapr_md5_cryptr   )r   portable_apache_22r   host_apache_22r   linux_apache_22r   r   )r   r   )r   has_os_crypt_supporthas_backend_warn_no_bcryptclearupdater[   )	host_bestrX   r   defaultss       r$   _init_default_schemesr     s     I*((..I + "--h77XTF  G 	H !4_* ==o 3O 0.&H" OO./&'   Or'   c                      / SQn U R                  [        R                  " 5       5        U S S S/-   U -   n[        [	        U 5      UR
                  S9n [        U [        S   SS9$ )N)r   r   sha512_crypt	des_cryptr   	ldap_sha1	plaintext   r   )ru   r   2y)schemesdefaultbcrypt__ident)extendr   get_supported_os_crypt_schemessortedr   indexr   htpasswd_defaults)r   	preferreds     r$   _init_htpasswd_contextr     sp    G0 NN8::<= //'9IS\y7G  ""67  r'   c                      ^  \ rS rSrSrSS\4U 4S jjrS rS rS r	S r
\" S	S
SS9S 5       rS rS r\" S	S
SS9S 5       rS rS r\" S	S
SS9S 5       rSrU =r$ )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                 ,  > SU;   a   [        S[        SS9  UR                  S5      nU(       aK  U[        ;   a  [        SU-  [        R
                  5        [        R                  X"5      nUR                  US9nX0l	        [        [        U ]2  " U40 UD6  g )Nr   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.   r/   zPHtpasswdFile: no bcrypt backends available, using fallback for default scheme %r)r   )r   r1   popr   r   PasslibSecurityWarningr   getcopycontextsuperr   r<   )r#   r   default_schemer   r"   r@   s        r$   r<   HtpasswdFile.__init__  s     * $3 "XXi0N0 <>LM//1 /22>RNll>l:GlD*4848r'   c                     UR                  5       R                  [        5      n[        U5      S:w  a  [	        SU-  5      eU$ )Nr.   z/malformed htpasswd file (error reading line %d)rm   split_BCOLONr   r2   )r#   r   r{   results       r$   rc   HtpasswdFile._parse_record  sA    &&w/v;!N%& ' 'r'   c                     [        SX5      $ )Nz%s:%s
r
   )r#   r   hashs      r$   r   HtpasswdFile._render_record  s    It22r'   c                 b    U R                    Vs/ s H  oR                  U5      PM     sn$ s  snf )z&
Return list of all users in database
)r8   r   r   s     r$   usersHtpasswdFile.users  s)     6:]]C]T""4(]CCCs   ,c                 Z    U R                   R                  U5      nU R                  X5      $ )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                 $    U R                  X5      $ zset password for userr   r#   r   r   s      r$   r   HtpasswdFile.update  s       00r'   c                 `     U R                   U R                  U5         $ ! [         a     gf = f)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)r8   r   KeyErrorr   s     r$   get_hashHtpasswdFile.get_hash  s3    	==!2!24!899 		s     
--c                     [         (       a0  [        U[        5      (       a  UR                  U R                  5      nU R                  U5      nU R                  X5      nU R                  5         U$ )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   r3   r   r   r   )r#   r   r   r   s       r$   r   HtpasswdFile.set_hash  sV     3:dC((;;t}}-D  &##D/r'   r  c                 $    U R                  U5      $ zreturn hash for userr  r   s     r$   findHtpasswdFile.find1  s     }}T""r'   c                 ~     U R                   U R                  U5      	 U R                  5         g! [         a     gf = f)zcDelete user's entry.

:returns:
    * ``True`` if user deleted.
    * ``False`` if user not found.
FT)r8   r   r  r   r   s     r$   deleteHtpasswdFile.delete8  sA    	d//56 	  		s   / 
<<c                 r   U R                  U5      nU R                  R                  U5      nUc  g[        U[        5      (       a  UR                  U R                  5      nU R                  R                  X#5      u  pEU(       a2  Ub/  XR                  ;   d   eXPR                  U'   U R                  5         U$ )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   r8   r   r   r   r   r3   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                 $    U R                  X5      $ zverify password for userr  r
  s      r$   verifyHtpasswdFile.verifye  s     ""422r'   )r   )rA   r   r   r   r   htpasswd_contextr<   rc   r   r   r   r   r   r  r   r  r  r  r$  r   __classcell__r@   s   @r$   r   r     s    mp !?O 9$3D$) %#13131$ %#-/#/#
> %#35353r'   c                      ^  \ rS rSrSrSrSU 4S jjrS rS rS r	S r
S	 rS
 rSS jrS\4S jr\" SSSS9S 5       rSS jrS\4S jr\" SSSS9S 5       rSS jrS rS\4S jr\" SSSS9S 5       rSrU =r$ )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                 <   > X l         [        [        U ]  " U40 UD6  g rG   )default_realmr   r   r<   )r#   r   r+  r"   r@   s       r$   r<   HtdigestFile.__init__  s    *lD*4848r'   c                     UR                  5       R                  [        5      n[        U5      S:w  a  [	        SU-  5      eUu  pEnXE4U4$ )Nr   z/malformed htdigest file (error reading line %d)r   )r#   r   r{   r   r   r   r   s          r$   rc   HtdigestFile._parse_record  sS    &&w/v;!N%& ' '"T}d""r'   c                 $    Uu  p4[        SX4U5      $ )Nz	%s:%s:%s
r   )r#   ru   r   r   r   s        r$   r   HtdigestFile._render_record  s    L$t<<r'   c                 @    Uc  U R                   nUc  [        S5      eU$ )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    U R                  U5      nU R                  US5      $ )Nr   )r2  r   r   s     r$   r   HtdigestFile._encode_realm  s%    ##E*!!%11r'   c                 F    U R                  U5      U R                  U5      4$ rG   )r   r   r#   r   r   s      r$   _encode_keyHtdigestFile._encode_key#  s#      &(:(:5(AAAr'   c                     [        S U R                   5       5      nU Vs/ s H  o R                  U5      PM     sn$ s  snf )z%Return list of all realms in databasec              3   *   #    U  H	  oS    v   M     g7f)rb   Nr   )r   ru   s     r$   r   &HtdigestFile.realms.<locals>.<genexpr>,  s     5}V}s   )r   r8   r   )r#   realmsr   s      r$   r=  HtdigestFile.realms*  s7    5t}}557=>ve""5)v>>>s   >c                     U R                  U5      nU R                   Vs/ s H"  nUS   U:X  d  M  U R                  US   5      PM$     sn$ s  snf )zReturn list of all users in specified realm.

* uses ``self.default_realm`` if no realm explicitly provided.
* returns empty list if realm not found.
rb   r   )r   r8   r   )r#   r   ru   s      r$   r   HtdigestFile.users/  sW     ""5)6:mm $msq6U? +""3q6*m $ 	$ $s
   AAc                     U[         L a  SUp2U R                  U5      n[        R                  " X1X R                  S9nU R                  XU5      $ )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r3   )_UNSETr2  r	   r   r3   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                 &    U R                  XU5      $ r  r	  r#   r   r   r   s       r$   r   HtdigestFile.updated  s       h77r'   c                     U R                  X5      nU R                  R                  U5      nUc  g[        (       a  UR	                  U R
                  5      nU$ )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  r8   r   r   r   r3   )r#   r   r   ru   r   s        r$   r  HtdigestFile.get_hashj  sL     t+}}  %<3;;t}}-Dr'   c                     U[         L a  SUp2[        (       a0  [        U[        5      (       a  UR	                  U R
                  5      nU R                  X5      nU R                  XC5      nU R                  5         U$ )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)	rC  r   r   r  r   r3   r8  r   r   )r#   r   r   r   ru   r   s         r$   r   HtdigestFile.set_hash}  sd     6>43:dC((;;t}}-Dt+##C.r'   r  c                 $    U R                  X5      $ r  r  r7  s      r$   r  HtdigestFile.find  s     }}T))r'   c                     U R                  X5      n U R                  U	 U R                  5         g! [         a     gf = f)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  r8   r  r   )r#   r   r   ru   s       r$   r  HtdigestFile.delete  sH     t+	c" 	  		s   1 
>>c                     U R                  U5      nU R                  nU Vs/ s H  o3S   U:X  d  M  UPM     nnU H  nX#	 M     U R                  5         [        U5      $ s  snf )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)
rb   )r   r8   r   r   )r#   r   rp   ru   keyss        r$   delete_realmHtdigestFile.delete_realm  sa     ""5)--&:wa&E/w:C 4y	 ;s
   A A c                     U[         L a  SUp2U R                  U5      nU R                  U5      nU R                  R	                  X45      nUc  g[
        R                  " X4XU R                  S9$ )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.
NrB  )rC  r   r   r8   r   r	   r$  r3   rD  s        r$   r  HtdigestFile.check_password  sm    $ v"E8  &""5)}}  $.<xt(,7 	7r'   r  c                 &    U R                  XU5      $ r"  r#  rG  s       r$   r$  HtdigestFile.verify  s     ""499r'   )r+  )NNrG   )rA   r   r   r   r   r+  r<   rc   r   r2  r   r8  r=  r   rC  r   r   r   r  r   r  r  rS  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	getLoggerrA   rh   rR   warningsr   passlibr   r   passlib.contextr   passlib.excr   passlib.hashr	   passlib.utilsr
   r   r   passlib.utils.decorr   passlib.utils.compatr   r   r   r   __all__objectrC  r   rg   r   rk   rl   r   r   r   r   r   r   r&  r   r   r   r'   r$   <module>rf     s    .
 & g''1 	  " ( + ! @ @ 1 B B  

	 &  

j& jJ %&R *+ *Z *+ X3; X3Bm:; m:r'   