
    lg;                     J   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mZmZmZmZmZ d dlmZmZ d dlmZmZ d dlmZmZmZmZ dZdZdZd	Zd
Z  ejB                   ejD                  e#            Z$ edde%fdee&e&f   fde'fg      Z( edde%fdee&e&f   fde&fdee&ef   fdee   fg      Z)de&de*fdZ+de&dee&   de&dee&   fdZ,i a-dee&   dee&   ddfdZ.dee&e&f   fdZ/dej`                  jb                  dee&e&f   fdZ2	 d1dejf                  dee%   de(fd Z4d! Z5d" Z6	 	 d2dejf                  dee%   dee&   de(fd#Z7dee   fd$Z8de&fd%Z9	 d2de&dee%   dee'e&f   fd&Z:di ddd'fde&d(ee'   dee&e&f   d)ee&   dee%   d*e*de)fd+Z;	 d3d,e&d-e&d.e&d/e&de)f
d0Z<y)4    N)AnyDictList
NamedTupleOptionalTuple)errorrequest)ParseResulturlparse)defaults
exceptionssystemutil)z169.254.169.254metadataz[fd00:ec2::254]zhttp://archive.ubuntu.comzhttps://esm.ubuntu.comzhttp://api.snapcraft.iozhttps://api.snapcraft.ioUnparsedHTTPResponsecodeheadersbodyHTTPResponse	json_dict	json_listurlreturnc                     	 t        |       }|j                  dvry	 |j                   y# t        $ r Y yw xY w# t        $ r Y yw xY w)NF)httpshttpT)r   
ValueErrorschemeport)r   
parsed_urls     8/usr/lib/python3/dist-packages/uaclient/http/__init__.pyis_service_urlr#   +   s\    c]
  11     s   * 9 	66	AAprotocolproxytest_urlc                 x   |sy t        |      st        j                  |      t        j                  |d      }| dk(  rMt        |      j                  dk(  r5	 t        ||      }|j                   dk(  r|S t        j                  |      t        j"                  | |i      }t        j$                  |      }	 |j'                  |       |S # t        j                  $ r  t        j                  $ r  t        j                  $ r  t        $ r<}t        j                  d||t        |             t        j                  |      d }~ww xY w# t(        j*                  t        j,                  f$ rG}t        j                  d||t/        |d	t        |                   t        j                  |      d }~ww xY w)
N)r%   HEAD)methodr   https_proxyz:Error trying to use "%s" as pycurl proxy to reach "%s": %s   z:Error trying to use "%s" as urllib proxy to reach "%s": %sreason)r#   r   ProxyInvalidUrlr
   Requestr   r   _readurl_pycurl_https_in_httpsPycurlRequiredErrorProxyAuthenticationFailedPycurlCACertificatesError	ExceptionLOGr	   strProxyNotWorkingErrorr   ProxyHandlerbuild_openeropensockettimeoutURLErrorgetattr)r$   r%   r&   reqresponseeproxy_handleropeners           r"   validate_proxyrD   <   s    % ((u55
//(6
2C7x55@	?5cuMH  ==CL11>>(((E):;M!!-0F
;C3 -- 	33 	33 	 	?IILA	 11>>	?( NNENN+ ;		HAxQ(		
 --E::;s2   C ;E AE7EE#F92AF44F9
http_proxyr+   c           
      ~   i }| r| |d<   |r||d<   dj                  t        t                    }dD ]r  }t        j                  j                  |      }|s%dj                  t        t        |j                  d            j                  t        t                                }t t        j                  d|       |t        j                  d<   |t        j                  d<   |r?t        j                  |      }t        j                  |      }t        j                  |       t        j                  dd	|i
       |ay)aW  
    Globally configure pro-client to use http and https proxies.

    - sets global proxy configuration for urllib
    - sets the no_proxy environment variable for the current process
      which gets inherited for all subprocesses
    - sets module variable for use in https-in-https pycurl requests
      this is retrieved later using get_configured_web_proxy

    :param http_proxy: http proxy to be used by urllib. If None, it will
                       not be configured
    :param https_proxy: https proxy to be used by urllib. If None, it will
                        not be configured
    r   r   ,)no_proxyNO_PROXYzSetting no_proxy: %srH   rI   zSetting global proxy dictextra)rJ   N)joinsortedUA_NO_PROXY_URLSosenvirongetsetsplitunionr5   debugr
   r8   r9   install_opener_global_proxy_dict)rE   r+   
