
    K}bgE                        d Z ddlmZ ddlZ ej        e          ZddlZddlm	Z	 ddl
mZmZ ddlmZ ddlmZ ddlmZ dd	lmZmZmZ dd
lmZ ddlmZmZmZmZ ddgZ e            Z dZ!dZ"dZ#dZ$dZ% G d de          Z& e'            Z(d Z) e)            Z*d Z+ e+            Z, G d de&          Z- G d de&          Z.dS )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                       e Zd ZdZdZdZdZdZdZdZ	dZ
ed             Zed             ZdddddefdZd	 Zed
             Zej        d             Zed             Zd ZddZd Zd Zd Zd Zd ZddZd Zd Zd Zd Z d Z!ddZ"d Z#dS ) _CommonFilez0common framework for HtpasswdFile & HtdigestFileNFc                 f    d|v rt          d           | di |}|                    |           |S )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       a/home/e360mart.nyusoft.in/public_html/e360mart_env/lib/python3.11/site-packages/passlib/apache.pyfrom_stringz_CommonFile.from_stringK   sF     T>>BCCCs{{T{{    c                 @     | di |}|                     |           |S )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_pathz_CommonFile.from_path\   s)     s{{T{{		$r%   Tutf-8c                 J   |st          dt          d           d}d}nt          |          st          d          || _        || _        || _        || _        d| _        |st          dt          d           d	}|r|s| 	                                 d S i | _
        g | _        d S )
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autoloadr2   r0   r1   s          r#   __init__z_CommonFile.__init__n   s      
	H 9 $3 3 3 3 H"NN)) 	H FGGG  - 
  	 P#3 3 3 3 C 	 	IIKKKKKDMDLLLr%   c                     d}| j         r|dz  }| j        r|d| j        z  z  }| j        dk    r|d| j        z  z  }d| j        j        t          |           |fz  S )N z autosave=Truez path=%rr)   z encoding=%rz<%s 0x%0x%s>)r2   r3   r0   	__class____name__id)r"   tails     r#   __repr__z_CommonFile.__repr__   sr    = 	%$$D: 	,J++D=G##NT]22D!8"T((D IIIr%   c                     | j         S N)r3   r"   s    r#   r   z_CommonFile.path   s
    zr%   c                 8    || j         k    rd| _        || _         d S )Nr   )r3   r4   r"   values     r#   r   z_CommonFile.path   s!    DJDK


r%   c                     | j         S )z7modify time when last loaded (if bound to a local file))r4   rC   s    r#   mtimez_CommonFile.mtime   s     {r%   c                     | j         st          d| z            | j        r/| j        t          j                            | j                   k    rdS |                                  dS )zBReload from ``self.path`` only if file has changed since last loadz%r is not bound to a local fileFT)r3   RuntimeErrorr4   osr   getmtimer'   rC   s    r#   load_if_changedz_CommonFile.load_if_changed   s`    z 	I@4GHHH; 	4;"'*:*:4:*F*FFF5		tr%   c                 B   |Et          |d          5 }d| _        |                     |           ddd           n# 1 swxY w Y   n|sFt          dt	          | j        j                  z  t          d           |                                 S | j	        rlt          | j	        d          5 }t          j                            | j	                  | _        |                     |           ddd           n# 1 swxY w Y   nt          d| j        j        z            d	S )
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)openr4   _load_linesr   dictr<   r=   r.   rM   r3   rK   r   rL   rJ   )r"   r   forcefhs       r#   r'   z_CommonFile.load   s     dD!! %R  $$$% % % % % % % % % % % % % % %  	8 ; 4>23334 $	3 3 3 3
 '')))Z 	8dj$'' %2 g..tz::  $$$% % % % % % % % % % % % % % % S#~6 7 8 8 8ts!   <A A ,?C77C;>C;c                     t          || j        d          }d| _        |                     t	          |                     dS )z@Load state from unicode or bytes string, replacing current stater    r   N)r   r0   r4   rR   r   )r"   r    s     r#   r   z_CommonFile.load_string   s<    dmV44'''''r%   c                 &   | j         }i }g }d}t          |          D ]\  }}|                                }|r|                    t                    r||z  }; |||dz             \  }	}
