
    Vh-                       d Z ddlmZ ddlZddlZddlZddlZddlZddl	Zddl
ZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddl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!Z!dZ"dZ#e!jH                  Z$dd
l(m)Z) ddl*m+Z+m,Z, ddl-m.Z.m/Z/m0Z0 	 ddl1Z1dZ2dZ4	 ddl5m6Z6 ddl7m8Z8 ddl9m:Z: ddl;m<Z< 	 ddl=Z=dZ>dZ?	 ddl@Z@ G d de       ZA ej                  dej                  ej                  z        ZE G d de3      ZF G d deF      ZG G d deF      ZH G d deH      ZI G d de3      ZJdZKdZLe2rFed        ZM G d  d!ej                  j                        ZL G d" d#ej                  j                        ZK G d$ d%ej                  j                        ZS G d& d'ej                  j                        ZU G d( d)eV      ZWd* ZXd+ ZYd, ZZd- Z[ G d. d/e$      Z\ G d0 d1ej                  j                        Z]	 	 dCd2Z^dDd3Z_dEd4Z`d5 ZadFd6Zbd7 Zc G d8 d9      Zd	 	 	 	 	 	 	 dGd:Zed; Zfd< Zgd= Zh	 	 	 	 dHd>Zid? ZjdId@Zk	 	 	 dJdAZldB Zmy# e%$ r d	Z" ejL                         Z#e'Z$Y w xY w# e3$ r d	Z2Y w xY w# e%$ r d	Z4Y w xY w# e%$ r d	Z>Y w xY w# e%$ r  ejL                         Z?dZAY w xY w)Ka  
The **urls** utils module offers a replacement for the urllib python library.

urllib is the python stdlib way to retrieve files from the Internet but it
lacks some security features (around verifying SSL certificates) that users
should care about in most situations. Using the functions in this module corrects
deficiencies in the urllib module wherever possible.

There are also third-party libraries (for instance, requests) which can be used
to replace urllib with a more secure library. However, all third party libraries
require that the library be installed on the managed machine. That is an extra step
for users making use of a module. If possible, avoid third party libraries by using
this code instead.
    )annotationsN)contextmanager)	cookiejar)unquoteurlparse
urlunparse)BaseHandlerTFmissing_required_lib)Mappingis_sequence)to_bytes	to_nativeto_text)x509)default_backend)hashes)UnsupportedAlgorithmc                  b    e Zd ZdZ ej
                  dej                        ZdZddZ	d Z
d Zy)	HTTPGSSAPIAuthHandlerz@ Handles Negotiate/Kerberos support through the gssapi library. z)(?:.*)\s*(Negotiate|Kerberos)\s*([^,]*),?i  Nc                .    || _         || _        d | _        y N)usernamepassword_context)selfr   r   s      I/home/dcms/DCMS/lib/python3.12/site-packages/ansible/module_utils/urls.py__init__zHTTPGSSAPIAuthHandler.__init__g   s    $DM$DM DM    c                    | j                   j                  |j                  dd            }|r5|j                  d      t	        j
                  |j                  d            fS y )Nzwww-authenticate       )AUTH_HEADER_PATTERNsearchgetgroupbase64	b64decode)r   headers
auth_matchs      r   get_auth_valuez$HTTPGSSAPIAuthHandler.get_auth_valuel   sY    1188EWY[9\]J!''*F,<,<Z=M=Ma=P,QQQ r   c                   | j                   ry t        |j                               }| j                  |      }|sy |\  }}	d }
| j                  r9t        j                  | j                  t
        j                  j                        }
|
ru| j                  rit        t
        j                  d      st        d      t        | j                  d      }t
        j                  j                  |
|d      j                  }nt        j                   |
d      }d }t#        |d	      }|rGt%        j&                         d
k7  r0t)        |      }|r#t
        j                  j+                  d|z         }t        j                  d|j,                  z  t
        j                  j.                        }t        j0                  d|||      | _         d }| j                   j2                  s| j                   j5                  |	      }|s	 |S |dt7        t9        j:                  |            }|j=                  d|       | j>                  jA                  |      }| j                  |jB                        }|s	 |S |d   }	| j                   j2                  s|S )N)	name_typeacquire_cred_with_passwordzPlatform GSSAPI library does not support gss_acquire_cred_with_password, cannot acquire GSSAPI credential with explicit username and password.surrogate_or_stricterrorsinitiate)usage)namer4   TDarwins   tls-server-end-point:)application_datazHTTP@%s)r4   r5   credschannel_bindings Authorizationr"   )"r   r   get_full_urlr,   r   gssapiNameNameTypeuserr   hasattrrawNotImplementedErrorr   r/   r8   Credentialsgetpeercertplatformsystemget_channel_binding_cert_hashChannelBindingshostnamehostbased_serviceSecurityContextcompletestepr   r(   	b64encodeadd_unredirected_headerparentopenr*   )r   reqfpcodemsgr*   parsedauth_headerauth_protocolin_tokenr   
