Ë
    hjE¶  ã                   ób  — 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.y)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#y)Ú_CommonFilez0common framework for HtpasswdFile & HtdigestFileNFc                 óV   — d|v rt        d«      ‚ | di |¤Ž}|j                  |«       |S )zöcreate 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       úW/var/www/html/sergio/sergio-backend/venv/lib/python3.12/site-packages/passlib/apache.pyÚfrom_stringz_CommonFile.from_stringK   s5   € ð �T‰>ÜÐBÓCÐCÙ‰{�T‰{ˆØ×Ñ˜ÔØˆó    c                 ó8   —  | di |¤Ž}|j                  |«       |S )zûcreate new object from file, without binding object to file.

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

        :param \*\*kwds:
            all other keywords are the same as in the class constructor
        r   )Úload)r   r   r!   r"   s       r#   Ú	from_pathz_CommonFile.from_path\   s   € ñ ‰{�T‰{ˆØ�	‰	�$ŒØˆr%   Túutf-8c                 ó  — |st        dt        d¬«       d}d}nt        |«      st        d«      ‚|| _        || _        || _        || _        d| _        |st        dt        d¬«       d	}|r|s| j                  «        y i | _
        g | _        y )
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ž   € ñ Üð 9ô $°õ3ð ˆHØ"‰NÜ Ô)ô ÐFÓGÐGØ ˆŒð -ˆÔØ ˆŒØˆŒ
ØˆŒñ Üð Pä#°õ3ð ˆCÙ™Ø�I‰I�KàˆDŒMØˆD�Lr%   c                 óð   — d}| j                   r|dz  }| j                  r|d| j                  z  z  }| j                  dk7  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Ò#Ø�N T§]¡]Ñ2Ñ2ˆDØ §¡×!8Ñ!8¼"¸T»(ÀDÐ IÑIÐIr%   c                 ó   — | j                   S ©N)r3   ©r"   s    r#   r   z_CommonFile.path�   s   € à�z‰zÐr%   c                 ó>   — || j                   k7  rd| _        || _         y )Nr   )r3   r4   ©r"   Úvalues     r#   r   z_CommonFile.path¡   s   € à�D—J‘JÒØˆDŒKØˆ�
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                  r7| j                  t        j                  j                  | j                   «      k(  ry| j                  «        y)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¯   sN   € à�zŠzÜÐ@À4ÑGÓHÐHØ�;Š;˜4Ÿ;™;¬"¯'©'×*:Ñ*:¸4¿:¹:Ó*FÒFØØ�	‰	ŒØr%   c                 ó6  — |�.t        |d«      5 }d| _        | j                  |«       ddd«       y	|sCt        dt	        | j
                  j                  ¬«      z  t        d¬«       | j                  «       S | j                  r_t        | j                  d«      5 }t        j                  j                  | j                  «      | _        | j                  |«       ddd«       y	t        d| j
                  j                  z  «      ‚# 1 sw Y   y	xY w# 1 sw Y   y	xY w)
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û   € ð  ÐÜ�d˜DÔ! RØ�”Ø× Ñ  Ô$÷ "ð" ñ Üð ;ô ˜4Ÿ>™>×2Ñ2Ô3ñ4ô $°õ	3ð
 ×'Ñ'Ó)Ð)Ø�ZŠZÜ�d—j‘j $Ô'¨2Ü Ÿg™g×.Ñ.¨t¯z©zÓ:�”Ø× Ñ  Ô$÷ (ð ô ÐSØ#Ÿ~™~×6Ñ6ñ 7ó 8ð 8÷ "ð" ú÷ (ð ús   �DÂA DÄDÄDc                 ót   — t        || j                  d«      }d| _        | j                  t	        |«      «       y)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-   € ä˜˜dŸm™m¨VÓ4ˆØˆŒØ×Ñœ ›Õ'r%   c                 óâ  — | j                   }i }g }d}t        |«      D ]š  \  }}|j                  «       }|r|j                  t        «      r||z  }Œ3 |||dz   «      \  }	}
|	|v rt
        j                  d|	z  «       ||z  }Œd|r|j                  t        |f«       d}|