|	|v r#t
                              d|	z             ||z  }t|r|                    t          |f           d}|
||	<   |                    t          |	f           |
                                r|                    t          |f           || _        || _        dS )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keyrF   s              r#   rR   z_CommonFile._load_lines   s>   ""5)) 	* 	*IC ++--C #..00 4 tSU++JC g~~ORUUVVV4  x1222 !GCLMM7C.)))) >> 	/MM8W-...  r%   c                      t          d          )z)parse line of file into (key, value) pair!should be implemented in subclassNotImplementedError)r"   r   linenos      r#   rY   z_CommonFile._parse_record      !"EFFFr%   c                 l    | j         }||v }|||<   |s!| j                            t          |f           |S )z
        helper for setting record which takes care of inserting source line if needed;

        :returns:
            bool if key already present
        )r5   r6   r`   rb   )r"   rk   rF   rf   existings        r#   _set_recordz_CommonFile._set_record  sD     -7N 	0L#///r%   c                 R    | j         r| j        r|                                  dS dS dS )z0subclass helper to call save() after any changesN)r2   r3   saverC   s    r#   	_autosavez_CommonFile._autosave!  s:    = 	TZ 	IIKKKKK	 	 	 	r%   c                 z   |Rt          |d          5 }|                    |                                            ddd           dS # 1 swxY w Y   dS | j        rE|                     | j                   t
          j                            | j                  | _        dS t          d| j
        j        z            )zhSave current state to file.
        If no path is specified, attempts to save to ``self.path``.
        Nwbz%%s().path is not set, cannot autosave)rQ   
writelines_iter_linesr3   rv   rK   r   rL   r4   rJ   r<   r=   )r"   r   rU   s      r#   rv   z_CommonFile.save&  s     dD!! 2Rd..001112 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2Z 	8IIdj!!!'**4:66DKKKF#~6 7 8 8 8s   (AAAc                 D    t          |                                           S )z)Export current state as a string of bytes)r   r{   rC   s    r#   	to_stringz_CommonFile.to_string4  s    $**,,---r%   c              #     K   | j         }	 t          |          }| j        D ][\  }}|t          k    r|V  |t          k    sJ ||vr'|                     |||                   V  	 |                    |           \	 |rJ d|            dS )z#iterator yielding lines of databaseTz%failed to write all records: missing=N)r5   setr6   ra   rb   _render_recordremove)r"   rf   pendingactioncontents        r#   r{   z_CommonFile._iter_lines@  s       -	#'llG#| 	, 	,OFG!!((((')) ))'773CDDDDD,NN7++++	W VVVWW VVV;VVr%   c                      t          d          )z,given key/value pair, encode as line of filerm   rn   )r"   rk   rF   s      r#   r   z_CommonFile._render_record[  rq   r%   c                 .    |                      |d          S )z)user-specific wrapper for _encode_field()user_encode_fieldr"   r   s     r#   _encode_userz_CommonFile._encode_userb  s    !!$///r%   c                 .    |                      |d          S )z*realm-specific wrapper for _encode_field()realmr   r"   r   s     r#   _encode_realmz_CommonFile._encode_realmf  s    !!%111r%   fieldc                 X   t          |t                    r|                    | j                  }n%t          |t                    st          ||          t          |          dk    rt          |d|          t          d |D                       rt          |d|          |S )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   (   K   | ]}|t           v V  d S rB   )_INVALID_FIELD_CHARS).0cs     r#   	<genexpr>z,_CommonFile._encode_field.<locals>.<genexpr>  s(      88Qq((888888r%   z contains invalid characters: )	
isinstancer   encoder0   bytesr   lenr/   any)r"   rF   params      r#   r   z_CommonFile._encode_fieldj  s    " eW%% 	4LL//EEE5)) 	4%eU333u::#eeUU, - - -88%88888 	.#eeUU- . . .r%   c                     t          |t                    s
J d            | j        r|                    | j                  S |S )aW  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   rE   s     r#   _decode_fieldz_CommonFile._decode_field  sG     %''EE)EEE' 	<<...Lr%   )NTrB   )r   )$r=   
__module____qualname____doc__r0   r1   r3   r4   r2   r5   r6   classmethodr$   r(   r   r9   r@   propertyr   setterrH   rM   r'   r   rR   rY   rt   rw   rv   r}   r{   r   r   r   r   r   r   r%   r#   r   r   ,   s       :: H N EF H H G
   [    [" !edU!#! ! ! !FJ J J   X 
[  [
   X  " " " "H( ( (( ( (TG G G  "  
8 8 8 8. . .W W W6G G G0 0 02 2 2   :    r%   r   c                  f   d } dD ]}t          j        |          r|}  nt          j        d          rdnd }t                                           |st                              g d           t          |pdd|p| pd| pd|pdd          }|                    |d         |d         	           |S )
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updaterS   )	host_bestrP   r   defaultss       r#   _init_default_schemesr     s    I*  (.. 	IE	 "-h77AXXTF H  G  G  G 	H 	H 	H !4_* ==o 3O 0.&  H" OO./&'     Or%   c                      g d} |                      t          j                               | d d         dgz   | z   }t          t	          |           |j                  } t          | t          d         d          S )N)r   r   sha512_crypt	des_cryptr   	ldap_sha1	plaintext   r   )rk   r   2y)schemesdefaultbcrypt__ident)extendr   get_supported_os_crypt_schemessortedr   indexr   htpasswd_defaults)r   	preferreds     r#   _init_htpasswd_contextr     s      G0 NN8:<<=== //'9IS\\y777G  ""67    r%   c                        e Zd ZdZddef fd	Zd Zd Zd Zd Z	 e
dd	d
          d             Zd Zd Z e
dd	d          d             Zd Zd Z e
dd	d          d             Z xZS )r   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                 j   d|v r,t          dt          d           |                    d          }|rW|t          v rt          d|z  t          j                   t                              ||          }|                    |          }|| _	         t          t          |           j        |fi | d S )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   r.   popr   r   PasslibSecurityWarningr   getcopycontextsuperr   r9   )r"   r   default_schemer   r!   r<   s        r#   r9   zHtpasswdFile.__init__  s     * $3 3 3 3 "XXi00N 	;00 <>LM/1 1 1 /22>>RRNll>l::G*lD!!*488488888r%   c                     |                                                     t                    }t          |          dk    rt	          d|z            |S )Nr+   z/malformed htpasswd file (error reading line %d)rc   split_BCOLONr   r/   )r"   r   rp   results       r#   rY   zHtpasswdFile._parse_record  sP    &&w//v;;!N%& ' ' 'r%   c                 $    t          d||          S )Nz%s:%s
r
   )r"   r   hashs      r#   r   zHtpasswdFile._render_record  s    ItT222r%   c                 *      fd j         D             S )z6
        Return list of all users in database
        c                 :    g | ]}                     |          S r   r   )r   r   r"   s     r#   
<listcomp>z&HtpasswdFile.users.<locals>.<listcomp>  s'    CCCT""4((CCCr%   )r5   rC   s   `r#   userszHtpasswdFile.users  s"     DCCCT]CCCCr%   c                 b    | j                             |          }|                     ||          S )a  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_passwordzHtpasswdFile.set_password  s-     |  **}}T4(((r%   1.61.8r   
deprecatedremovedreplacementc                 .    |                      ||          S zset password for userr   r"   r   r   s      r#   r   zHtpasswdFile.update  s       x000r%   c                 f    	 | j         |                     |                   S # t          $ r Y dS w xY w)a  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 is deprecated, and will be removed
            in Passlib 1.8.
        N)r5   r   KeyErrorr   s     r#   get_hashzHtpasswdFile.get_hash  sD    	=!2!24!8!899 	 	 	44	s   " 