proxy_dictrH   env_varproxy_valuerB   rC   s           r"   configure_web_proxyrZ   q   s   " J'
6)
7 xx/01H+ jjnnW-xx))#./55c:J6KLH	 II$h/%BJJz%BJJz,,Z8%%m4v&II)':1FIG#    c                      t         S N)rV    r[   r"   get_configured_web_proxyr_      s    r[   c                 r    | j                         D ci c]  \  }}|j                         | c}}S c c}}w r]   )itemslower)r   kvs      r"   _headers_to_dictre      s*    &-mmo6UQAGGIqL666s   3r?   r<   c                    	 t        j                  | |      }|j                         }t        |j                  t        |j                         |      S # t        j                  $ r}|}Y d }~Ud }~wt        j                  $ rN}t
        j                  t        |j                               t        j                  || j                        d }~ww xY w)Nr<   )causer   r   r   r   )r
   urlopenr	   	HTTPErrorr=   r5   	exceptionr6   r-   r   ConnectivityErrorfull_urlreadr   r   re   r   )r?   r<   resprA   r   s        r"   _readurl_urllibrq      s    FsG4 99;DYY .  ?? >> Fc!((m$**EEFs$   A C'A..CA	CCc                     t        |      }t        |       }|j                  dk(  xr7 t        j                  |j
                         xr |duxr |j                  dk(  }t        j                  d|       |S )a  
    We only want to use pycurl if all of the following are true

    - The target url scheme is https
    - The target host is not in no_proxy
    - An https_proxy is configured either via pro's config or via environment
    - The https_proxy url scheme is https

    urllib.request provides some helpful functions that we re-use here.

    This function also returns the https_proxy to use, since it is calculated
    here anyway.
    r   NzShould use pycurl: %r)r   _parse_https_proxyr   r
   proxy_bypasshostnamer5   rT   )r+   
target_urlparsed_target_urlparsed_https_proxyrets        r"   should_use_pycurlrz      s     !,+K8  G+ 	1$$%6%?%?@@	1d*	1 %%0	  II%s+Jr[   c                 F   d }d }t        | j                        dkD  r| j                  d   }t        | j                        dkD  r| j                  d   }||k(  r|rd|v rt        j                         ||k(  rt        j                  |      t        j
                  |       )Nr      407r   )rA   )lenargsr   r2   r3   PycurlError)r	   r   authentication_error_codeca_certificates_error_coder   msgs         r"   _handle_pycurl_errorr      s     D
