
    hV                    >   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(d&dZ)d'dZ*	 	 	 	 	 	 d(dZ+e&fd)dZ,h dZ-d*dZ.d+dZ/d+dZ0d+dZ1d,d-dZ2	 d.	 	 	 	 	 	 	 	 	 d/dZ3e&fd0dZ4 ejj                  d ejl                  d      z   d z         Z7 e'g d!      Z8d1d"Z9	 	 	 	 	 	 d2d#Z:e&ddddf	 	 	 	 	 	 	 	 	 	 	 	 	 d3d$Z;d4d%Z<y)5zTools 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zlibCompressionLevelc                x    t        t        |             D ]#  }| |   dk(  s| ||dz    }t        |      |k(  s# y y)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   )sisubs      X/opt/lhia/marcimex/python/venv/lib/python3.12/site-packages/pymongo/uri_parser_shared.py_unquoted_percentrN   m   sL     3q6] Q43;AA,C C C'     c                    d| v s| j                  d      dkD  st        |       rt        d      | j                  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)countrN   r   	partitionr   )userinfouser_passwds       rM   parse_userinforZ   }   sq     h(..-15Fx5P4
 	

 ((-OD!VABB|F333rO   c                    | j                  d      dk(  rt        d      | j                  d      }|dk(  r| dd |fS | d| | |dz   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]:rS      N)find
ValueError)entitydefault_portrK   s      rM   parse_ipv6_literal_hostrc      sh     {{32\
 	
 	DABwa|\))!A;q1uw''rO   c                @   | }|}| d   dk(  rt        | |      \  }}n]| j                  d      r| |fS | j                  d      dk7  r4| j                  d      dkD  rt	        d      |j                  dd      \  }}t        |t              r|j                         sBt        d |D              r%|D ]   }|j                         st	        d	|       t	        d
      t        |      dkD  st        |      dk  rt	        d      t        |      }|j                         |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   [.sockrR   r]   rS   zReserved characters such as ':' must be escaped according RFC 2396. An IPv6 address literal must be enclosed in '[' and ']' according to RFC 2732.c              3  `   K   | ]&  }|j                         xs |j                          ( y wN)isspaceisdigit).0cs     rM   	<genexpr>zparse_host.<locals>.<genexpr>   s$     <!199;-!))+-<s   ,.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)rc   endswithr_   rT   r`   split
isinstancestrrj   allri   intlower)ra   rb   hostportrl   s        rM   
parse_hostrw      s.    D&2DayC,V\B
d		!|##	S	R	<<q 1  ZZQ'
d$||~<t<< WAyy{(+OPQu)UVVW 8  t9uD	QJKK4y ::<rO   >   tlsallowinvalidhostnamestlsallowinvalidcertificatestlsdisableocspendpointcheckc                b   t               }| j                  |      D ]  }|j                  d      \  }}|j                         dk(  r"|j                  |g       j	                  |       L||v rt        j                  d| dd       |j                         dk(  r|}nt        |      }|||<    |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'.r^   
stacklevelauthmechanismproperties)r   ro   rt   
setdefaultappendwarningswarnr   )optsdelimoptionsurioptkeyvaluevals          rM   _parse_optionsr      s    
 )*G**U# \\#&
U99;..sB'..u5g~ 6se2>1Myy{77"5)GCL NrO   c                ~   | j                  d      }|?t        D ]6  }|| v sd}t        || j                  d      | j                  |      fz         | j                  d      }|.d| v r!d}t        |d| j                  d      fz        |du rd| d<   | j                  d      }|+dD ]&  }| j                  |      du sd}t        ||fz         d	| v rgd
| v rcdd} || j                  d	             || j                  d
            k7  r0d}t        || j                  d	      | j                  d
      fz        | S )zRaise appropriate errors when conflicting TLS options are present in
    the options dictionary.

    :param options: Instance of _CaseInsensitiveDictionary containing
          MongoDB URI options.
    tlsinsecurez9URI options %s and %s cannot be specified simultaneously.ry   rz   T