00c                     t           r/t          |t                    r|                    | j                  }|                     |          }|                     ||          }|                                  |S )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   rt   rw   )r"   r   r   rs   s       r#   r   zHtpasswdFile.set_hash  sm      	.:dC(( 	.;;t}--D  &&##D$//r%   r   c                 ,    |                      |          S zreturn hash for userr   r   s     r#   findzHtpasswdFile.find1  s     }}T"""r%   c                     	 | j         |                     |          = n# t          $ r Y dS w xY w|                                  dS )zDelete user's entry.

        :returns:
            * ``True`` if user deleted.
            * ``False`` if user not found.
        FT)r5   r   r   rw   r   s     r#   deletezHtpasswdFile.delete8  sY    	d//5566 	 	 	55	ts    
,,c                 `   |                      |          }| j                            |          }|dS t          |t                    r|                    | j                  }| j                            ||          \  }}|r+|)|| j        v sJ || j        |<   | 	                                 |S )aM  
        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_updaterw   )r"   r   r   r   oknew_hashs         r#   check_passwordzHtpasswdFile.check_passwordF  s       &&}  &&<4h(( 	6  t}55H|55hEEH 	(&4=(((("*DM$NN	r%   r   c                 .    |                      ||          S zverify password for userr   r   s      r#   verifyzHtpasswdFile.verifye  s     ""4222r%   )r=   r   r   r   htpasswd_contextr9   rY   r   r   r   r   r   r   r   r   r   r   r  __classcell__r<   s   @r#   r   r     st       m mp !?O 9 9 9 9 9 9$  3 3 3D D D$) ) ) %#13 3 31 13 31    $ %#-/ / /# #/ /#
    > %#35 5 53 35 53 3 3 3 3r%   c                       e Zd ZdZdZd fd	Zd Zd Zd Zd Z	d Z
d	 Zdd
ZdefdZ eddd          d             ZddZdefdZ eddd          d             ZddZd ZdefdZ eddd          d             Z xZS )r   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 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    || _          t          t          |           j        |fi | d S rB   )default_realmr   r   r9   )r"   r   r	  r!   r<   s       r#   r9   zHtdigestFile.__init__  s6    **lD!!*488488888r%   c                     |                                                     t                    }t          |          dk    rt	          d|z            |\  }}}||f|fS )Nr   z/malformed htdigest file (error reading line %d)r   )r"   r   rp   r   r   r   r   s          r#   rY   zHtdigestFile._parse_record  sf    &&w//v;;!N%& ' ' '"eTe}d""r%   c                 0    |\  }}t          d|||          S )Nz	%s:%s:%s
r   )r"   rk   r   r   r   s        r#   r   zHtdigestFile._render_record  s    eL$t<<<r%   c                 :    || j         }|t          d          |S )NzGyou must specify a realm explicitly, or set the default_realm attribute)r	  r   r   s     r#   _require_realmzHtdigestFile._require_realm  s4    =&E} !E F F Fr%   c                 X    |                      |          }|                     |d          S )Nr   )r  r   r   s     r#   r   zHtdigestFile._encode_realm  s+    ##E**!!%111r%   c                 V    |                      |          |                     |          fS rB   )r   r   r"   r   r   s      r#   _encode_keyzHtdigestFile._encode_key#  s)      &&(:(:5(A(AAAr%   c                 \     t          d  j        D                       } fd|D             S )z%Return list of all realms in databasec              3   &   K   | ]}|d          V  dS )rX   Nr   )r   rk   s     r#   r   z&HtdigestFile.realms.<locals>.<genexpr>,  s&      55SV555555r%   c                 :    g | ]}                     |          S r   r   )r   r   r"   s     r#   r   z'HtdigestFile.realms.<locals>.<listcomp>-  s'    >>>e""5))>>>r%   )r   r5   )r"   realmss   ` r#   r  zHtdigestFile.realms*  s;    55t}55555>>>>v>>>>r%   c                 X                                      fd j        D             S )zReturn list of all users in specified realm.

        * uses ``self.default_realm`` if no realm explicitly provided.
        * returns empty list if realm not found.
        c                 ^    g | ])}|d          k                         |d                   *S )rX   r   r   )r   rk   r   r"   s     r#   r   z&HtdigestFile.users.<locals>.<listcomp>6  s?     $ $ $sq6U?? ""3q6**"??r%   )r   r5   r   s   ``r#   r   zHtdigestFile.users/  sJ     ""5))$ $ $ $ $dm $ $ $ 	$r%   c                     |t           u rd|}}|                     |          }t          j        |||| j                  }|                     |||          S )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   )_UNSETr  r	   r   r0   r   r"   r   r   r   r   s        r#   r   zHtdigestFile.set_passwordQ  s[     v"E8E##E**}XtUT]KKK}}T5$///r%   r   r   r   r   c                 0    |                      |||          S r   r   r"   r   r   r   s       r#   r   zHtdigestFile.updated  s       uh777r%   c                     |                      ||          }| j                            |          }|dS t          r|                    | j                  }|S )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 deprecated, and will be removed
            in Passlib 1.8.
        N)r  r5   r   r   r   r0   )r"   r   r   rk   r   s        r#   r   zHtdigestFile.get_hashj  sX     tU++}  %%<4 	.;;t}--Dr%   c                    |t           u rd|}}t          r/t          |t                    r|                    | j                  }|                     ||          }|                     ||          }|                                  |S )a  
        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)	r  r   r   r   r   r0   r  rt   rw   )r"   r   r   r   rk   rs   s         r#   r   zHtdigestFile.set_hash}  s     6>>4E 	.:dC(( 	.;;t}--DtU++##C..r%   r   c                 .    |                      ||          S r   r   r  s      r#   r   zHtdigestFile.find  s     }}T5)))r%   c                     |                      ||          }	 | j        |= n# t          $ r Y dS w xY w|                                  dS )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)r  r5   r   rw   )r"   r   r   rk   s       r#   r   zHtdigestFile.delete  sb     tU++	c"" 	 	 	55	ts   ! 