C
5::zz!}
5::jjm((SUc\2244	+	+22s;;$$u--r[   c                    	 dd l }|j	                         }| j                         j                         }|dk(  r|j                  |j                  d       n|dk(  r|j                  |j                  d       nn|dk(  rO|j                  |j                  d       | j                  rA|j                  |j                  | j                         nt        dj                  |            |j                  |j                  | j!                                | j#                         D cg c]  \  }}dj                  ||       }}}t%        |      dkD  r|j                  |j&                  |       |j                  |j(                  d       |j                  |j*                  t,        j.                         |r|j                  |j0                  |       |rXt3        |      }	|	r|	j5                         nd }|j                  |j6                  |       |j                  |j8                  d       nt:        j=                  d	       t?        j@                         }
|j                  |jB                  |
       i fd
}|j                  |jD                  |       	 |jG                          tQ        |jS                  |jT                              }|
jW                         }|jY                          t[        ||      S # t        $ r t        j                         w xY wc c}}w # |jH                  $ r;}tK        || j!                         |jL                  |jN                         Y d }~d }~ww xY w)Nr   GETTr(   POSTz5HTTP method "{}" not supported in HTTPS-in-HTTPS modez{}: {}   z1in pycurl request function without an https proxyc                     | j                  d      } d| vry | j                  dd      \  }}|j                         j                         }|j                         }||<   y )Nz
iso-8859-1:r|   )decoderR   striprb   )header_linename_raw	value_rawnamevaluer   s        r"   save_headerz3_readurl_pycurl_https_in_https.<locals>.save_header(  s_    !((6k!)//Q7)~~%%'!r[   )r   r   r   ri   ).pycurlImportErrorr   r1   Curl
get_methoduppersetoptHTTPGETNOBODYr   dataCOPYPOSTFIELDSr   formatURLget_full_urlheader_itemsr   
HTTPHEADERFOLLOWLOCATIONCAINFOr   SSL_CERTS_PATHTIMEOUTrs   geturlPROXY	PROXYTYPEr5   warningioBytesIO	WRITEDATAHEADERFUNCTIONperformr	   r   E_RECV_ERRORE_SSL_CACERT_BADFILEintgetinfoRESPONSE_CODEgetvaluecloser   )r?   r<   r+   r   cr)   r   valheader_str_listrx   body_outputr   rA   r   r   r   s                  @r"   r0   r0      s   
/ 	A ^^##%F	&	6		%	6		d#88HHV**CHH5CJJ
 	
 HHVZZ))+, 584D4D4F'0tSc"O  ?a	""O4 HHV""D)HHV]]H334	) /<+=%%'4 	 	
{+	!!1%GH **,KHHV{+G HHV""K0
			 qyy--./D!DGGI c  /,,../4T << 
  "&,&9&9'-'B'B		
 	

s)   K6 $LL 6LM',1M""M'c                 j    | s#t        j                         j                  d      } | rt        |       S d S )Nr   )r
   
getproxiesrP   r   r*   s    r"   rs   rs   J  s0    ((*..w7$/8K 9T9r[   c                     | j                   j                  d      }i }|si }nJt        j                  j	                  |      si }n(t        j                  t        j                  |            }|j                  |g       S )Nserviceclient_url_responses)	featuresrP   rN   pathexistsjsonloadsr   	load_file)cfgr   response_overlay_pathresponse_overlays       r"   _get_overlay_datar   P  sl    LL,,-JK WW^^12::f&6&67L&MNR((r[   c                 z   t        | |      }|rH|j                  d      }t        j                  |d   d         5 }|j	                         dfcd d d        S t        |      st        j                  |      t        j                  dj                  |             t               j                  d      }i }|r||d<   t        ||      rt        t        j                   ||	      ||
      }|j"                  dk(  rt        j$                  |      t        j&                  |j(                        |j*                  j                  d      fS t        j                   ||	      }		 t        j,                  |	      5 }t        j                  |      5 }|j	                         |j*                  j                  d      fcd d d        cd d d        S # 1 sw Y   xY w# 1 sw Y   nxY w	 d d d        y # 1 sw Y   y xY w# t.        j0                  $ r+}
|
j"                  dk(  rt        j$                  |       d }
~
ww xY w)Nr   r@   	file_path r~   zURL [GET]: {}r   zIf-None-Match)r   r<   r+   i0  etagETag)r   poplzmar:   ro   r#   r   
InvalidUrlr5   rT   r   r_   rP   rz   r0   r
   r/   r   ETagUnchanged
decompressr   r   rj   r	   rk   )r   r   r<   r   overlay_responser@   fr+   r   r?   rA   s              r"   download_xz_file_from_urlr   ^  s    )c2#''*YYx
+K89 	"QFFHb>	" 	" ###,,IIo$$S)**,009KG#' c*1OOC1#
 ==C**s33 OOHMM*  (
 	

 ooc73	% YYx( A ((,,V4  =	" 	">      	vv} ..377		s_   G$G< 9G0+G:	G0	G< GG#	G0'G< 0G95G< 9G< <H:&H55H:Tr   r)   log_response_bodyc           
         t        |       st        j                  |       |r|sd}t        j                  | |||      }dj                  t        |      D cg c]  }dj                  |||          c}      }t        j                  dj                  |xs d| ||r|j                  d      nd              t               j                  d	      }	t        |	|       rt        |||	
      }