tlscrlfile)r   ry   rz   zDURI option %s=True cannot be specified when CRL checking is enabled.r7   r8   c                <    | dv r| dk(  S t        | t              r| S | S )N)truefalser   )rp   bool)r   s    rM   truth_valuez-_handle_security_options.<locals>.truth_value$  s)    ''f}$#t$
JrO   z=Can not specify conflicting values for URI options %s and %s.)r   r   returnr   )get_IMPLICIT_TLSINSECURE_OPTSr   	cased_key)r   r   opterr_msgtlsallowinvalidcertsr   r   s          rM   _handle_security_optionsr      s    ++m,K- 	Cg~U w00?ARARSVAWXX 	 #;;'DE'(G3QG0'2C2CDa2bcd   4'59G12 \*J` 	3C{{34'` C6!122	3
 EW,	 w{{5)*k'++e:L.MMUGW(9(9%(@'BSBSTYBZ'[[\\NrO   c                   t        |       D ]  }|t        v st        |   \  }}|dk(  r|}|| v rSd}t        j                  || j	                  |      | j	                  |      fz  t
        d       | j                  |       vd}t        j                  || j	                  |      |fz  t
        d       |dk(  sd}t        j                  || j	                  |      |fz  t
        d        | 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'.r^   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_msgs         rM   _handle_option_deprecationsr   2  s     = 117@MD'y $
(QHMM G$5$5g$>@Q@QR\@]#^^*#$
 KK(I 1 1' :JGG& 
 "; 1 1' :GDD& -8 NrO   c                    | j                  d      }|t        D ]  }|| |<   	 t        |       D ]/  }t        j                   |d      }|| j	                  |      | |<   1 | 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   intnames        rM   _normalize_optionsr   Y  sw     ++m,K- 	'C&GCL	' = 4.227DA&{{73GG4
 NrO   Fc                    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   )r   r   s     rM   validate_optionsr   o  s     !t,,rO   Tc                   | j                  d      }| j                  d      }	 |dk\  r|dk\  rt        d      |dk\  rt        | d      }n9|dk\  rt        | d      }n'| j                  d      dk7  rt        | d      }nt        t	        |      }t        |      }|rt        |      }|r9t        t        t        ||            }|j                  d	      d
k(  rt        d      |S # t        $ r t        d      dw xY w)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|   r]   Nz'MongoDB URI options are key=value pairs
authsource z1the authSource database cannot be an empty string)r_   r   r   r`   r   r   r   r   r   r   r   )r   validater   	normalizeand_idxsemi_idxr   s          rM   split_optionsr   ~  s    iinGyy~HNa<HMLMM\$T3/G]$T3/GYYs^r!$T40G 'w/G)'2G$W-13CGT3RS;;|$*PQQN  NBCMNs   A C$ $C:c                    g }| j                  d      D ]?  }|st        d      |}|j                  d      rd}|j                  t	        ||             A |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)rf   N)ro   r   rn   r   rw   )hostsrb   nodesra   rv   s        rM   split_hostsr     s`     E++c" /$%OPP??7#DZ-./ LrO   re   z/ "$r\   )r   r   
replicasetr.   loadbalancedr    c                   t        |       dkD  r|j                  d      rt        d      |j                  d      rRt        |       dkD  rt        d      |j                  d      rt        d      |j                  d      rt        d      y y )	NrS   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)rI   r   r   )r   r   s     rM   _check_optionsr     s    
5zA~'++&89 ![\\{{>"u:>$%[\\;;)*$%bcc;;|$$%WXX % #rO   c                   | si S t        | t              st        d      i }| j                         D ]  \  }}t        |t              st        d| d      |j	                  dd       t        |      }t        |      }t        |      }t        t
        t        |            }t        ||      \  }}|t        d      |rt        d      dD ]  }||v rt        d	|       |||<     |S )
