o
    sDiV                     @  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&e'g dZ(dVddZ)dWddZ*dXddZ+e&fdYd!d"Z,h d#Z-dZd(d)Z.d[d+d,Z/d[d-d.Z0d[d/d0Z1d\d]d5d6Z2	7d^d_d:d;Z3e&fd`d>d?Z4e5d@e6dA dB Z7e'g dCZ8dadGdHZ9dbdMdNZ:e&d7d1d7dfdcdRdSZ;dddTdUZ<dS )ezTools 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  ).appnameauthMechanismauthMechanismProperties
authSourcecompressorsconnectTimeoutMSdirectConnectionheartbeatFrequencyMSjournalloadBalancedlocalThresholdMSmaxIdleTimeMSmaxPoolSizemaxConnectingmaxStalenessSecondsminPoolSize	proxyHost	proxyPortproxyUsernameproxyPasswordreadConcernLevelreadPreferencereadPreferenceTags
replicaSet
retryReadsretryWritesserverMonitoringModeserverSelectionTimeoutMSserverSelectionTryOncesocketTimeoutMSsrvMaxHostssrvServiceNamessltlstlsAllowInvalidCertificatestlsAllowInvalidHostnames	tlsCAFiletlsCertificateKeyFiletlsCertificateKeyFilePassword$tlsDisableCertificateRevocationChecktlsDisableOCSPEndpointChecktlsInsecurewwaitQueueTimeoutMS
wTimeoutMSzlibCompressionLevel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   )rD   isub rN   W/home/alumno/antzosa8961/venv/lib/python3.10/site-packages/pymongo/uri_parser_shared.py_unquoted_percentm   s   rP   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)countrP   r   	partitionr   )rQ   user_passwdrN   rN   rO   parse_userinfo}   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]:rU      N)find
ValueError)r\   r]   rL   rN   rN   rO   parse_ipv6_literal_host   s   
re   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   [.sockrT   ra   rU   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crN   rN   rO   	<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)re   endswithrc   rV   rd   split
isinstancerE   rj   allri   intlower)r\   r]   hostportrl   rN   rN   rO   
parse_host   s4   

rv   >   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'.rb   
stacklevelauthmechanismproperties)r   ro   rs   
setdefaultappendwarningswarnr   )rz   r{   optionsurioptkeyvaluevalrN   rN   rO   _parse_options   s   
r   r   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.rx   ry   T
tlscrlfile)r   rx   ry   zDURI option %s=True cannot be specified when CRL checking is enabled.r6   r7   r   r   rF   c                 S  s"   | dv r| dkS t | tr| S | S )N)truefalser   )rp   rG   )r   rN   rN   rO   truth_value$  s
   
z-_handle_security_options.<locals>.truth_valuez=Can not specify conflicting values for URI options %s and %s.)r   r   rF   r   )get_IMPLICIT_TLSINSECURE_OPTSr   	cased_key)r   r   opterr_msgtlsallowinvalidcertsr   r   rN   rN   rO   _handle_security_options   sB   



r   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'.rb   r   z,Option '%s' is deprecated, use '%s' instead.removedzOption '%s' is deprecated. %s.)listr   r   r   r   DeprecationWarningpop)r   optnamemodemessage
newoptnamewarn_msgrN   rN   rO   _handle_option_deprecations2  s:   
r   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)r   r   r   r   r   )r   r   r   r   intnamerN   rN   rO   _normalize_optionsY  s   

r   FMapping[str, Any]r   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   )rz   r   rN   rN   rO   validate_optionso  s   
r   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 separatorsr}   ra   Nz'MongoDB URI options are key=value pairs
authsource z1the authSource database cannot be an empty string)rc   r   r   rd   r   r   r   r
   r   r   r   )rz   r   r   r   and_idxsemi_idxr   rN   rN   rO   split_options~  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)rg   N)ro   r   rn   r   rv   )r   r]   nodesr\   ru   rN   rN   rO   split_hosts  s   
r   rf   z/ "$r`   )r   r   
replicasetr-   loadbalancedr   r   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 )	NrU   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)rK   r   r   )r   r   rN   rN   rO   _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 dictr7   TNz!TLS is required for KMS providerszInsecure TLS options prohibited)r?   r8   r9   r=   z!Insecure TLS options prohibited: )rp   dict	TypeErroritemsr   r   r   r   r
   r   r   r   )	r   r   contextsproviderr   rz   ssl_contextallow_invalid_hostnamesnrN   rN   rO   _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?/.rU   zBad database name "%s"rS   z;Any '/' in a unix domain socket must be percent-encoded: %sr4   r   z*Cannot specify directConnection=true with z URIs)r]   z. URIs must include one, and only one, hostnamer   z$ URIs must not include a port numberr5   zDThe srvServiceName option is only allowed with 'mongodb+srv://' URIszAThe srvMaxHosts option is only allowed with 'mongodb+srv://' URIs)nodelistusernamepassworddatabase
collectionr   fqdn)
startswithSCHEME
SCHEME_LEN
SRV_SCHEMEr   sys
executabler   SRV_SCHEME_LENr   r   rW   r   ro   _BAD_DB_CHARSsearchupdater   
rpartitionr[   r   r   rK   r   )r   r]   r   r   r   r   is_srvscheme_freepython_pathrX   rZ   dbaser   r   host_plus_db_partrY   rz   	host_partrQ   r   r   r   ru   rN   rN   rO   _validate_uri  s   





r   c                 C  sN   i }t D ]}| | v r| | ||< | | q|  D ]\}}|||< q|S rh   )URI_OPTIONSrs   r   r   )r   case_sensitiveoptionkvrN   rN   rO   _make_options_case_sensitive^  s   

r   )rD   rE   rF   rG   )rQ   rE   rF   rR   )r\   rE   r]   r^   rF   r_   )r\   rE   r]   r^   rF   r   )rz   rE   r{   r|   rF   r   )r   r   rF   r   )F)rz   r   r   rG   rF   r   )TFT)
rz   rE   r   rG   r   rG   r   rG   rF   r   )r   rE   r]   r^   rF   r   )r   r   r   r   rF   r   )r   r   r   rG   rF   r   )r   rE   r]   r^   r   rG   r   rG   r   rG   r   r^   rF   r   )r   r   rF   r   )=__doc__
__future__r   rer   r   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   rK   r   r   r   DEFAULT_PORT	frozensetr   rP   r[   re   rv   r   r   r   r   r   r   r   r   compileescaper   _ALLOWED_TXT_OPTSr   r   r   r   rN   rN   rN   rO   <module>   s`   (

4

4


5
'-

&`