||	<   |j                  t        |	f«       Œœ |j                  «       r|j                  t        |f«       || _        || _        y)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Ö)‰IˆC�ð —+‘+“-ˆCÙ˜#Ÿ.™.¬Ô0Ø˜4‘�Øñ ˜t S¨¡UÓ+‰JˆC�ð �g‰~Ü—‘ÐOÐRUÑUÔVØ˜4‘�Øñ Ø—‘œx¨Ð1Ô2Ø�ð !ˆG�C‰LØ�M‰Mœ7 C˜.Õ)ð5 *ð: �>‰>ÔØ�M‰Mœ8 WÐ-Ô.ð  ˆŒØˆ�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ÐFr%   c                 óv   — | j                   }||v }|||<   |s!| j                  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  s=   € ð —-‘-ˆØ˜7�NˆØˆ�‰ÙØ�L‰L×Ñ¤¨# Ô/Øˆr%   c                 óX   — | j                   r| j                  r| j                  «        yyy)z0subclass helper to call save() after any changesN)r2   r3   ÚsaverC   s    r#   Ú	_autosavez_CommonFile._autosave!  s   € à�=Š=˜TŸZšZØ�I‰I�Kð (ˆ=r%   c                 óx  — |�5t        |d«      5 }|j                  | j                  «       «       ddd«       y| j                  rJ| j	                  | j                  «       t
        j                  j                  | j                  «      | _        yt        d| j                  j                  z  «      ‚# 1 sw Y   yxY w)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�   € ð ÐÜ�d˜DÔ! RØ—‘˜d×.Ñ.Ó0Ô1÷ "Ð!à�ZŠZØ�I‰I�d—j‘jÔ!ÜŸ'™'×*Ñ*¨4¯:©:Ó6ˆD�KäÐFØ#Ÿ~™~×6Ñ6ñ 7ó 8ð 8÷ "Ð!ús   � B0Â0B9c                 ó4   — t        | j                  «       «      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 ]L  \  }}|t        k(  r|–— Œ|t        k(  sJ ‚||vrŒ$| j                  |||   «      –— 	 |j                  |«       ŒN 	 |r
J d|›�«       ‚y­w)z#iterator yielding lines of databasez%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—   è ø€ ð —-‘-ˆØÜ˜'“lˆGØ#Ÿ|œ|‰OˆF�GØœÒ!à“à¤Ò(Ð(Ð(à 'Ñ)ð Ø×)Ñ)¨'°7¸7Ñ3CÓDÒDØØ—N‘N 7Õ+ð  ,ð ñ ÑVÉWÐ VÓV�;�wùs   ‚BB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                 ó&   — | j                  |d«      S )z)user-specific wrapper for _encode_field()Úuser©Ú_encode_field©r"   r‡   s     r#   Ú_encode_userz_CommonFile._encode_userb  s   € à×!Ñ! $¨Ó/Ð/r%   c                 ó&   — | j                  |d«      S )z*realm-specific wrapper for _encode_field()Úrealmrˆ   ©r"   r�   s     r#   Ú_encode_realmz_CommonFile._encode_realmf  s   € à×!Ñ! %¨Ó1Ð1r%   c                 ó  — t        |t        «      r|j                  | j                  «      }nt        |t        «      st        ||«      ‚t        |«      dkD  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 –— Œ y ­wrB   )Ú_INVALID_FIELD_CHARS)Ú.0Úcs     r#   Ú	<genexpr>z,_CommonFile._encode_field.<locals>.<genexpr>‚  s   è ø€ Ð8±%¨QˆqÔ(Ô(±%ùs   ‚z contains invalid characters: )	Ú
isinstancer   Úencoder0   Úbytesr   Úlenr/   Úany)r"   rF   Úparams      r#   r‰   z_CommonFile._encode_fieldj  s„   € ô" �eœWÔ%Ø—L‘L §¡Ó/‰EÜ˜E¤5Ô)Ü% e¨UÓ3Ð3Üˆu‹:˜ÒÜÚ#¡Uð,ó -ð -äÑ8±%Ó8Ô8ÜÚ#¡Uð-ó .ð .àˆr%   c                 ó‚   — t        |t        «      sJ d«       ‚| j                  r|j                  | 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‡  s;   € ô ˜%¤Ô'ÐEÐ)EÓEÐ'Ø×ÒØ—<‘< §¡Ó.Ð.àˆLr%   )NTrB   )Úfield)$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ð
 ñó ðð  ñó ðð" ! e°dÀUØ!°#ó!òFJð ñó ðð 