b_passwordcredcbtcert	cert_hashtargetresp	out_tokens                      r   http_error_401z$HTTPGSSAPIAuthHandler.http_error_401q   s%   }}c..01F--g6K&1#M8H}}!;;t}}@T@TUDMMvzz+GH- /P Q Q &dmm<QR
zz<<XzYc<djj ))xzJ Cr4(D)X59$?	 **44F^ajFj4kC [[V__!<foo>_>_`F"22&X\orsDMDmm,, MM..x8	  K *7	&BRBRS\B]8^_++O[I{{'', #11$,,?" K 'q> mm,, Kr   NN)__name__
__module____qualname____doc__recompileIr$   handler_orderr   r,   rc    r   r   r   r   a   s5    N(bjj)UWYW[W[\	!
	R
9	r   r   z;^-----BEGIN CERTIFICATE-----\n.+?-----END CERTIFICATE-----$)flagsc                      e Zd ZdZy)ConnectionErrorzFailed to connect to the serverNre   rf   rg   rh   rm   r   r   rp   rp      s    )r   rp   c                      e Zd ZdZy)
ProxyErrorz%Failure to connect because of a proxyNrq   rm   r   r   rs   rs      s    /r   rs   c                      e Zd ZdZy)SSLValidationErrorzoFailure to connect due to SSL validation failing

    No longer used, but kept for backwards compatibility
    Nrq   rm   r   r   ru   ru           	r   ru   c                      e Zd ZdZy)
NoSSLErrorzNeeded to connect to an HTTPS url but no ssl library available to verify the certificate

    No longer used, but kept for backwards compatibility
    Nrq   rm   r   r   rx   rx      rv   r   rx   c                  $     e Zd ZdZd fd	Z xZS )MissingModuleErrorz8Failed to import 3rd party module required by the callerc                @    t         |   |       || _        || _        y r   )superr   import_tracebackmodule)r   messager}   r~   	__class__s       r   r   zMissingModuleError.__init__   s    ! 0r   r   )re   rf   rg   rh   r   __classcell__r   s   @r   rz   rz      s    B r   rz   c               #     K   t         j                  j                  j                  } t        j                  t         j                  j                  _        d | t         j                  j                  _        yw)zMonkey patch ``http.client.HTTPConnection.connect`` to be ``UnixHTTPConnection.connect``
        so that when calling ``super(UnixHTTPSConnection, self).connect()`` we get the
        correct behavior of creating self.sock for the unix socket
        N)httpclientHTTPConnectionconnectUnixHTTPConnection)_connects    r   (unix_socket_patch_httpconnection_connectr      sJ      ;;--55-?-G-G""*-5""*s   A6A8c                  .     e Zd Zd Z fdZ fdZ xZS )UnixHTTPSConnectionc                    || _         y r   _unix_socketr   unix_sockets     r   r   zUnixHTTPSConnection.__init__   s
     +Dr   c                `    t               5  t        | 	          d d d        y # 1 sw Y   y xY wr   )r   r|   r   )r   r   s    r   r   zUnixHTTPSConnection.connect   s,     :; " !	" " "s   $-c                &    t        |   |i | | S r   r|   r   r   argskwargsr   s      r   __call__zUnixHTTPSConnection.__call__   s    Gd-f-Kr   )re   rf   rg   r   r   r   r   r   s   @r   r   r      s    	,	"	 	r   r   c                  $     e Zd Z fdZd Z xZS )UnixHTTPSHandlerc                2    t        |   di | || _        y Nrm   r|   r   r   r   r   r   r   s      r   r   zUnixHTTPSHandler.__init__   s    G&v& +Dr   c                    i }	 | j                   |d<    | j                  t        | j                        |fd| j
                  i|S # t        $ r Y >w xY w)Ncheck_hostnamecontext)_check_hostnameAttributeErrordo_openr   r   r   )r   rS   r   s      r   
https_openzUnixHTTPSHandler.https_open  so    F+/+?+?'(  4<<#D$5$56  	  " s   A 	AA)re   rf   rg   r   r   r   r   s   @r   r   r      s    	,	r   r   c                  .     e Zd ZdZd Zd Z fdZ xZS )r   z+Handles http requests to a unix socket filec                    || _         y r   r   r   s     r   r   zUnixHTTPConnection.__init__  s
    'r   c                   t        j                   t         j                  t         j                        | _        	 | j                  j	                  | j
                         | j                  t         j                  ur&| j                  j                  | j                         y y # t        $ r }t        d| j
                  d|      d }~ww xY w)NzInvalid Socket File (z): )
socketAF_UNIXSOCK_STREAMsockr   r   OSErrortimeout_GLOBAL_DEFAULT_TIMEOUT
settimeout)r   es     r   r   zUnixHTTPConnection.connect  s    MM&..&2D2DE		SIId//0 <<v===II  . >  	SD<M<MqQRR	Ss   %B! !	C
*CC
c                &    t        |   |i | | S r   r   r   s      r   r   zUnixHTTPConnection.__call__      $)&)r   )re   rf   rg   rh   r   r   r   r   r   s   @r   r   r     s    5(/ r   r   c                  (     e Zd ZdZ fdZd Z xZS )UnixHTTPHandlerzHandler for Unix urlsc                2    t        |   di | || _        y r   r   r   s      r   r   zUnixHTTPHandler.__init__'  s    "6"'r   c                L    | j                  t        | j                        |      S r   )r   r   r   )r   rS   s     r   	http_openzUnixHTTPHandler.http_open+  s    ||.t/@/@A3GGr   )re   rf   rg   rh   r   r   r   r   s   @r   r   r   $  s    (Hr   r   c                  (     e Zd ZdZ fdZd Z xZS )ParseResultDottedDictzO
    A dict that acts similarly to the ParseResult named tuple from urllib
    c                2    t        |   |i | | | _        y r   )r|   r   __dict__r   s      r   r   zParseResultDottedDict.__init__3  s    $)&)r   c                L    dD cg c]  }| j                  |d       c}S c c}w )z]
        Generate a list from this dict, that looks like the ParseResult named tuple
        )schemenetlocpathparamsqueryfragmentN)r&   )r   ks     r   as_listzParseResultDottedDict.as_list7  s$     ,ggaD!gggs   !)re   rf   rg   rh   r   r   r   r   s   @r   r   r   /  s    hr   r   c                    t        | j                               }|j                  | j                  | j                  | j
                  | j                  d       |S )a  
    Returns a dictionary of url parts as parsed by urlparse,
    but accounts for the fact that older versions of that
    library do not support named attributes (ie. .netloc)

    This method isn't of much use any longer, but is kept
    in a minimal state for backwards compat.
    )r   r   rJ   port)r   _asdictupdater   r   rJ   r   )partsresults     r   generic_urlparser   >  sH     #5==?3F
MMNNNNNN

	  Mr   c              #  f   K   t         j                  |       D ]  }|j                  d        y w)Nr   )PEM_CERT_REfinditerr'   )datamatchs     r   extract_pem_certsr   Q  s.     %%d+ kk!ns   /1c                    | j                         }t        |      d   }t        j                  j	                  |j                  d            xs d }|rt        |      }| j                  j                  dd      xs |S )Nr#   /filenamezcontent-dispositionheader)	geturlr   osr   basenamerstripr   r*   	get_param)responseurlr   r   s       r   get_response_filenamer   V  sn    
