o
    'hHP                     @  s  d Z ddlmZ ddlZddlZddlZddlmZmZm	Z	m
Z
mZmZ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mZ dd	lmZmZ dd
lmZ er\ddlm Z  dZ!e"e!Z#dZ$e"e$Z%dZ&dSddZ'dTddZ(dUddZ)e&fdVd d!Z*h d"Z+dWd'd(Z,dXd*d+Z-dXd,d-Z.dXd.d/Z/dYdZd4d5Z0	6d[d\d9d:Z1e&fd]d=d>Z2e3d?e4d@ dA Z5e6g dBZ7d^dFdGZ8d_dLdMZ9e&d6d0d6dfd`dQdRZ:dS )azTools to parse and validate a MongoDB URI.

.. seealso:: This module is compatible with both the synchronous and asynchronous PyMongo APIs.
    )annotationsN)TYPE_CHECKINGAnyMappingMutableMappingOptionalSizedUnioncast)unquote_plus)_have_dnspython)_parse_ssl_options)INTERNAL_URI_OPTION_NAME_MAPURI_OPTIONS_DEPRECATION_MAP_CaseInsensitiveDictionaryget_validated_options)ConfigurationError
InvalidURI)_Address)
SSLContextz
mongodb://zmongodb+srv://ii  sstrreturnboolc                 C  sD   t t| D ]}| | dkr| ||d  }t||kr dS qdS )zCheck for unescaped percent signs.

    :param s: A string. `s` can have things like '%25', '%2525',
           and '%E2%85%A8' but cannot have unquoted percent like '%foo'.
    %   TF)rangelenr   )r   isub r    U/var/www/html/olx_land/venv/lib/python3.10/site-packages/pymongo/uri_parser_shared.py_unquoted_percent:   s   r"   userinfotuple[str, str]c                 C  sR   d| v s|  ddkst| rtd| d\}}}|s!tdt|t|fS )aZ  Validates the format of user information in a MongoDB URI.
    Reserved characters that are gen-delimiters (":", "/", "?", "#", "[",
    "]", "@") as per RFC 3986 must be escaped.

    Returns a 2-tuple containing the unescaped username followed
    by the unescaped password.

    :param userinfo: A string of the form <username>:<password>
    @:   zXUsername and password must be escaped according to RFC 3986, use urllib.parse.quote_plusz&The empty string is not valid username)countr"   r   	partitionr   )r#   user_passwdr    r    r!   parse_userinfoJ   s   
r-   entitydefault_portOptional[int]%tuple[str, Optional[Union[str, int]]]c                 C  sT   |  ddkrtd|  d}|dkr| dd |fS | d| | |d d fS )a  Validates an IPv6 literal host:port string.

    Returns a 2-tuple of IPv6 literal followed by port where
    port is default_port if it wasn't specified in entity.

    :param entity: A string that represents an IPv6 literal enclosed
                    in braces (e.g. '[::1]' or '[::1]:27017').
    :param default_port: The port number to use when one wasn't
                          specified in entity.
    ]zNan IPv6 address literal must be enclosed in '[' and ']' according to RFC 2732.z]:r'      N)find
ValueError)r.   r/   r   r    r    r!   parse_ipv6_literal_hostb   s   
r7   r   c                 C  s   | }|}| d dkrt | |\}}n#| dr| |fS | ddkr5| ddkr-td|dd\}}t|tro| s[t	dd	 |D rW|D ]}|
 rVtd
|qItdt|dksgt|dkrktdt|}| |fS )aq  Validates a host string

    Returns a 2-tuple of host followed by port where port is default_port
    if it wasn't specified in the string.

    :param entity: A host or host:port string where host could be a
                    hostname or IP address.
    :param default_port: The port number to use when one wasn't
                          specified in entity.
    r   [.sockr&   r3   r'   zReserved characters such as ':' must be escaped according RFC 2396. An IPv6 address literal must be enclosed in '[' and ']' according to RFC 2732.c                 s  s     | ]}|  p| V  qd S )N)isspaceisdigit).0cr    r    r!   	<genexpr>   s    zparse_host.<locals>.<genexpr>z$Port contains whitespace character: zPort contains non-digit characters. Hint: username and password must be escaped according to RFC 3986, use urllib.parse.quote_plusi  z+Port must be an integer between 0 and 65535)r7   endswithr5   r(   r6   split
isinstancer   r;   allr:   intlower)r.   r/   hostportr=   r    r    r!   
parse_hosty   s4   

rG   >   tlsallowinvalidhostnamestlsallowinvalidcertificatestlsdisableocspendpointcheckoptsdelimOptional[str]r   c                 C  s   t  }| |D ]9}|d\}}| dkr!||g | q||v r0tjd| ddd | dkr9|}nt|}|||< q|S )zHelper method for split_options which creates the options dict.
    Also handles the creation of a list for the URI tag_sets/
    readpreferencetags portion, and the use of a unicode options string.
    =readpreferencetagszDuplicate URI option 'z'.r4   
stacklevelauthmechanismproperties)r   r@   rD   
setdefaultappendwarningswarnr   )rK   rL   optionsurioptkeyvaluevalr    r    r!   _parse_options   s   
r\   rW   c                 C  s  |  d}|dur"tD ]}|| v r!d}t|| d| |f q|  d}|durDd| v r<d}t|d| df |du rDd| d< |  d}|durbdD ]}|  |du rad	}t||f qOd
| v rd| v rddd}||  d
||  dkrd}t|| d
| df | S )zRaise appropriate errors when conflicting TLS options are present in
    the options dictionary.

    :param options: Instance of _CaseInsensitiveDictionary containing
          MongoDB URI options.
    tlsinsecureNz9URI options %s and %s cannot be specified simultaneously.rI   rJ   T
tlscrlfile)r]   rI   rJ   zDURI option %s=True cannot be specified when CRL checking is enabled.ssltlsr[   r   r   c                 S  s"   | dv r| dkS t | tr| S | S )N)truefalsera   )rA   r   )r[   r    r    r!   truth_value   s
   
z-_handle_security_options.<locals>.truth_valuez=Can not specify conflicting values for URI options %s and %s.)r[   r   r   r   )get_IMPLICIT_TLSINSECURE_OPTSr   	cased_key)rW   r]   opterr_msgtlsallowinvalidcertsr^   rc   r    r    r!   _handle_security_options   sB   



rj   c                 C  s   t | D ]W}|tv r[t| \}}|dkrF|}|| v r4d}tj|| || |f tdd | | qd}tj|| ||f tdd q|dkr[d}tj|| ||f tdd q| S )a;  Issue appropriate warnings when deprecated options are present in the
    options dictionary. Removes deprecated option key, value pairs if the
    options dictionary is found to also have the renamed option.

    :param options: Instance of _CaseInsensitiveDictionary containing
          MongoDB URI options.
    renamedz0Deprecated option '%s' ignored in favor of '%s'.r4   rP   z,Option '%s' is deprecated, use '%s' instead.removedzOption '%s' is deprecated. %s.)listr   rU   rV   rf   DeprecationWarningpop)rW   optnamemodemessage
newoptnamewarn_msgr    r    r!   _handle_option_deprecations   s:   
ru   c                 C  sX   |  d}|durtD ]}|| |< qt| D ]}t |d}|dur)| || |< q| S )zNormalizes option names in the options dictionary by converting them to
    their internally-used names.

    :param options: Instance of _CaseInsensitiveDictionary containing
          MongoDB URI options.
    r]   N)rd   re   rm   r   ro   )rW   r]   rg   rp   intnamer    r    r!   _normalize_options&  s   

rw   FMapping[str, Any]rV   MutableMapping[str, Any]c                 C  s
   t | |S )a  Validates and normalizes options passed in a MongoDB URI.

    Returns a new dictionary of validated and normalized options. If warn is
    False then errors will be thrown for invalid options, otherwise they will
    be ignored and a warning will be issued.

    :param opts: A dict of MongoDB URI options.
    :param warn: If ``True`` then warnings will be logged and
          invalid options will be ignored. Otherwise invalid options will
          cause errors.
    )r   )rK   rV   r    r    r!   validate_options<  s   
rz   Tvalidate	normalizec                 C  s   |  d}|  d}z1|dkr|dkrtd|dkr!t| d}n|dkr+t| d}n|  ddkr8t| d}ntW n tyG   tddw t|}t|}|rVt|}|rkttt	||}|
d	d
krktd|S )a  Takes the options portion of a MongoDB URI, validates each option
    and returns the options in a dictionary.

    :param opt: A string representing MongoDB URI options.
    :param validate: If ``True`` (the default), validate and normalize all
          options.
    :param warn: If ``False`` (the default), suppress all warnings raised
          during validation of options.
    :param normalize: If ``True`` (the default), renames all options to their
          internally-used names.
    &;r   z-Can not mix '&' and ';' for option separatorsrN   r3   Nz'MongoDB URI options are key=value pairs
authsource z1the authSource database cannot be an empty string)r5   r   r\   r6   rj   ru   rw   r
   r   rz   rd   )rK   r{   rV   r|   and_idxsemi_idxrW   r    r    r!   split_optionsK  s2   


r   hostslist[_Address]c                 C  sF   g }|  dD ]}|std|}|drd}|t|| q|S )a  Takes a string of the form host1[:port],host2[:port]... and
    splits it into (host, port) tuples. If [:port] isn't present the
    default_port is used.

    Returns a set of 2-tuples containing the host name (or IP) followed by
    port number.

    :param hosts: A string of the form host1[:port],host2[:port],...
    :param default_port: The port number to use when one wasn't specified
          for a host.
    ,z(Empty host (or extra comma in host list)r9   N)r@   r   r?   rT   rG   )r   r/   nodesr.   rF   r    r    r!   split_hostsx  s   
r   r8   z/ "$r2   )r   
authSource
replicaset
replicaSetloadbalancedloadBalancedr   r   Nonec                 C  sh   t | dkr|drtd|dr0t | dkrtd|dr'td|dr2tdd S d S )	Nr'   directconnectionz8Cannot specify multiple hosts with directConnection=truer   z4Cannot specify multiple hosts with loadBalanced=truez;Cannot specify directConnection=true with loadBalanced=truer   z0Cannot specify replicaSet with loadBalanced=true)r   rd   r   )r   rW   r    r    r!   _check_options  s   


r   kms_tls_optionsOptional[Mapping[str, Any]]is_syncdict[str, SSLContext]c           	      C  s   | si S t | tstdi }|  D ]S\}}t |ts$td| d|dd t|}t|}t|}ttt	|}t
||\}}|du rLtd|rRtdd	D ]}||v ratd
| |||< qTq|S )z!Parse KMS TLS connection options.zkms_tls_options must be a dictzkms_tls_options["z"] must be a dictr`   TNz!TLS is required for KMS providerszInsecure TLS options prohibited)tlsInsecuretlsAllowInvalidCertificatestlsAllowInvalidHostnames$tlsDisableCertificateRevocationCheckz!Insecure TLS options prohibited: )rA   dict	TypeErroritemsrS   r   rj   rw   r
   rz   r   r   )	r   r   contextsproviderrW   rK   ssl_contextallow_invalid_hostnamesnr    r    r!   _parse_kms_tls_options  s0   


	r   urisrv_max_hostsdict[str, Any]c                 C  s&  |  trd}| td  }n'|  tr*t s!tjpd}td| d}| td  }nt	dt dt d|s;t	dd }	d }