‡[�[ñó ðð
 ñó ðòó"òH(ò(òTGòò"ó
8ò.òWò6Gò0ò2óó:r%   r   c                  óR  — d } dD ]  }t        j                  |«      sŒ|}  n t        j                  d«      rdnd }t        j	                  «        |st        j                  g d¢«       t        |xs dd|xs | xs d| xs d|xs dd¬«      }|j                  |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Ùð +ô "×-Ñ-¨hÔ7‰X¸T€FÜ×ÑÔÙÜ×Ñò  Gô 	Hô à!Ò4 _Ø*ð Ò= Ò=¨oØ Ò3 Oð Ò0 .Ø&ô€Hð" ‡O�OØÐ.Ñ/ØÐ&Ñ'ð ô ð €Or%   c                  óÒ   — g d¢} | j                  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Ë   Þ  sp   € ò€Gð0 ‡N�N”8×:Ñ:Ó<Ô=ð ˜˜�˜Ð/Ñ/°'Ñ9€IÜ”S˜“\ y§¡Ô7€Gô Øô "Ð"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                 ó(  •— d|v r#t        dt        d¬«       |j                  d«      }|rM|t        v rt        d|z  t        j
                  «       t        j                  ||«      }|j                  |¬«      }|| _	        t        t        | �2  |fi |¤Ž y )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ð "ŸX™X iÓ0ˆNÙØ¤Ñ0Üð <Ø>LñMä×/Ñ/ô1ô /×2Ñ2°>À>ÓRˆNØ—l‘l¨>�lÓ:ˆGØˆŒÜŒl˜DÑ*¨4Ñ8°4Ó8r%   c                 ó„   — |j                  «       j                  t        «      }t        |«      dk7  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Ü  sA   € à—‘“×&Ñ&¤wÓ/ˆÜˆv‹;˜!ÒÜÐNØ%ñ&ó 'ð 'àˆr%   c                 ó   — t        d||«      S )Nz%s:%s
©r
   )r"   r‡   Úhashs      r#   r€   zHtpasswdFile._render_recordä  s   € Ü˜I t¨TÓ2Ð2r%   c                 ó^   — | j                   D �cg c]  }| j                  |«      ‘Œ c}S c c}w )z6
        Return list of all users in database
        )r5   rŸ   rŠ   s     r#   ÚuserszHtpasswdFile.usersë  s+   € ð 6:·]²]ÓC±]¨T�×"Ñ" 4Õ(°]ÑCÐCùÒCs   �*c                 ó\   — | j                   j                  |«      }| 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)   € ð �|‰|× Ñ  Ó*ˆØ�}‰}˜T 4Ó(Ð(r%   ú1.6ú1.8râ   ©Ú