//
CC=DwwC 019TH8$%%j9N%O[S[[r   c                   | j                   j                  }| j                   j                  } |       xs dj                  d      d   }|j                  d      \  }} |d      xs dj                  d      d   }||||fS )Napplication/octet-stream,r   r   charsetzutf-8)r*   get_content_typer   split)r   get_typer   content_type	main_typesub_typer   s          r   parse_content_typer   `  s    00H  **IJ<"<CCCHKL&,,S1Ix#.w55c:1=GHg55r   c                  8     e Zd ZdZ fdZd Zed        Z xZS )GzipDecodedReaderzA file-like object to decode a response encoded with the gzip
    method, as described in RFC 1952.

    Largely copied from ``xmlrpclib``/``xmlrpc.client``
    c                    t         st        | j                         t              || _        t
        |   d| j                         y )Nr}   rb)modefileobj)HAS_GZIPrz   missing_gzip_errorGZIP_IMP_ERR_ior|   r   )r   rT   r   s     r   r   zGzipDecodedReader.__init__o  s:    $T%<%<%>Q]^^dDHH5r   c                    	 t         j                  j                  |        | j                  j                          y # | j                  j                          w xY wr   )gzipGzipFilecloser   )r   s    r   r   zGzipDecodedReader.closev  s6    	MM%HHNNDHHNNs	   < Ac                     t        dd      S )Nr   zito decompress gzip encoded responses. Set "decompress" to False, to prevent attempting auto decompression)reasonr
   rm   r   r   r   z$GzipDecodedReader.missing_gzip_error|  s    #Y
 	
r   )	re   rf   rg   rh   r   r   staticmethodr   r   r   s   @r   r   r   i  s&    
6 
 
r   r   c                       e Zd ZdZddZ fdZ	 ej                  j                  j                   d Z xZS # e
$ r# ej                  j                  j                  Z	Y .w xY w)HTTPRedirectHandlerzThis is an implementation of a RedirectHandler to match the
    functionality provided by httplib2. It will utilize the value of
    ``follow_redirects`` to determine how redirects should be handled in
    urllib.
    c                    || _         y r   )follow_redirects)r   r   s     r   r   zHTTPRedirectHandler.__init__  s
     0r   c                &    t        |   |i | | S r   r   r   s      r   r   zHTTPRedirectHandler.__call__  r   r   c           	        | j                   }|dv r/t        j                  j                  j	                  | ||||||      S |dv r#t        j
                  j                  |||||      |j                         }|dv r;|dk  s|dk\  rt        j
                  j                  |j                         ||||      |dk(  r?|dk  s	|dk\  s|dvrbt        j
                  j                  |j                         ||||      t        j
                  j                  |j                         ||||      |j                  }	|j                  }
|j                  dd	      }|d
v r|j                  }ned }	|j                  j                         D ci c]  \  }}|j                         dvr|| }}}|dk(  r|dk7  rd}|dk(  r|dk7  rd}|dk(  r|dk(  rd}t        j                  j                  ||	||
d|j!                               S c c}}w )N)urllib2urllib)nononeF)allyesTi,    safe)GETHEADr:   z%20)i3  i4  )zcontent-lengthcontent-typeztransfer-encodingi/  r  r  i.  i-  POSTT)r   r*   origin_req_hostunverifiablemethod)r   r  requestr   redirect_requesterror	HTTPError
get_methodr<   r   r  replacer*   itemslowerRequestupper)r   rS   rT   rU   rV   r*   newurlr   r  r   r  req_headersr   vs                 r   r  z$HTTPRedirectHandler.redirect_request  s   00 44>>55FFtSRTVZ\_ahjpqq !66,,((sGRHH! 33czTS[ll,,S-=-=-?sGUWXX'czTS[F/,Ill,,S-=-=-?sGUWXX,,(()9)9);T3QSTTxx-- U+ :++K D,/KK,=,=,? hDAqggi/ff a4 hK h s{v/ s{v/ s{v/~~%%+<<> & 
 	
!hs   G>r   )re   rf   rg   rh   r   r   r  r  r   http_error_308r   http_error_302r  r   r   s   @r   r   r     sX    1K**99
;
	  K;;JJKs    9 %A! A!r   c                J   |g }t        |      s"t        d|j                  j                  z        t	        j
                  |       }|s?|xj                  t        j                  z  c_        d|_        t        j                  |_
        |r@| s>|s
t               }|j                  t        |      d          |r|j                  |       |r.|j                  dj!                  t#        t$        |                   |r&t'        |d      rd	|_        |j+                  ||
       |S )NzCiphers must be a list. Got %s.)cafileF)capathr   )cadata:post_handshake_authT)keyfile)r   	TypeErrorr   re   sslcreate_default_contextoptionsOP_NO_SSLv3r   	CERT_NONEverify_mode	bytearrayextendget_ca_certsload_verify_locationsset_ciphersjoinmapr   rA   r&  load_cert_chain)r"  r$  r#  ciphersvalidate_certsclient_cert
client_keyr   s           r   make_contextr;    s    w9G<M<M<V<VVWW((7G3??*!&!mm f[Fl&1!45)))8CHHSG%<=> 712*.G'Z@Nr   c                P   i }| ry| g}t        t        | d      dd      5 }t        |j                               D ]  }t	        j
                  |      }d ||<    	 d d d        t               j                  |      |fS t	        j                         }|j                  }|xs |j                  h}|r|j                  |       t        t        j                         d      }	|	dk(  r4|j                  d       |j                  d       |j                  d       n|	d	k(  r|j                  d
       n|	dk(  r|j                  d       nl|	dk(  r|j                  d       nU|	dk(  r|j                  d       n>|	dk(  r#|j                  d       |j                  d       n|	dk(  r|j                  d       |j                  d       |D ]  }
|
r$|
|k(  st        j                   j#                  |
      s*t        j$                  |
      D ]  }t        j                   j                  |
|      }t        j                   j'                  |      sCt        j                   j)                  |      d   dv sh	 t        |dd      5 }|j                         }d d d        	 t              D ]  }t	        j
                  |      }d ||<      t               j                  |      t1        |      fS # 1 sw Y   xY w# 1 sw Y   ixY w# t*        $ r Y w xY w# t,        t.        f$ r Y w xY w)Nr0   r1   rsurrogateescapeLinuxz/etc/pki/ca-trust/extracted/pemz/etc/pki/tls/certsz%/usr/share/ca-certificates/cacert.orgFreeBSDz/usr/local/share/certsOpenBSDz/etc/sslNetBSDz/etc/openssl/certsSunOSz/opt/local/etc/openssl/certsAIXz/var/ssl/certsz/opt/freeware/etc/ssl/certsr6   z/usr/local/etc/opensslz/etc/ansibler"   >   .cer.crt.pem)rR   r   r   readr)  PEM_cert_to_DER_certr/  r4  get_default_verify_pathsr#  r"  addr   rF   rG   r   r   isdirlistdirisfilesplitext	Exceptionr   IOErrorlist)r"  r#  r$  paths_checkedfpemb_derdefault_verify_pathsdefault_capathrG   r   	full_path	cert_filer^   s                 r   r1  r1    s    F (6*?@#N_` 	%de(2 %005 $u%	% {'66779)00N#B';'B'BCM&!X__&/DEF ;<./AB	:	23	:	*%	9	./	8	89	6	*+78	9	23 n%
  t~-RWW]]45HD! 	AT1-Iww~~i(RWW-=-=a-@-CG_-_
i5FG 09(~~/0!#4T#: 1C$'$<$<S$AE,0F5M1		( ;F#T-%888{	% 	%b0 0 % ! !) sS   9K)/L=K6L*L)K36K?;L	LLLLL%$L%c                    | j                   j                  j                  }	  |j                  |      S # t        $ r Y yw xY w)zC Attempt to get the peer certificate of the response from urlopen. N)rT   rB   _sockrE   r   )r   binary_formr   s      r   rE   rE   J  s?    [[__""F!v!!+.. s   4 	A A c                N   t         syt        j                  | t                     }d}	 |j                  }|r|j                  dv rt        j                         }t        j                  |t                     }|j                  |        |j                         S # t
        $ r Y nw xY w)zM Gets the channel binding app data for a TLS connection using the peer cert. N)md5sha1)HAS_CRYPTOGRAPHYr   load_der_x509_certificater   signature_hash_algorithmr   r5   r   SHA256Hashr   finalize)certificate_derr^   hash_algorithmdigests       r   rH   rH   T  s     ))/?;LMDN66
 ^00OC[[):;F
MM/"??   s   B 	B$#B$c           	     `    dg d| d      | d   g d| d   dz
     | d   | d   | d	   | d
   |fz  S )zAccepts a timetuple and optional zone which defaults to ``-0000``
    and returns a date string as specified by RFC 2822, e.g.:

    Fri, 09 Nov 2001 01:08:47 -0000

    Copied from email.utils.formatdate and modified for separate use
    z"%s, %02d %s %04d %02d:%02d:%02d %s)MonTueWedThuFriSatSun   r#   )JanFebMarAprMayJunJulAugSepOctNovDecr"   r            rm   )	timetuplezones     r   rfc2822_date_stringr  k  s\     09)A,G!	33<Q<!3C	E!ilIaL)A,3  r   c                F   i }g }t        |       }|j                  dk(  r| ||fS |}	|}