d }d }t
 }|d	\}}}d
|v r[|d
\}}}n|}|r{t|}d|v ro|dd\}}t|rzt	d| nd }|r|t|||| d|v r|d\}}}t|\}	}
n|}d
|v rt	d| t|}d }|p|d}|r|drtdt dt|d d}t|dkrt	t d|d \}}|d urt	t dn|s|dd urtd|s|rtdt||d}t|| ||	|
||||dS )NFpythonzThe "dnspython" module must be installed to use mongodb+srv:// URIs. To fix this error install pymongo again:
 %s -m pip install pymongo>=4.3Tz)Invalid URI scheme: URI must begin with 'z' or ''z(Must provide at least one hostname or IP?/.r'   zBad database name "%s"r%   z;Any '/' in a unix domain socket must be percent-encoded: %ssrvMaxHostsdirectConnectionz*Cannot specify directConnection=true with z URIs)r/   z. URIs must include one, and only one, hostnamer   z$ URIs must not include a port numbersrvServiceNamezDThe srvServiceName option is only allowed with 'mongodb+srv://' URIszAThe srvMaxHosts option is only allowed with 'mongodb+srv://' URIs)nodelistusernamepassworddatabase
collectionrW   fqdn)
startswithSCHEME
SCHEME_LEN
SRV_SCHEMEr   sys
executabler   SRV_SCHEME_LENr   r   r)   r   r@   _BAD_DB_CHARSsearchupdater   
rpartitionr-   rd   r   r   r   )r   r/   r{   rV   r|   r   is_srvscheme_freepython_pathr*   r,   dbaser   rW   host_plus_db_partr+   rK   	host_partr#   r   r   r   rF   r    r    r!   _validate_uri  s   





r   )r   r   r   r   )r#   r   r   r$   )r.   r   r/   r0   r   r1   )r.   r   r/   r0   r   r   )rK   r   rL   rM   r   r   )rW   r   r   r   )F)rK   rx   rV   r   r   ry   )TFT)
rK   r   r{   r   rV   r   r|   r   r   ry   )r   r   r/   r0   r   r   )r   r   rW   rx   r   r   )r   r   r   r   r   r   )r   r   r/   r0   r{   r   rV   r   r|   r   r   r0   r   r   );__doc__
__future__r   rer   rU   typingr   r   r   r   r   r   r	   r
   urllib.parser   !pymongo.asynchronous.srv_resolverr   pymongo.client_optionsr   pymongo.commonr   r   r   r   pymongo.errorsr   r   pymongo.typingsr   pymongo.pyopenssl_contextr   r   r   r   r   r   DEFAULT_PORTr"   r-   r7   rG   re   r\   rj   ru   rw   rz   r   r   compileescaper   	frozenset_ALLOWED_TXT_OPTSr   r   r   r    r    r    r!   <module>   sX   (



4


5
'-

&