//c                     |                                | j        }fd|D             }|D ]}||= |                                  t          |          S )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)
        c                 ,    g | ]}|d          k    |S )rX   r   )r   rk   r   s     r#   r   z-HtdigestFile.delete_realm.<locals>.<listcomp>  s"    :::#a&E/////r%   )r   r5   rw   r   )r"   r   rf   keysrk   s    `   r#   delete_realmzHtdigestFile.delete_realm  sl     ""5))-::::w::: 	 	C4yyr%   c                     |t           u rd|}}|                     |          }|                     |          }| j                            ||f          }|dS t          j        ||||| j                  S )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.
        Nr  )r  r   r   r5   r   r	   r  r0   r  s        r#   r   zHtdigestFile.check_password  s    $ v"E8E  &&""5))}  $u..<4xtU(,7 7 7 	7r%   r   c                 0    |                      |||          S r  r  r  s       r#   r  zHtdigestFile.verify  s     ""4999r%   )NNrB   )r=   r   r   r   r	  r9   rY   r   r  r   r  r  r   r  r   r   r   r   r   r   r   r%  r   r  r  r  s   @r#   r   r   r  s       B B^ M
9 9 9 9 9 9# # #= = =  2 2 2B B B? ? ?
$ $ $ $D (,f 0 0 0 0& %#13 3 38 83 38   & $(f    4 %#-/ / /* */ /*
   "   *. 7 7 7 7: %#35 5 5: :5 5: : : : :r%   )/r   
__future__r   logging	getLoggerr=   r^   rK   warningsr   passlibr   r   passlib.contextr   passlib.excr   passlib.hashr	   passlib.utilsr
   r   r   passlib.utils.decorr   passlib.utils.compatr   r   r   r   __all__objectr  r   r]   r   ra   rb   r   r   r   r   r   r   r  r   r   r   r%   r#   <module>r5     s&   . .
 & % % % % % 'g'11 				       " ! ! ! ! ! ! ! ( ( ( ( ( ( + + + + + + ! ! ! ! ! ! @ @ @ @ @ @ @ @ @ @ 1 1 1 1 1 1 B B B B B B B B B B B B  

	 &  

j j j j j& j j jJ #%%& & &R *)++ * * *Z *)++ X3 X3 X3 X3 X3; X3 X3 X3Bm: m: m: m: m:; m: m: m: m: m:r%   