|	r|j                  }n|d|j                  v rn|j                  j                  dd      \  }}d|v r|j                  dd      \  }	}
n|}	d}
t	        |	      }	t	        |
      }
t        |j                  |            } |rBt        r|j                  t        |	|
             n5t        ddd	
      }t        |t              |	r|st        j                  j                         }|j                  d |	|
       t        j                  j!                  |      }t        j                  j#                  |      }|j                  |       |j                  |       n|	r|rt%        |	|
      |d<   nk|ri	 t'        j&                  t(        j*                  j-                  d            }|j/                  |j0                        }|r|\  }	}}
|	r|
rt%        |	|
      |d<   | ||fS # t2        $ r d }Y -w xY w)Nftp@r"   r%  r!   )r   r=   zfor use_gssapi=Truez https://pypi.org/project/gssapi/)r   r   r   r;   NETRC)r   r   r   r   r   r   _replacer   appendr   rz   GSSAPI_IMP_ERRr  r  HTTPPasswordMgrWithDefaultRealmadd_passwordHTTPBasicAuthHandlerHTTPDigestAuthHandlerbasic_auth_headernetrcr   environr&   authenticatorsrJ   rQ  )r   url_usernameurl_password
use_gssapiforce_basic_auth	use_netrcr*   handlersrW   r   r   r   credentialsimp_err_msgpassmanauthhandlerdigest_authhandlerrclogindummys                       r   _configure_authr  |  s   GHc]F}}GX%%HH		$mm11#q9V+!,!2!23!:Hh"HH8$8$ 78 OO1(HEF.x@U3UWK$[>RR	*..@@B 	T68X>
 nn99'B#^^AA'J 	$*+	&#4Xx#H 		RZZ^^G45B%%foo6E (-%HeXH+<Xx+P(!!  	E	s   %AH H H c                  j    e Zd Z	 	 	 	 	 ddZd Z	 	 	 	 	 	 	 ddZd Zd Zd ZddZ	dd	Z
dd
Zd Zy)r  Nc                   |xs i | _         t        | j                   t              st        d| j                   z        || _        || _        || _        || _        || _        || _	        || _
        |	| _        |
| _        || _        || _        || _        || _        || _        || _        || _        || _        || _        t        |t,        j.                        r|| _        yt-        j.                         | _        y)a<  This class works somewhat similarly to the ``Session`` class of from requests
        by defining a cookiejar that can be used across requests as well as cascaded defaults that
        can apply to repeated requests

        For documentation of params, see ``Request.open``

        >>> from ansible.module_utils.urls import Request
        >>> r = Request()
        >>> r.open('GET', 'http://httpbin.org/cookies/set?k1=v1').read()
        '{
  "cookies": {
    "k1": "v1"
  }
}
'
        >>> r = Request(url_username='user', url_password='passwd')
        >>> r.open('GET', 'http://httpbin.org/basic-auth/user/passwd').read()
        '{
  "authenticated": true, 
  "user": "user"
}
'
        >>> r = Request(headers=dict(foo='bar'))
        >>> r.open('GET', 'http://httpbin.org/get', headers=dict(baz='qux')).read()

        zheaders must be a dict: %rN)r*   
isinstancedict
ValueError	use_proxyforcer   r8  r  r  
http_agentr  r   r9  r:  r   ca_pathunredirected_headers
decompressr7  r  r   r   	CookieJarcookies)r   r*   r  r  r   r8  r  r  r  r  r   r9  r:  r  r   r  r  r  r7  r  r   s                        r   r   zRequest.__init__  s    . }"$,,-9DLLHII"
,(($ 0 0&$&$8!$"gy223"DL$..0DLr   c                    ||S |S r   rm   )r   valuefallbacks      r   	_fallbackzRequest._fallback  s    =Or   c                8
   |i }nt        |t              st        d      t        | j                  fi |}| j	                  || j
                        }| j	                  || j                        }| j	                  || j                        }| j	                  |	| j                        }	| j	                  |