z!Parse KMS TLS connection options.zkms_tls_options must be a dictzkms_tls_options["z"] must be a dictr8   Tz!TLS is required for KMS providerszInsecure TLS options prohibited)r@   r9   r:   r>   z!Insecure TLS options prohibited: )rp   dict	TypeErroritemsr   r   r   r   r   r   r   r   )	kms_tls_optionsis_synccontextsproviderr   r   ssl_contextallow_invalid_hostnamesns	            rM   _parse_kms_tls_optionsr     s   
 	ot,899H,224 -''4(/z9JKLL5$')'2'-!$'.0@0FG/A$/P,,$%HII"$%FGG
 	-A Dy(+LQC)PQQ!,HX	--. OrO   c                   | j                  t              rd}| t        d  }ng| j                  t              r8t	               s"t
        j                  xs d}t        d|z        d}| t        d  }nt        dt         dt         d      |st        d      d }	d }
d }d }t               }|j                  d	      \  }}}d
|v r|j                  d
      \  }}}n|}|rGt        |      }d|v r|j                  dd      \  }}t        j                  |      rt        d|z        d }|r|j!                  t#        ||||             d|v r$|j%                  d      \  }}}t'        |      \  }	}
n|}d
|v rt        d|z        t        |      }d }|xs |j)                  d      }|rm|j)                  d      rt        dt         d      t+        |d       }t-        |      dk7  rt        t         d      |d   \  }}|Lt        t         d      |s|j)                  d      t        d      |s|rt        d      t+        ||      }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?/.rS   zBad database name "%s"rQ   z;Any '/' in a unix domain socket must be percent-encoded: %sr5   r   z*Cannot specify directConnection=true with z URIs)rb   z. URIs must include one, and only one, hostnamer   z$ URIs must not include a port numberr6   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   rU   r   ro   _BAD_DB_CHARSsearchupdater   
rpartitionrZ   r   r   rI   r   )urirb   r   r   r   srv_max_hostsis_srvscheme_freepython_pathrW   rY   dbaser   r   host_plus_db_partrX   r   	host_partrV   r   r   r   rv   s                          rM   _validate_urir     s    ~~f*+&	
	# ..4HK$1 5@A  ./*DVHFS]R^^_`aaCDDDFEJ(*G!,!6!6s!;q$
/99#>	1e%	U#%< %C 3E:&5=>>}T8T9EF
i&11#6!U%h/f
e|VYbbccED!?W[[%?M;;)*$'QR\Q]]b%cddE5u:?
|+YZ[[1X
d
|+OPQQ$45A R
 	
  O
 	
 E=5'"   rO   c                    i }t         D ].  }|j                         | v s| |   ||<   | j                  |       0 | j                         D ]
  \  }}|||<    |S rh   )URI_OPTIONSrt   r   r   )r   case_sensitiveoptionkvs        rM   _make_options_case_sensitiver   ^  si    N  <<>W$%,V_N6"KK   1qrO   )rJ   rq   r   r   )rV   rq   r   ztuple[str, str])ra   rq   rb   Optional[int]r   z%tuple[str, Optional[Union[str, int]]])ra   rq   rb   r   r   r   )r   rq   r   zOptional[str]r   r   )r   r   r   r   )F)r   Mapping[str, Any]r   r   r   MutableMapping[str, Any])TFT)
r   rq   r   r   r   r   r   r   r   r   )r   rq   rb   r   r   zlist[_Address])r   r	   r   r   r   None)r   zOptional[Mapping[str, Any]]r   r   r   zdict[str, SSLContext])r   rq   rb   r   r   r   r   r   r   r   r   r   r   dict[str, Any])r   r   r   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   rI   r   r   r   DEFAULT_PORT	frozensetr   rN   rZ   rc   rw   r   r   r   r   r   r   r   r   compileescaper   _ALLOWED_TXT_OPTSr   r   r   r    rO   rM   <module>r     s    # 	 
 	 	 	 & = 5  : $4	[

Z/1h 40((,(*(. ;G 0h ,2j$N,-  MQ*
**,0*EI**Z ;G 4 

37!33c9:\ 
Y!0!! !L #/#']	]] ] 	]
 ] !] ]@rO   