deprecatedÚremovedÚreplacementc                 ó&   — | j                  ||«      S ©zset password for user©râ   ©r"   r‡   rá   s      r#   r·   zHtpasswdFile.update  s   € ð × Ñ   xÓ0Ð0r%   c                 ó^   — 	 | j                   | j                  |«         S # t        $ r Y y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  s3   € ð	Ø—=‘= ×!2Ñ!2°4Ó!8Ñ9Ð9øÜò 	Ùð	ús   ‚   	,«,c                 óÎ   — t         r+t        |t        «      r|j                  | j                  «      }| j                  |«      }| j                  ||«      }| 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  sS   € õ ”:˜d¤CÔ(Ø—;‘;˜tŸ}™}Ó-ˆDØ× Ñ  Ó&ˆØ×#Ñ# D¨$Ó/ˆØ�‰ÔØˆr%   rï   c                 ó$   — | j                  |«      S ©zreturn hash for user©rï   rŠ   s     r#   ÚfindzHtpasswdFile.find1  s   € ð �}‰}˜TÓ"Ð"r%   c                 ó|   — 	 | j                   | j                  |«      = | j                  «        y# t        $ r Y yw xY w)zƒDelete user's entry.

        :returns:
            * ``True`` if user deleted.
            * ``False`` if user not found.
        FT)r5   r‹   rî   rw   rŠ   s     r#   ÚdeletezHtpasswdFile.delete8  sA   € ð	Ø—‘˜d×/Ñ/°Ó5Ð6ð 	�‰ÔØøô ò 	Ùð	ús   ‚/ ¯	;º;c                 ó^  — | j                  |«      }| j                  j                  |«      }|€yt        |t        «      r|j                  | j                  «      }| j                  j                  ||«      \  }}|r1|�/|| j                  v sJ ‚|| 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Ÿ   € ð × Ñ  Ó&ˆØ�}‰}× Ñ  Ó&ˆØˆ<ØÜ�h¤Ô(ð  —‘ t§}¡}Ó5ˆHØ—|‘|×5Ñ5°hÀÓE‰ˆˆHÙ�(Ð&à˜4Ÿ=™=Ñ(Ð(Ð(Ø"*ˆD�M‰M˜$ÑØ�N‰NÔØˆ	r%   rü   c                 ó&   — | j                  ||«      S ©zverify password for user©rü   rì   s      r#   ÚverifyzHtpasswdFile.verifye  s   € ð ×"Ñ" 4¨Ó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     s¢   ø„ ñmðp !°Ð?Oõ 9ò$ò3òDò$)ñ  %°Ø#1ô3ñ1ó3ð1òòñ$  %°Ø#-ô/ñ#ó/ð#ò