| j                        }
| j	                  || j                        }| j	                  || j                        }| j	                  || j                        }| j	                  || j                        }| j	                  || j                        }| j	                  || j                        }| j	                  || j                         }| j	                  || j"                        }| j	                  || j$                        }| j	                  || j&                        }| j	                  || j(                        }| j	                  || j*                        }| j	                  || j,                        }| j	                  || j.                        }g }|r|j1                  t3        |             t5        ||
||||      \  }}}|j7                  |       |j9                  |       |s0t:        j<                  j?                  i       }|j1                  |       |stA        |||	||      }|rtC        ||      }n t:        j<                  jE                  |      }|j1                  |       |j1                  tG        |             |.|j1                  t:        j<                  jI                  |             t;        j<                  jJ                  | }t:        j<                  jM                  |       tO        |d      }t:        j<                  jQ                  |||jS                               } |r| jU                  d	|       |r| jU                  d
d       n.|r,tW        |jY                         d      }!| jU                  d|!       |xs g D "cg c]  }"|"j[                          }}"|D ]?  }#|#j[                         |v r| j]                  |#||#          +| jU                  |#||#          A t:        j<                  j_                  | d|      }$|rP|$j                  ja                  dd      j[                         dk(  r#tc        |$jd                        }%|%|$_2        d|$_3        |$S c c}"w )a  
        Sends a request via HTTP(S) or FTP using urllib (Python3)

        Does not require the module environment

        Returns :class:`HTTPResponse` object.

        :arg method: method for the request
        :arg url: URL to request

        :kwarg data: (optional) bytes, or file-like object to send
            in the body of the request
        :kwarg headers: (optional) Dictionary of HTTP Headers to send with the
            request
        :kwarg use_proxy: (optional) Boolean of whether or not to use proxy
        :kwarg force: (optional) Boolean of whether or not to set `cache-control: no-cache` header
        :kwarg last_mod_time: (optional) Datetime object to use when setting If-Modified-Since header
        :kwarg timeout: (optional) How long to wait for the server to send
            data before giving up, as a float
        :kwarg validate_certs: (optional) Booleani that controls whether we verify
            the server's TLS certificate
        :kwarg url_username: (optional) String of the user to use when authenticating
        :kwarg url_password: (optional) String of the password to use when authenticating
        :kwarg http_agent: (optional) String of the User-Agent to use in the request
        :kwarg force_basic_auth: (optional) Boolean determining if auth header should be sent in the initial request
        :kwarg follow_redirects: (optional) String of urllib2, all/yes, safe, none to determine how redirects are
            followed, see HTTPRedirectHandler for more information
        :kwarg client_cert: (optional) PEM formatted certificate chain file to be used for SSL client authentication.
            This file can also include the key as well, and if the key is included, client_key is not required
        :kwarg client_key: (optional) PEM formatted file that contains your private key to be used for SSL client
            authentication. If client_cert contains both the certificate and key, this option is not required
        :kwarg cookies: (optional) CookieJar object to send with the
            request
        :kwarg use_gssapi: (optional) Use GSSAPI handler of requests.
        :kwarg unix_socket: (optional) String of file system path to unix socket file to use when establishing
            connection to the provided url
        :kwarg ca_path: (optional) String of file system path to CA cert bundle to use
        :kwarg unredirected_headers: (optional) A list of headers to not attach on a redirected request
        :kwarg decompress: (optional) Whether to attempt to decompress gzip content-encoded responses
        :kwarg ciphers: (optional) List of ciphers to use
        :kwarg use_netrc: (optional) Boolean determining whether to use credentials from ~/.netrc file
        :kwarg context: (optional) ssl.Context object for SSL validation. When provided, all other SSL related
            arguments are ignored. See make_context.
        :returns: HTTPResponse. Added in Ansible 2.9
        Nzheaders must be a dict)r"  r7  r8  r9  r:  )r   r   )r   passthru)	nonstring)r   r  z