nt        ||      }
|
j                   j                  dd      }i }g }d|
j"                  j                  dd      v rjt%        j&                  |t(        j*                        }t-        |t.              r|}n2t-        |t0              r|}nt        j3                  dt5        |             dj                  t        |
j"                        D cg c]!  }dj                  ||
j"                  |         # c}      }dj                  |xs d| |      }|r)|
j                   }|r|}n|r|}|dj                  |      z  }t        j                  |       t7        |
j8                  |
j"                  |||      S c c}w c c}w )Nr~   r   )r   r   r)   z, z
'{}': '{}'z'URL [{}]: {}, headers: {{{}}}, data: {}r   utf-8r   r   rg   ignoreerrorsapplication/jsoncontent-typer   clsunexpected JSON response: %sz&URL [{}] response: {}, headers: {{{}}}z
, data: {}r   r   r   r   r   )r#   r   r   r
   r/   rK   rL   r   r5   rT   r   r_   rP   rz   r0   rq   r   r   r   r   r   DatetimeAwareJSONDecoder
isinstancedictlistr   r6   r   r   )r   r   r   r)   r<   r   r?   rc   sorted_header_strr+   rp   decoded_bodyr   r   	json_body	debug_msgbody_to_logs                    r"   readurlr     s1    ###,,F
//#D'&
IC		5;G_E		Q
	+E II188Oe$(DKK d		
 +,009Kc*-k
 sG499##GH#=LIIT\\--nbAAJJ|1N1NO	i&!I	4(!IKK6IG		:@:NOQ		QQ	0O 9??%/I ii#K#K\((55	IIiYY a 	FB 	Ps   I.&I3socket_pathhttp_method	http_pathhttp_hostnamec                 X   t        j                   t         j                  t         j                        }|j                  |        t        j
                  j                  |      }||_        	 |j                  ||       |j                         }|j                         j                  dd      }|j                          |j                          i }g }	d|j                  j                  dd      v rjt        j                   |t"        j$                        }
t'        |
t(              r|
}n2t'        |
t*              r|
}	nt,        j/                  dt1        |
             t3        |j4                  t7        |j                        |||		      S # |j                          |j                          w xY w)
Nr   r   r   r   r   r   r   r   r   )r;   AF_UNIXSOCK_STREAMconnectr   clientHTTPConnectionsockr
   getresponsero   r   r   r   rP   r   r   r   r   r   r   r   r5   r   r6   r   statusre   )r   r   r   r   r   connrp   outr   r   r   s              r"   unix_socket_requestr     s<    ==););<DLL;;%%m4DDI[),!iik   :



IIT\\--nbAAJJs(E(EF	i&!I	4(!IKK6IG[[ .  	



s   +AF "F)r]   )NN)	localhost)=email.messageemailhttp.clientr   r   r   loggingr   rN   r;   typingr   r   r   r   r   r   urllibr	   r
   urllib.parser   r   uaclientr   r   r   r   rM   PROXY_VALIDATION_APT_HTTP_URLPROXY_VALIDATION_APT_HTTPS_URLPROXY_VALIDATION_SNAP_HTTP_URLPROXY_VALIDATION_SNAP_HTTPS_URL	getLoggerreplace_top_level_logger_name__name__r5   r   r6   bytesr   r   boolr#   rD   rV   rZ   r_   messageMessagere   r/   rq   rz   r   r0   rs   r   r   r   r   r^   r[   r"   <module>r     s     	    	  ? ? ! . 7 7E  ; !9 !: "< g:::8DE!		DcN#	  		DcN#		d38n%	d3i 	  "/;/;"3-/;36/;c]/;d  .$.$,4SM.$	.$b$sCx. 7emm33 7S#X 7 "	c] *4.& "!%\	\c]\ #\ 	\~:x'< :) ) 8<//$SM/
5#:/h !  !"F	F
5/F #s(^F SM	F
 c]F F FZ %	&&& & 	&
 &r[   