òñ>  %°Ø#3ô5ñ3ó5ô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                 ó<   •— || _         t        t        | �  |fi |¤Ž y rB   )Údefault_realmrÓ   r   r9   )r"   r   r  r!   r<   s       €r#   r9   zHtdigestFile.__init__  s   ø€ Ø*ˆÔÜŒl˜DÑ*¨4Ñ8°4Ó8r%   c                 ó˜   — |j                  «       j                  t        «      }t        |«      dk7  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  sW   € Ø—‘“×&Ñ&¤wÓ/ˆÜˆv‹;˜!ÒÜÐNØ%ñ&ó 'ð 'à"Ñˆˆe�TØ�eˆ}˜dÐ"Ð"r%   c                 ó(   — |\  }}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  s1   € Øˆ=Ø×&Ñ&ˆEØˆ}Üð !Eó Fð Fàˆr%   c                 óH   — | j                  |«      }| j                  |d«      S )Nr�   )r
  r‰   rŽ   s     r#   r�   zHtdigestFile._encode_realm  s%   € Ø×#Ñ# EÓ*ˆØ×!Ñ! %¨Ó1Ð1r%   c                 óF   — | j                  |«      | j                  |«      fS rB   )r‹   r�   ©r"   r‡   r�   s      r#   Ú_encode_keyzHtdigestFile._encode_key#  s#   € Ø× Ñ  Ó&¨×(:Ñ(:¸5Ó(AÐAÐAr%   c                 ó‚   — t        d„ | j                  D «       «      }|D �cg c]  }| j                  |«      ‘Œ c}S c c}w )z%Return list of all realms in databasec              3   ó&   K  — | ]	  }|d    –— Œ y­w)rX   Nr   )r”   rk   s     r#   r–   z&HtdigestFile.realms.<locals>.<genexpr>,  s   è ø€ Ð5¡} �S˜•V¡}ùs   ‚)r   r5   rŸ   )r"   Úrealmsr�   s      r#   r  zHtdigestFile.realms*  s9   € äÑ5 t§}¢}Ó5Ó5ˆÙ7=Ó>±v¨e�×"Ñ" 5Õ)°vÑ>Ð>ùÒ>s   ¡<c                 ó–   — | j                  |«      }| j                  D �cg c]  }|d   |k(  r| j                  |d   «      ‘Œ  c}S c c}w )z®Return list of all users in specified realm.

        * uses ``self.default_realm`` if no realm explicitly provided.
        * returns empty list if realm not found.
        rX   r   )r�   r5   rŸ   )r"   r�   rk   s      r#   rÞ   zHtdigestFile.users/  sU   € ð ×"Ñ" 5Ó)ˆØ6:·m²mó $±m¨sØ�q‘6˜U’?ð ×"Ñ" 3 q¡6Õ*°mñ $ð 	$ùò $s    #Ac                 ó¨   — |t         u rd|}}| j                  |«      }t        j                  |||| 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  sP   € ð ”vÑà" E�8ˆEØ×#Ñ# EÓ*ˆÜ�}‰}˜X t¨U¸T¿]¹]ÔKˆØ�}‰}˜T 5¨$Ó/Ð/r%   rã   rä   râ   rå   c                 ó(   — | j                  |||«      S rê   rë   ©r"   r‡   r�   rá   s       r#   r·   zHtdigestFile.updated  s   € ð × Ñ   u¨hÓ7Ð7r%   c                 ó¨   — | j                  ||«      }| j                  j                  |«      }|€yt        r|j	                  | 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  sL   € ð ×Ñ˜t UÓ+ˆØ�}‰}× Ñ  Ó%ˆØˆ<ØÝØ—;‘;˜tŸ}™}Ó-ˆDØˆr%   c                 óè   — |t         u rd|}}t        r+t        |t        «      r|j	                  | j
                  «      }| j                  ||«      }| j                  ||«      }| 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}  se   € ð ”6‰>à �4ˆEå”:˜d¤CÔ(Ø—;‘;˜tŸ}™}Ó-ˆDØ×Ñ˜t UÓ+ˆØ×#Ñ# C¨Ó.ˆØ�‰ÔØˆr%   rï   c                 ó&   — | j                  ||«      S ró   rô   r  s      r#   rõ   zHtdigestFile.find—  s   € ð �}‰}˜T 5Ó)Ð)r%   c                 ó‚   — | j                  ||«      }	 | j                  |= | j                  «        y# t        $ r Y yw xY w)záDelete user's entry for specified realm.

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

        :returns:
            * ``True`` if user deleted,
            * ``False`` if user not found in realm.
        FT)r  r5   rî   rw   )r"   r‡   r�   rk   s       r#   r÷   zHtdigestFile.deletež  sJ   € ð ×Ñ˜t UÓ+ˆð	Ø—‘˜cÐ"ð 	�‰ÔØøô ò 	Ùð	ús   ”2 ²	>½>c                 óÀ   — | j                  |«      }| j                  }|D �cg c]  }|d   |k(  sŒ|‘Œ }}|D ]  }||= Œ | j                  «        t        |«      S c c}w )z±Delete all users for specified realm.

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

        :returns: number of users deleted (0 if realm not found)
        rX   )r�   r5   rw   rš   )r"   r�   rf   rk   Úkeyss        r#   Údelete_realmzHtdigestFile.delete_realm¯  se   € ð ×"Ñ" 5Ó)ˆØ—-‘-ˆÙ&Ó:™w˜¨#¨a©&°E«/’˜wˆÐ:ÛˆCØ˜‘ð à�‰ÔÜ�4‹yÐùò	 ;s
   ¢A°Ac                 óæ   — |t         u rd|}}| j                  |«      }| j                  |«      }| j                  j	                  ||f«      }|€y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¾  su   € ð$ ”vÑà" E�8ˆEØ× Ñ  Ó&ˆØ×"Ñ" 5Ó)ˆØ�}‰}× Ñ  $ u Ó.ˆØˆ<ØÜ�‰˜x¨¨t°UØ(,¯©ô7ð 	7r%   rü   c                 ó(   — | j                  |||«      S rþ   rÿ   r  s       r#   r   zHtdigestFile.verifyÛ  s   € ð ×"Ñ" 4¨°Ó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ð^ €Mõ
9ò#ò=òò2òBò?ó
$ðD (,°fó 0ñ&  %°Ø#1ô3ñ8ó3ð8óð& $(¨fó ñ4  %°Ø#-ô/ñ*ó/ð*ó
ò"ð *.¸ó 7ñ:  %°Ø#3ô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>r/     sÒ   ðÙ .õ
 &ã Ð'�g×'Ñ'¨Ó1�Û 	Ý ÷ "Ý (Ý +Ý !ß @Ñ @Ý 1ß BÓ Bð Øð€ñ 
‹€à
€Ø	€ð &Ð ð €Ø
€ô
j�&ô jñJ “%€ò&ñR *Ó+Ð ò*ñZ *Ó+Ð ôX3�;ô X3ôBm:�;õ m:r%   