User-agentzcache-controlzno-cacheGMTzIf-Modified-Sincezcontent-encodingr!   r   )4r  r  r  r*   r  r  r  r   r8  r  r  r  r  r   r9  r:  r  r   r  r  r  r7  r  r   r  r   r  r   r0  r  r  ProxyHandlerr;  r   HTTPSHandlerr   HTTPCookieProcessorbuild_openerinstall_openerr   r  r  
add_headerr  r  r  rP   urlopenr&   r   rT   length)&r   r  r   r   r*   r  r  last_mod_timer   r8  r  r  r  r  r   r9  r:  r  r  r   r  r  r  r7  r  r   r  auth_headersauth_handlersproxyhandlerssl_handleropenerr  tstamphr   r=  rT   s&                                         r   rR   zRequest.open  s=   j ?GGT*566t||/w/NN9dnn=	udjj1..$,,78K8KL~~lD4E4EF~~lD4E4EF^^J@
>>*:D<Q<QR>>*:D<Q<QRnn[$2B2BC^^J@
..$,,7nn[$2B2BC..$,,7#~~.BDD]D]^^^J@
..$,,7NN9dnn=	..$,,7OOOK89+:3l\fhx  {D  ,E(\=|$&!>>66r:LOOL)"-'%G *{GTK ..55g5FK$+,<=> OOFNN>>wGH,,h7%%f-
3..((4(O |Z8 
;()@)@)BEJF2F; 5I4NBPa	PP 	<F||~!55//H""676?;		< NN""7D':!))--(:B?EEG6Q"144(BAD AH  Qs   Tc                *     | j                   d|fi |S )zSends a GET request. Returns :class:`HTTPResponse` object.

        :arg url: URL to request
        :kwarg \*\*kwargs: Optional arguments that ``open`` takes.
        :returns: HTTPResponse
        r  rR   r   r   r   s      r   r&   zRequest.get  s     tyy.v..r   c                *     | j                   d|fi |S )zSends a OPTIONS request. Returns :class:`HTTPResponse` object.

        :arg url: URL to request
        :kwarg \*\*kwargs: Optional arguments that ``open`` takes.
        :returns: HTTPResponse
        OPTIONSr  r  s      r   r+  zRequest.options  s     tyyC2622r   c                *     | j                   d|fi |S )zSends a HEAD request. Returns :class:`HTTPResponse` object.

        :arg url: URL to request
        :kwarg \*\*kwargs: Optional arguments that ``open`` takes.
        :returns: HTTPResponse
        r  r  r  s      r   headzRequest.head  s     tyy///r   c                .     | j                   d|fd|i|S )a(  Sends a POST request. Returns :class:`HTTPResponse` object.

        :arg url: URL to request.
        :kwarg data: (optional) bytes, or file-like object to send in the body of the request.
        :kwarg \*\*kwargs: Optional arguments that ``open`` takes.
        :returns: HTTPResponse
        r  r   r  r   r   r   r   s       r   postzRequest.post  s!     tyy:4:6::r   c                .     | j                   d|fd|i|S )a'  Sends a PUT request. Returns :class:`HTTPResponse` object.

        :arg url: URL to request.
        :kwarg data: (optional) bytes, or file-like object to send in the body of the request.
        :kwarg \*\*kwargs: Optional arguments that ``open`` takes.
        :returns: HTTPResponse
        PUTr   r  r  s       r   putzRequest.put  s!     tyy9$9&99r   c                .     | j                   d|fd|i|S )a)  Sends a PATCH request. Returns :class:`HTTPResponse` object.

        :arg url: URL to request.
        :kwarg data: (optional) bytes, or file-like object to send in the body of the request.
        :kwarg \*\*kwargs: Optional arguments that ``open`` takes.
        :returns: HTTPResponse
        PATCHr   r  r  s       r   patchzRequest.patch  s!     tyy#;D;F;;r   c                *     | j                   d|fi |S )zSends a DELETE request. Returns :class:`HTTPResponse` object.

        :arg url: URL to request
        :kwargs \*\*kwargs: Optional arguments that ``open`` takes.
        :returns: HTTPResponse
        DELETEr  r  s      r   deletezRequest.delete  s     tyy31&11r   )NTF
   TNNNFr  NNNNNNTNTN)NNNNNNNNNNNNNNNFNNNNNNNr   )re   rf   rg   r   r  rR   r&   r+  r  r  r  r  r  rm   r   r   r  r    s_    ]aY^jncg	/1b
 DHJN>B59INSW37Sj/30	;	:	<2r   r  c                x    |xs |rdnd}t               j                  || ||||||||	|
|||||||||||||      S )zp
    Sends a request via HTTP(S) or FTP using urllib (Python3)

    Does not require the module environment
    r  r  )r   r*   r  r  r  r   r8  r  r  r  r  r   r9  r:  r  r  r   r  r  r  r7  r  )r  rR   )r   r   r*   r  r  r  r  r   r8  r  r  r  r  r   r9  r:  r  r  r   r  r  r  r7  r  s                           r   open_urlr    sn     2$EF9>>&#D'Y %]Gdr'3,[e+;N^&1jRY%/[RY/CPZdk  xA  B Br   c           	     *   t        | t              s"t        d| j                  j                  z        t
        j                  j                  j                  d      }t        | j                               D ]  \  }}t        |t              r	d}d}|}d}nt        |t              r|j                  d      }|j                  d      }t        ||f      st        d      |j                  d	      }|s#	 t        j                   |xs d
d      d   xs d}|j%                  d      \  }}	}n"t        d|j                  j                  z        |st|rrt'        t)        |d      d      5 }
t
        j                  j*                  j-                  |
j/                               }|d= |j1                  d|d|       ddd       nDt
        j                  j2                  j5                  ||      }|j7                  t)        |             j1                  dd       |d= |j9                  d|d       |r:|j9                  dt;        t<        j>                  jA                  |            d       |jC                  |       
 |jE                  t
        jF                  jH                        }~|j%                  d      \  }}	}~t
        jJ                  jM                         jN                  } ||      d   |fS # t"        $ r d}Y w xY w# 1 sw Y   xY w)aA  Takes a mapping, and prepares a multipart/form-data body

    :arg fields: Mapping
    :returns: tuple of (content_type, body) where ``content_type`` is
        the ``multipart/form-data`` ``Content-Type`` header including
        ``boundary`` and ``body`` is the prepared bytestring body

    Payload content from a file will be base64 encoded and will include
    the appropriate ``Content-Transfer-Encoding`` and ``Content-Type``
    headers.

    Example:
        {
            "file1": {
                "filename": "/bin/true",
                "mime_type": "application/octet-stream"
            },
            "file2": {
                "content": "text based file content",
                "filename": "fake.txt",
                "mime_type": "text/plain",
            },
            "text_form_field": "value"
        }
    z&Mapping is required, cannot be type %sz	form-datatextplainNr   contentz4at least one of filename or content must be provided	mime_typer!   F)strictr   r   r   z5value must be a string, or mapping, cannot be type %sr0   r1   r   zContent-TypezContent-DispositionzMIME-Versionr5   r   )policys   

r  )(r  r   r(  r   re   emailmime	multipartMIMEMultipartsortedr  strr&   anyr  	mimetypes
guess_typerP  	partitionrR   r   applicationMIMEApplicationrH  r  nonmultipartMIMENonMultipartset_payload	set_paramr   r   r   r   attachas_bytesr  HTTPparserBytesHeaderParser
parsebytes)fieldsmfieldr  r   r   r  r   r  seprT  partb_datar*   	b_contentr  s                   r   prepare_multipartr    s   6 fg&4v7G7G7P7PP
 	
 	

**;7Av||~. /ueS!IHGHw'yy,Hii	*G'*+ !WXX99[)D6$//BuMaPnTnD (,~~c':$IsHG%//JbJbb  8hx0EFM QQRzz--==affhG(9h0OPQ Q
 ::**;;IxPDXg./-{; ( 	 	

 NN"''**845,   	
_/f ZZu||00Z1F	$..{;GS)\\++-88F 	w' W ! 65D6Q Qs   3"K6(AL6LLL	c                Z    |d}dt        j                  t        | d|d            z  S )zTakes a username and password and returns a byte string suitable for
    using as value of an Authorization header to do basic auth.
    r!   s   Basic %sr%  r0   r1   )r(   rO   r   )r   r   s     r   r  r  S  s2     ))(h3QZo*pqqqr   c                    t        t        d      t        dd      t        dd      t        dd      t        dd      t        d      t        dd      t        dd      t        d	      t        d	      t        dd      
      S )zz
    Creates an argument spec that can be used with any module
    that will be requesting content via urllib/urllib2
    r  )typeboolF)r  defaultansible-httpgetT)r  no_logr   )r   r  r  r  r8  r  r  r  r9  r:  r  )r  rm   r   r   url_argument_specr
  \  sx    
 e.U,=>FD16u%uT2659f%V$VU3 r   c           	        t         s$| j                  t        j                                t        j
                  }| j                  t        _        | j                  j                  dd      }|| j                  j                  dd      }| j                  j                  dd      }| j                  j                  dd      }| j                  j                  d	t                     }| j                  j                  d
d      }| j                  j                  dd      }| j                  j                  d      }| j                  j                  d      }| j                  j                  d|	      }	t        |t        j                        st        j                         }d}t        |d      }	 t        |fi d|d|d|d|d|d|d|d|d|d|d	|d
|d|d|d|d|d|	d|
d|d|d|d|d|}|j                  |j!                         j#                         D ci c]  \  }}|j%                         | c}}       i }|j&                  j#                         D ]8  \  }} |j%                         }||v rdj)                  ||   | f      ||<   4| ||<   : |j                  |       g }!i }"|D ]B  }#|#j*                  |"|#j,                  <   |!j/                  |#j,                  |#j*                  f       D d j)                  d! |!D              |d"<   |"|d<   |j                  t        d#|j&                  j                  d$d%      z  |j1                         |j2                  &             |t        _        ||fS c c}}w # t4        t6        f$ r'}$ | j                  d1d't9        |$      i| Y d}$~$Fd}$~$wt:        $ r0}$| j                  t=        |$      |$j>                  (       Y d}$~$}d}$~$wt@        jB                  jD                  $ r}$|$}	 |$jF                  tH        |$jK                         }%|$jM                          n# tH        $ r d}%Y nw xY w	 |j                  |$j!                         j#                         D ci c]  \  }}|j%                         | nc c}}w c}}       n# tN        $ r Y nw xY w|j                  t9        |$      |%|$j2                  d)       Y d}$~$yd}$~$wt@        jB                  jP                  $ rI}$tS        tU        |$d*d            }&|j                  t        d+t9        |$      z  |&,             Y d}$~$d}$~$wtV        jB                  $ r3}$|j                  t        d-t9        |$      z  d,             Y d}$~$!d}$~$wtX        jZ                  j\                  $ r=}$|j                  t        d.t9        |$j^                        z  d,             Y d}$~$yd}$~$wtN        $ rG}$|j                  t        d/t9        |$      z  d,      ta        jb                         0       Y d}$~$d}$~$ww xY w# |t        _        w xY w)2a  Sends a request via HTTP(S) or FTP (needs the module as parameter)

    :arg module: The AnsibleModule (used to get username, password etc. (s.b.).
    :arg url:             The url to use.

    :kwarg data:          The data to be sent (in case of POST/PUT).
    :kwarg headers:       A dict with the request headers.
    :kwarg method:        "POST", "PUT", etc.
    :kwarg use_proxy:     (optional) whether or not to use proxy (Default: True)
    :kwarg boolean force: If True: Do not get a cached copy (Default: False)
    :kwarg last_mod_time: Default: None
    :kwarg int timeout:   Default: 10
    :kwarg boolean use_gssapi:   Default: False
    :kwarg unix_socket: (optional) String of file system path to unix socket file to use when establishing
        connection to the provided url
    :kwarg ca_path: (optional) String of file system path to CA cert bundle to use
    :kwarg cookies: (optional) CookieJar object to send with the request
    :kwarg unredirected_headers: (optional) A list of headers to not attach on a redirected request
    :kwarg decompress: (optional) Whether to attempt to decompress gzip content-encoded responses
    :kwarg cipher: (optional) List of ciphers to use
    :kwarg boolean use_netrc: (optional) If False: Ignores login and password in ~/.netrc file (Default: True)

    :returns: A tuple of (**response**, **info**). Use ``response.read()`` to read the data.
        The **info** contains the 'status' and other meta data. When a HttpError (status >= 400)
        occurred then ``info['body']`` contains the error response data::

    Example::

        data={...}
        resp, info = fetch_url(module,
                               "http://example.com",
                               data=module.jsonify(data),
                               headers={'Content-type': 'application/json'},
                               method="POST")
        status_code = info["status"]
        body = resp.read()
        if status_code >= 400 :
            body = info['body']
    rV   r8  TNr  r  r!   r  r  r  r   r  r9  r:  r  )r   statusr   r*   r  r  r  r   r  r   r  r  r  r7  r  , z; c              3  &   K   | ]	  }d |z    yw)z%s=%sNrm   ).0cs     r   	<genexpr>zfetch_url.<locals>.<genexpr>  s     *L17Q;*Ls   cookies_stringzOK (%s bytes)zContent-Lengthunknown)rV   r   r  rV   )rV   	exception)rV   bodyr  rU   zRequest failed: %s)rV   r  zConnection failure: %szRConnection failure: connection was closed before a valid response was received: %szAn unknown error occurred: %s)r  rm   )2r   	fail_jsonr   r   tempfiletempdirtmpdirr   r&   get_user_agentr  r   r  r  r  r   infor  r  r*   r4  r  r5   r  r   rU   rp   r  r   rz   r   r}   r  r  r  rT   r   rH  r   rP  URLErrorintgetattrr   r   r   BadStatusLineline	traceback
format_exc)'r~   r   r   r*   r  r  r  r  r   r  r   r  r  r  r  r7  r  old_tempdirr8  r   r   r  r  r   r9  r:  r=  r  r   r  temp_headersr5   r  cookie_listcookie_dictcookier   r  rU   s'                                          r   	fetch_urlr*  p  s   X .AACD ""K}}H ]]&&'7>NMM%%k48	}}  4H}}  4H""<1ABJ}}(();R@}}(();YG--##M2K""<0J""<<Jgy223%%'AC#DK'S Rt RW RV R(R05RERR\cR$2RAIR #+R 8BR UeR '7	R EP	R
 !+R
 5<R
 ISR "-R 7>R UiR !+R 5<R HQR 	affhnn.>?daQWWY\?@ 99??, 	+KD%::<D|#%)YYT0BE/J%KT"%*T"	+ 	L!   	<F'-||K$V\\:;	< "&*L*L!L%YD_qyy}}=My/YY_`_g_g_irsrxrxyzN 'd7NG @6 Z( 32Yq\2T2 GWQZ13E3EFF<<!! K
	tt| %$668D GGI  	D		KK!&&(..2BC$!QACCD 		 	IaL$!&&IJJ<<   P71fb)*D1IaL@NOO<< RD5	!DRPQQ;;$$ SDqt}~  E  E  uF  F  OQ  R  	S  	S 6D<y|KTVW'224 	 	6 	66 's   .A;N )N 
D-N  N X=N72Y  7X=&O.)Y  . X=S*"Q3S*QS*QS*,R-RR-,S*-	R96S*8R99+S*$Y  * X=
>UY  X=$(VY   X=22W*$Y  *X=6<X82Y  8X==Y   Yc                    | j                  d      rg S | j                  d      } | j                  d      dd D cg c]  }d|z   	 c}S c c}w )z1A list of the final component's suffixes, if any..r"   N)endswithlstripr   )r5   ss     r   	_suffixesr0  	  sH    }}S	;;sD!ZZ_QR01C!G111s   A
c                    d}t        t        t        |                   D ]B  \  }}||k\  r | |fS |t        |      cxk  r|k  rn n||}| j	                  |      } ? | |fS  | |fS )a  Split a multi-part extension from a file name.

    Returns '([name minus extension], extension)'.

    Define the valid extension length (including the '.') with 'min' and 'max',
    'count' sets the number of extensions, counting from the end, to evaluate.
    Evaluation stops on the first file extension that is outside the min and max range.

    If no valid extensions are found, the original ``name`` is returned
    and ``extension`` is empty.

    :arg name: File name or path.
    :kwarg min: Minimum length of a valid file extension.
    :kwarg max: Maximum length of a valid file extension.
    :kwarg count: Number of suffixes from the end to evaluate.

    r!   )	enumeratereversedr0  lenr   )r5   minmaxcount	extensionisfxs          r   _split_multiextr;    s    $ IHYt_56 	3: ? #c(!c!"%y1I;;s#D ?	 ?r   c                   d}t        |      }t        t        j                  j	                  |j                        d      \  }}t        j                  | j                  ||d      }| j                  |j                         	 t        | |||||||||	|
|      \  }}|r|j                  r*|j                  dk\  r| j                  d|d	|d
          |j                  |      }|r%|j                  |       |j                  |      }|r%|j                          |j                  S # t         $ r6}| j                  d|d	t#        |             Y d}~|j                  S d}~ww xY w)a  Download and save a file via HTTP(S) or FTP (needs the module as parameter).
    This is basically a wrapper around fetch_url().

    :arg module: The AnsibleModule (used to get username, password etc. (s.b.).
    :arg url:             The url to use.

    :kwarg data:          The data to be sent (in case of POST/PUT).
    :kwarg headers:       A dict with the request headers.
    :kwarg method:        "POST", "PUT", etc.
    :kwarg boolean use_proxy:     Default: True
    :kwarg boolean force: If True: Do not get a cached copy (Default: False)
    :kwarg last_mod_time: Default: None
    :kwarg int timeout:   Default: 10
    :kwarg unredirected_headers: (optional) A list of headers to not attach on a redirected request
    :kwarg decompress: (optional) Whether to attempt to decompress gzip content-encoded responses
    :kwarg ciphers: (optional) List of ciphers to use

    :returns: A string, the path to the downloaded file.
    i   r#   )r7  F)dirprefixsuffixr  )r  r  r7  r	  zFailure downloading r  rV   r  N)r   r;  r   r   r   r  NamedTemporaryFiler  add_cleanup_filer5   r*  rU   r  rH  writer   rP  r   )r~   r   r   r*   r  r  r  r  r   r  r  r7  bufsizer   file_prefixfile_extfetch_temp_filerspr  r   s                       r   
fetch_filerH  2  sQ   . GSME+BGG,<,<UZZ,HPQRK11fmmK`hqvwO
O001Qfc4&)UTacj3GT^hoq	TsxxCHHOd5k!RSxx !!$'88G$D  	   QS)A,OPPQs   B	D* D* *	E)3!E$$E)c                      y)z%Returns a user agent used by open_urlr  rm   rm   r   r   r  r  ]  s    r   )NNNNTNNrd   )F)z-0000)NNNTFNr  TNNNFr  NNNFNNNTNT)NNNNFNr  FNNNNTNT)r  r  r#   )
NNNTFNr  NTN)nrh   
__future__r   r(   email.mime.applicationr  email.mime.multipartemail.mime.nonmultipartemail.parseremail.policyemail.utilshttp.clientr   r  r  r   rF   ri   r   r  r#  typesurllib.errorr  urllib.request
contextlibr   r   urllib.parser   r   r   r	   r   r   r   r   ImportErrorr$  objectansible.module_utils.basicr   'ansible.module_utils.common.collectionsr   r   +ansible.module_utils.common.text.convertersr   r   r   r)  HAS_SSLrP  ra  cryptographyr   cryptography.hazmat.backendsr   cryptography.hazmat.primitivesr   cryptography.exceptionsr   urllib_gssapi
HAS_GSSAPIr  r=   r   rj   MSr   rp   rs   ru   rx   rz   r   r   r   r   HTTPSConnectionr  r  r   r   HTTPHandlerr   r  r   r   r   r   r   r   r   r;  r1  rE   rH   r  r  r  r  r  r  r
  r*  r0  r;  rH  r  rm   r   r   <module>rg     s.   #           	  	       %  6 6 &	HL }}H ; H T TG  !<5<
J P!I I` bjjB
$$+	i 	
	 	
	 		# 	    
6 6dkk99 "6>>66 (33 (Hfnn00 HhD h&
\6
 
8O
&..<< O
d hl $NI9X."A"HS2 S2l CGIM>B6?8<9=QUB,_Nr( <@GIcg7;Vr2B =AHJCG( VC)  H'9'')LH  G    Jd  !)Y))+N !sZ   2I I7 (J J 
J! I43I47JJJJJJ!J=<J=