o ݀a @sdZdZdZgdZdZdZddlZddlZddlZddl Z ddl Z ddl m Z ddl Z ddl Z ddlZdd lmZddlZdd lmZdd lmZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl!Z!ddl"Z#ddl$Z$zddl%Z%Wne&yd d l'm%Z%Ynwd dl'm(Z(d dl)Td dl*m*Z*ddZ+gdZ,dZ-dZ.dZ/gdZ0dZ1e2dZ3ddl4m5Z5e56Z7e8eddpe8edZ9     ddddZ:ddZ;d d!Zd#d$Z?d%d&Z@e=d'ZAe=d(ejBZCd)d*ZDe=d+ZEd,d-ZFd.d/ZGd0d1ZHdZId2d3ZJd4d5ZKd6d7ZLd8d9ZMd:d;ZNdd?d?ePZQGd@dAdAeQZRGdBdCdCeQZSGdDdEdEeQZTGdFdGdGeQZUGdHdIdIeQZVeReUeSeTeVdJZWgdKZXGdLdMdMePZYGdNdOdOePZZGdPdQdQeZZ[GdRdSdSePZ\GdTdUdUePZ]dedWdXZ^dfdYdZZ_Gd[d\d\ej`jaZbGd]d^d^ej`jcZdebedd_ZeGd`dadaePZfGdbdcdcegZhdS)gz+Small, fast HTTP client library for Python.z!Joe Gregorio (joe@bitworking.org)zCopyright 2006, Joe Gregorio) !Thomas Broyer (t.broyer@ltgt.net)z James AntillzXavier Verges FarrerozJonathan Feinbergz Blair ZajaczSam RubyzLouis Nyffeneggerz Mark PilgrimzAlex YuMITz0.20.2N)header)gettext)md5)sha1)socks)auth)*)iri2uricCs$ttdr|duo |tjuS|duS)N_GLOBAL_DEFAULT_TIMEOUT)hasattrsocketr )timeoutr3/usr/lib/python3/dist-packages/httplib2/__init__.py has_timeout9s r) debuglevelFailedToDecompressContentHttp HttpLib2Error ProxyInfo RedirectLimitRedirectMissingLocationResponseRETRIES"UnimplementedDigestAuthOptionError&UnimplementedHmacDigestAuthOptionError) connectionz keep-alivezproxy-authenticatezproxy-authorizationtetrailerstransfer-encodingupgrade)GETHEADOPTIONSTRACE),-./i34)certs PROTOCOL_TLSPROTOCOL_SSLv23cCsttds tdtt}|rtjntj|_|dur3t|dr/t|t r+t tj |}||_ ntd|durOt|drKt|t rGt tj |}||_ ntdt|drX| |_|||rf|||||S)N SSLContextz0httplib2 requires Python 3.2+ for ssl.SSLContextmaximum_versionzHsetting tls_maximum_version requires Python 3.7 and OpenSSL 1.1 or newerminimum_versionzHsetting tls_minimum_version requires Python 3.7 and OpenSSL 1.1 or newercheck_hostname)rssl RuntimeErrorr2DEFAULT_TLS_VERSION CERT_NONE CERT_REQUIRED verify_mode isinstancestrgetattr TLSVersionr3r4r5load_verify_locationsload_cert_chain)"disable_ssl_certificate_validationca_certs cert_filekey_filer3r4 key_passwordcontextrrr_build_ssl_contexts,          rHcsDttdd|dddDfddt|DS)NcSg|]}|qSrstrip.0xrrr z(_get_end2end_headers..r!,csg|]}|vr|qSrr)rMrhopbyhoprrrO)list HOP_BY_HOPextendgetsplitkeys)responserrSr_get_end2end_headerss"r]cCsjt|jdkrt|jdtjr|jdjS|jSt|dr3|j}t|jdtjr0|jdjS|jSdS)Nr socket_err)lenargsr<rerrorerrnorr^)ee_intrrr_errno_from_exceptions $ $rez9^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?cCs0t|}|d|d|d|d|dfS)zParses a URI using the regex given in Appendix B of RFC 3986. (scheme, authority, path, query, fragment) = parse_uri(uri) r)URImatchgroups)urirlrrr parse_uris"rncCsxt|\}}}}}|r |std||}|}|sd}|r(d||gp)|}|}|d||}||||fS)Nz(Only absolute URIs are allowed. uri = %s/?z://)rnRelativeURIErrorlowerjoin)rmscheme authoritypathqueryfragment request_uri defrag_urirrrurlnorms  r{z^\w+://z[^\w\-_.()=!]+cCsbt|tr |}|d}n|d}t|}td|}td|}|dd}d ||fS)zReturn a filename suitable for the cache. Strips dangerous and common characters to create a filename we can use to store the cache in. utf-8rQNZrR) r<bytesdecodeencode_md5 hexdigest re_url_schemesub re_unsafers)filenamefilename_bytesfilemd5rrrsafenames       rz(?:\r\n)?[ \t]+cCstdd|DS)NcSs0g|]\}}t|tt|dfqS) )_convert_byte_strrrNORMALIZE_SPACErrK)rMkeyvaluerrrrOsz&_normalize_headers..)dictitemsheadersrrr_normalize_headerss rcCst|ts t|dS|SNr|)r<r=)srrrr s  rcCsFi}d|vr!|dd}dd|D}dd|D}t||}|S)N cache-controlrRcSs4g|]}d|dkrtdd|ddDqS)=cSsg|]}|qSr)rKrrrLrrrrOrUz3_parse_cache_control...r)findtuplerZ)rMpartrrrrOs.z(_parse_cache_control..cSs*g|]}d|dkr|dfqS)rrr)rrKrr)rMnamerrrrOs*)rZr)rretvalpartsparts_with_args parts_wo_argsrrr_parse_cache_controls rc Csd}t|}t|}d|vr%|dddkr%d}d|vr#d|d<|Sd|vr-d}|Sd|vr5d}|Sd|vr=d}|Sd |vrttj|d }t}t d ||}d |vrozt |d }Wn+t ynd }Yn!wd |vrtj|d } d | krd }n t d t| |}nd }d |vrzt |d }Wn t yd }Ynwd|vrzt |d} Wn t yd } Ynw|| 7}||krd}|S)aDetermine freshness from the Date, Expires and Cache-Control headers. We don't handle the following: 1. Cache-Control: max-stale 2. Age: headers are not used in the calculations. Not that this algorithm is simpler than you might think because we are operating as a private (non-shared) cache. This lets us ignore 's-maxage'. We can also ignore 'proxy-invalidate' since we aren't a proxy. We will never return a stale document as fresh as a design decision, and thus the non-implementation of 'max-stale'. This also lets us safely ignore 'must-revalidate' since we operate as if every server has sent 'must-revalidate'. Since we are private we get to ignore both 'public' and 'private' parameters. We also ignore 'no-transform' since we don't do any transformations. The 'no-store' parameter is handled at a higher level. So the only Cache-Control parameters we look at are: no-cache only-if-cached max-age min-fresh STALEpragmazno-cacher TRANSPARENTronly-if-cachedFRESHdaterzmax-ageexpiresNz min-fresh) rrrrcalendartimegmemailutils parsedate_tztimemaxint ValueError) response_headersrequest_headersrcc cc_responsernow current_agefreshness_lifetimer min_freshrrr_entry_disposition&sb%#!   rc Cs|}z<|dd}|dvr<|dkrtjt|d}|dkr(t|tj }t t ||d<|d|d<|d=W|SW|St tj fyWd}t td |d||w) Ncontent-encoding)gzipdeflater)fileobjrcontent-lengthz-content-encodingrQzDContent purported to be compressed with %s but failed to decompress.)rYrGzipFileioBytesIOreadzlib decompress MAX_WBITSr=r_IOErrorrar_)r\ new_contentcontentencodingrrr_decompressContentqs,  rcsfdd}|S)NcsD]4\}}td|d|jdt|tjr%t|j|jd|jdqtj||jd|d}t||jdqt|jddS)Nz%s:r)endfile) maxlinelen)rr|)rcharset header_name)rprint_fpr<rHeaderr _maxheaderlen)selfhvrmsgrr_write_headerss z+_bind_write_headers.._write_headersr)rrrrr_bind_write_headerss  rc CsH|rt|}t|}d|vsd|vr||dStj}|D] \}} |dvr.| ||<q"|dd} | r\| dd d} | D]} d| }z|| ||<WqDt y[YqDw|j } | dkred } d | }z| }Wnt yt|d t|| }Ynwtd d |}d|d|d|g}|||dSdS)Nzno-store)statusrr$varyrrQrR -varied-%s0z status: %d rz (?! )|(?.r|)rrctimerangerr)digrrr_cnonces " rcCs,ttd|||fddS)Nz%s%s%sr|)base64 b64encode_shardigestrKr)cnonceiso_nowpasswordrrr_wsse_username_tokens*rc@sleZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ ddZ ddZ ddZdS)Authenticationc Cs.t|\}} } } } | |_||_||_||_dSN)rnrvhost credentialshttp) rr r ryrr\rr rtrurvrwrxrrr__init__s  zAuthentication.__init__cCs*t|\}}}}}|t|jddS)Nro)rnr_rvcount)rryrtrurvrwrxrrrdepthszAuthentication.depthcCs(t|\}}}}}||jko||jSr )rnr  startswithrv)rr ryrtrurvrwrxrrrinscopeszAuthentication.inscopecCdS)znModify the request headers to add the appropriate Authorization header. Over-rise this in sub-classes.NrrmethodryrrrrrrequestszAuthentication.requestcCr)a Gives us a chance to update with new nonces or such returned from the last authorized response. Over-rise this in sub-classes if necessary. Return TRUE is the request is to be retried, for example Digest may return stale=true. Fr)rr\rrrrr\szAuthentication.responsecCrNFrrr rrr__eq__zAuthentication.__eq__cCrNTrrrrr__ne__rzAuthentication.__ne__cCrrrrrrr__lt__rzAuthentication.__lt__cCrrrrrrr__gt__rzAuthentication.__gt__cCrrrrrrr__le__rzAuthentication.__le__cCrrrrrrr__ge__rzAuthentication.__ge__cCrrrrrrr__bool__ rzAuthentication.__bool__N)__name__ __module__ __qualname__rrrrr\rrrrrr r"rrrrr s  r c@eZdZddZddZdS)BasicAuthenticationc Ct||||||||dSr r rrr r ryrr\rr rrrrzBasicAuthentication.__init__cCs,dtd|jdd|d<dS)OModify the request headers to add the appropriate Authorization header.zBasic rr| authorizationN)rrr rrKrrrrrrs   zBasicAuthentication.requestNr#r$r%rrrrrrr's r'c@s*eZdZdZddZd ddZddZdS) DigestAuthenticationzMOnly do qop='auth' and MD5, since that is all Apache currently implementsc Cst||||||||t|dd|_|jdd}ddd|Dvr)dp*d|jd<|jddur=ttd||jdd  |jd<|jdd kr[ttd |jdd |j d d |jdd |j dg|_ d|jd<dS)Nwww-authenticaterqopr cSrIrrJrLrrrrO#rPz1DigestAuthentication.__init__..zUnsupported value for qop: %s. algorithmMD5$Unsupported value for algorithm: %s.rQr:realmrnc) r rr _parse_www_authenticate challengerYrZrrupperrsr A1) rr r ryrr\rr r1rrrrs$(zDigestAuthentication.__init__Nc sddfdd}d|d|g}|pt|jd<d||jd|jd d |jd |jd|jd |f}d |jd|jd|jd ||jd||jd |jd |jdf |d<|jdrr|dd|jd7<|jd d7<dS)Modify the request headerscSst|dSr)rrr)rNrrr0sz.DigestAuthentication.request..csd||fS)Nrr)rdHrrr=1srQr5rz"%s"%s:%s:%s:%s:%snoncez%08xr7r1zoDigest username="%s", realm="%s", nonce="%s", uri="%s", algorithm=%s, response=%s, qop=%s, nc=%08x, cnonce="%s"rr6r2r-opaquez , opaque="%s"rN)rsrr9r;r rY) rrryrrrKDA2request_digestrr?rr.s<    zDigestAuthentication.requestcCszd|vr%t|ddi}d|dkr#|d|jd<d|jd<d Sd St|d}d |vr;|d |jd<d|jd<d S) Nzauthentication-infor0rtruestalerBrr7T nextnonceF)r r8rYr9_parse_authentication_info)rr\rr9updated_challengerrrr\Rs   zDigestAuthentication.responser )r#r$r%__doc__rrr\rrrrr/s   $r/c@s,eZdZdZdZddZddZddZd S) HmacDigestAuthenticationz@Adapted from Robert Sayre's code and DigestAuthentication above.rc Cst||||||||t|d}|d|_|jdd|jd<|jddvr-d|jd<|jdd|jd<|jdsCttd |jd d |jd <|jd d vr_ttd |jd |jdd|jd<|jddvr{ttd|jd|jd dkrt|_ nt |_ |jddkrt|_ nt |_ d |j dd|j d |j d|jdgd|jdg|_|j |j|_dS)Nr0 hmacdigestreason unauthorized)rP integritysaltrQsnoncezCThe challenge doesn't contain a server nonce, or this one is empty.r2 HMAC-SHA-1)rTHMAC-MD5r4z pw-algorithmSHA-1)rVr3z'Unsupported value for pw-algorithm: %s.rUr3rr5rr6)r rr r8r9rYrrrhashmodr pwhashmodrsr newrrrr) rr r ryrr\rr r9rrrrgsH    ( z!HmacDigestAuthentication.__init__c st}ddd|D}dfdd|D}tdt}t} d||| |jd|f} t|j | |j  } d|j d |jd |jd| ||| |fd <d S) r<rQcSsg|]}d|qS)z%s rrMkrrrrOrPz4HmacDigestAuthentication.request..csg|]}|qSrrrZrrrrOrP%Y-%m-%dT%H:%M:%SZrArSzsHMACDigest username="%s", realm="%s", snonce="%s", cnonce="%s", uri="%s", created="%s", response="%s", headers="%s"rr6r-N)r]rsrstrftimegmtimerr9hmacrYrrWrrrr ) rrryrrr[keylist headers_valcreatedrrFrrrrs$ z HmacDigestAuthentication.requestcCs*t|ddi}|ddvrdSdS)Nr0rNrO)rQrHTF)r r8rY)rr\rr9rrrr\sz!HmacDigestAuthentication.responseN)r#r$r%rL __author__rrr\rrrrrMbs * rMc@ eZdZdZddZddZdS)WsseAuthenticationaThis is thinly tested and should not be relied upon. At this time there isn't any third party server to test against. Blogger and TypePad implemented this algorithm at one point but Blogger has since switched to Basic over HTTPS and TypePad has implemented it wrong, by never issuing a 401 challenge but instead requiring your client to telepathically know that their endpoint is expecting WSSE profile="UsernameToken".c Cr(r r)r*rrrrr+zWsseAuthentication.__init__cCsNd|d<tdt}t}t|||jd}d|jd|||f|d<dS) r,zWSSE profile="UsernameToken"r-r\rzJUsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"rzX-WSSEN)rr]r^rrr )rrryrrrrpassword_digestrrrrszWsseAuthentication.requestN)r#r$r%rLrrrrrrres rec@r&)GoogleLoginAuthenticationc Csddlm}t||||||||| |d} | ddd} | dkr-|ddkr-d} t|d|d | |d d } |jj d d || ddid\} }| d} tdd| D}| j dkrcd|_ dS|d|_ dS)Nr) urlencoder0 googleloginservicexapirclr user-agent)EmailPasswdrjsourcez+https://www.google.com/accounts/ClientLoginPOSTz Content-Typez!application/x-www-form-urlencoded)rbodyr cSs g|] }|rt|ddqS)rr)rrZ)rMlinerrrrOs z6GoogleLoginAuthentication.__init__..irQAuth) urllib.parserhr rr8rYrrr rrZrru)rr r ryrr\rr rhr r9rjresplinesr>rrrrs$     z"GoogleLoginAuthentication.__init__cCsd|j|d<dS)r,zGoogleLogin Auth=r-N)rurrrrrsz!GoogleLoginAuthentication.requestNr.rrrrrgs rg)basicwsserrNri)rNrirrzryc@s4eZdZdZefddZddZddZdd Zd S) FileCachezUses a local directory as a store for cached files. Not really safe to use if multiple threads or processes are going to be running on the same cache. cCs,||_||_tj|st|jdSdSr )rsafeosrvexistsmakedirs)rrr|rrrrs  zFileCache.__init__cCsPd}tj|j||}zt|d}|}|W|Sty'Y|Sw)Nrb) r}rvrsrr|openrcloser)rrr cacheFullPathfrrrrYs   z FileCache.getcCs6tj|j||}t|d}|||dS)Nwb)r}rvrsrr|rwriter)rrrrrrrrrs   z FileCache.setcCs4tj|j||}tj|rt|dSdSr )r}rvrsrr|r~remove)rrrrrrrs zFileCache.deleteN) r#r$r%rLrrrYrrrrrrr{s   r{c@s.eZdZddZd ddZddZdd Zd S) CredentialscC g|_dSr r r!rrrr zCredentials.__init__rQcCs|j|||fdSr r appendrrrrrdomainrrradd szCredentials.addcCrr rr!rrrclear#rzCredentials.clearccs2|jD]\}}}|dks||kr||fVqdSNrQr)rrcdomainrrrrriter&s  zCredentials.iterNrQ)r#r$r%rrrrrrrrrs   rc@rd)KeyCertszNIdentical to Credentials except that name/password are mapped to key/cert.cCs|j||||fdSr rrrcertrrrrrr0r+z KeyCerts.addccs6|jD]\}}}}|dks||kr|||fVqdSrr)rrrrrrrrrr3s  z KeyCerts.iterN)r#r$r%rLrrrrrrr,s rc@s eZdZdS)AllHostsN)r#r$r%rrrrr9src@sHeZdZdZdZ dddZddZd d Zd d Zd dZ ddZ dS)rz,Collect information required to use a proxy.rTNcCsVt|tr |}t|tr|}|||||||f\|_|_|_|_|_|_|_ dS)aArgs: proxy_type: The type of proxy server. This must be set to one of socks.PROXY_TYPE_XXX constants. For example: p = ProxyInfo(proxy_type=socks.PROXY_TYPE_HTTP, proxy_host='localhost', proxy_port=8000) proxy_host: The hostname or IP address of the proxy server. proxy_port: The port that the proxy server is running on. proxy_rdns: If True (default), DNS queries will not be performed locally, and instead, handed to the proxy to resolve. This is useful if the network does not allow resolution of non-local names. In httplib2 0.9 and earlier, this defaulted to False. proxy_user: The username used to authenticate with the proxy server. proxy_pass: The password used to authenticate with the proxy server. proxy_headers: Additional or modified headers for the proxy connect request. N) r<r~r proxy_type proxy_host proxy_port proxy_rdns proxy_user proxy_pass proxy_headers)rrrrrrrrrrrrBs(   zProxyInfo.__init__cCs |j|j|j|j|j|j|jfSr )rrrrrrrr!rrrastuplelszProxyInfo.astuplecCsto |jdko |jdkSr )r rrr!rrrisgoodwszProxyInfo.isgoodcCs || Sr ) bypass_host)rhostnamerrr applies_tozs zProxyInfo.applies_tocCsX|jturdSd|d}|jD]}|dr ||r dS|d|kr)dSqdS)z1Has this host been excluded from the proxy configT.F) bypass_hostsrlstriprendswith)rr skip_namerrrr}s   zProxyInfo.bypass_hostcCs dj|dS)Nz)p)formatr!rrr__repr__szProxyInfo.__repr__)TNNN) r#r$r%rLrrrrrrrrrrrr=s *  rr cCsD|dvrdS|d}tj|tj|}|sdSt||ddS)z4Read proxy info from the environment variables. r httpsN_proxy)noproxy)r}environrYr:proxy_info_from_url)renv_varurlrrrproxy_info_from_environmentsrc Cstj|}d}d}d}d|dvr,|ddd\}}d|vr)|dd\}}n|}n|d}d|vr=|dd\}}n|}|rFt|}ntddd|}d} t| |||pWd|pZddd } g} |durptj d tj d d }|d krwt } n| r|d} t t t| } | | _| S)zBConstruct a ProxyInfo from a URL (such as http_proxy env var) N@rr5iP)rr rf)rrrrrrno_proxyNO_PROXYrQr rR)urllibparseurlparserZrrrr}rrYrrKrfilterboolr) rrrusernamerportident host_portr rpirrrrrsF     rc@s"eZdZdZdddZddZdS)HTTPConnectionWithTimeoutagHTTPConnection subclass that supports timeouts HTTPConnection subclass that supports timeouts All timeouts are in seconds. If None is passed for timeout then Python's default timeout for sockets will be used. See for example the docs of socket.setdefaulttimeout(): http://docs.python.org/library/socket.html#socket.setdefaulttimeout NcCs@tjjj||||d||_|rt|ts|d|_dSdSdS)N)rrr )r clientHTTPConnectionr proxy_infor<r)rr rrrrrrrs z"HTTPConnectionWithTimeout.__init__cCs|jr tdur td|jr-|jr-|j|jr-d}|j\}}}}}}}|} |} n d}|j} |j} d}d} t | | dtj D]} | \} }}}}zf|rbt | |||_ |j ||||||nt| |||_ |j tjtjdt|jr|j |j|jdkrtd|j|j|rtdt||||||f|j |j|jf|d dWn@tjy}z3|} |jdkrtd |j|j|rtd t||||||f|j r|j d|_ WYd}~qBd}~ww|j s| dS) z3Connect to the host and port specified in __init__.Nz2Proxy support missing but proxy use was requested!TFrrz connect: ({0}, {1}) ************zproxy: {0} ************rconnect fail: ({0}, {1}) proxy: {0})rr ProxiesUnavailableErrorrrr rrr getaddrinfo SOCK_STREAM socksocketsocksetproxy setsockopt IPPROTO_TCP TCP_NODELAYrr settimeoutrrrr=connectrar)r use_proxyrrrrrrrr rr^resafsocktypeproto canonnamesarcrrrrsz    $   z!HTTPConnectionWithTimeout.connect)NNN)r#r$r%rLrrrrrrrs rcs>eZdZdZ          dfdd ZddZZS) HTTPSConnectionWithTimeouta-This class allows communication via SSL. All timeouts are in seconds. If None is passed for timeout then Python's default timeout for sockets will be used. See for example the docs of socket.setdefaulttimeout(): http://docs.python.org/library/socket.html#socket.setdefaulttimeout NFc sz||_|r|nt|_||_|rt|ts|d|_t|j|j||| | | d} tt|j |||| d||_ ||_ | |_ dS)Nr)r3r4rF)rrrG) rBCA_CERTSrCrr<rrHsuperrrrErDrF) rr rrErDrrrCrBtls_maximum_versiontls_minimum_versionrFrG __class__rrr3s(   z#HTTPSConnectionWithTimeout.__init__cCs|jr"|jr"|j|jr"d}|j\}}}}}}}|} |} n d}|j} |j} d}d}d} t| | dtj} | D]\} }}}}z|rXt | ||}| ||||||nt| ||}| tj tjdt|jrs||j||j|jf|jj||jd|_t|jds|jsz t|j|jWnty|jtj|jw|jdkrt d!|j|j|rt d !t"||||||fWnptj#tj$fy}z|r||jr|jd|_d}~wtjtj%fytj&yA}z6|} |jdkr+t d !|j|j|r+t d !t"||||||f|jr4|jd|_WYd}~q;d}~ww|jsI| dS) z(Connect to a host on a given (SSL) port.TFNrr)server_hostnamer5zconnect: ({0}, {1})rr)'rrrr rrrrrr rrrrrrrrr_context wrap_socketrrrBr6match_hostname getpeercert Exceptionshutdown SHUT_RDWRrrrrr=SSLErrorCertificateErrorgaierrorra)rrrrrrrrrr rr^ address_infofamilyrrrsockaddrrrcrrrrYs           z"HTTPSConnectionWithTimeout.connect) NNNNNNFNNN)r#r$r%rLrr __classcell__rrrrr*s &rrc@seZdZdZddeddddfddZddZdd Zd d Zd d Z dddZ dddZ ddZ ddZ ddZddZdddedfddZdS) rzAn HTTP client that handles: - all methods - caching - ETags - compression, - HTTPS - Basic - Digest - WSSE and more. NFcCs||_||_||_||_||_i|_|rt|trt||_ n||_ t |_ t |_ g|_d|_t|_ddg|_tt|_d|_d|_d|_||_d|_dS)aIf 'cache' is a string then it is used as a directory name for a disk cache. Otherwise it must be an object that supports the same interface as FileCache. All timeouts are in seconds. If None is passed for timeout then Python's default timeout for sockets will be used. See for example the docs of socket.setdefaulttimeout(): http://docs.python.org/library/socket.html#socket.setdefaulttimeout `proxy_info` may be: - a callable that takes the http scheme ('http' or 'https') and returns a ProxyInfo instance per request. By default, uses proxy_info_from_environment. - a ProxyInfo instance (static proxy config). - None (proxy disabled). ca_certs is the path of a file containing root CA certificates for SSL server certificate validation. By default, a CA cert file bundled with httplib2 is used. If disable_ssl_certificate_validation is true, SSL cert validation will not be performed. tls_maximum_version / tls_minimum_version require Python 3.7+ / OpenSSL 1.1.0g+. A value of "TLSv1_3" requires OpenSSL 1.1.1+. TPUTPATCHFN)rrCrBrr connectionsr<r=r{rrr r certificatesauthorizationsfollow_redirectsREDIRECT_CODESredirect_codesoptimistic_concurrency_methodsrV SAFE_METHODS safe_methodsfollow_all_redirects ignore_etagforce_exception_to_status_coderforward_authorization_headers)rrrrrCrBrrrrrrs*$    z Http.__init__cCs>|ji}|_|D]\}}|q |j|dS)zClose persistent connections, clear sensitive data. Not thread-safe, requires external synchronization against concurrent requests. N)rrrrrclear_credentials)rexistingrcrrrrs    z Http.closecCs,t|j}d|vr |d=d|vr|d=|S)Nrr)copy__dict__)r state_dictrrr __getstate__$s zHttp.__getstate__cCs|j|i|_dSr )rupdater)rstaterrr __setstate__.s  zHttp.__setstate__c csPt|d}|j|D]}tD]}||vr$t||||||||Vqq dS)zcA generator that creates Authorization objects that can be applied to requests. r0N)r r8r rAUTH_SCHEME_ORDERAUTH_SCHEME_CLASSES) rr ryrr\r challengescredrtrrr_auth_from_challenge2s zHttp._auth_from_challengerQcCs|j|||dS)z]Add a name and password that will be used any time a request requires authentication.N)r rrrrradd_credentials<szHttp.add_credentialscCs|j||||dS)zXAdd a key and cert that will be used any time a request requires authentication.N)rrrrrradd_certificateAszHttp.add_certificatecCs|jg|_dS)zKRemove all the names and passwords that are used for authenticationN)r rrr!rrrrFs  zHttp.clear_credentialsc Cs d}d}|tkr |d7}z|jdur||||||Wnvtjy-|tjy?|td|j tj yb}zt |} | t j t jfvr]|tkr]WYd}~qd}~wtjjy|jdur|tdkr||Yq||tdkr||YqYnwz|} WnLtjjtjjfy|s|dkrd}d}||Yq|tjytj tjjfy||dkr||Yqwd} |dkr|n| } t| } |dkrt| | } | | fS| | fS)NrFrzUnable to find the server at %sTrr')rrrrrrrrServerNotFoundErrorr rarerb ENETUNREACH EADDRNOTAVAILr r HTTPException getresponse BadStatusLineResponseNotReadyrrr) rconnryrrrrrseen_bad_status_linercerrno_r\rrrr _conn_requestLs            zHttp._conn_requestc sfdd|jD} | rt| ddpd} | r!| ||||||||\} } | rJ| | |rJ| ||||||||\} } d| _| jdkr||| | D](}|||||||||\} } | jdkr|j||| |nqX|j s||j vs| jdvri|j rK| j|j vrK|rEd| vr| jd krt td | | d| vr| d}t|\}}}}}|dkrtj||| d<| jd ks| jd kr||j vr| d| d <d| vr|| d<t|| | |j| d|vr|d=d|vr|d=d|vr |js |d=d| vrA| d}t| }d|vr$||d<|}| jdvr0d}d}|j|||||dd\} } || _| | fStd| | | jdvri||j vrid| vr`|| d<t|| | |j| | | fS)zmDo the actual request using the connection object and also follow one level of redirects if necessarycs&g|]}|r||fqSr)rr)rMr r ryrrrOs&z!Http._request..rrNi)r-r.locationr*z:Redirected but the response is missing a Location: header.r.r+-x-permanent-redirect-urlzcontent-location if-none-matchif-modified-sincer-)r,r-r&)rrrr redirections4Redirected more times than redirection_limit allows.)r)rsortedrrr\ _stale_digestrrrrrrrrrrnrrurljoinrrrrdeepcopypreviousr)rrr  absolute_uriryrrrrr#rauthsr r\rr-rrtrurvrwrx old_responseredirect_methodrrr_requests               z Http._requestcCst|Sr )r)rrrrrrszHttp._normalize_headersr&c! Cshd}z|dur i}n||}d|vrdt|d<t|}|ddddd d }t|\}} } } |d | }|j|} | dur|sJt|}t|j | } t |t r| r|| | d d | d d |j |j|j|j|j|j| d dd } |j|<n%|| |j |j|j|j|j|jd} |j|<n|| |j |jd} |j|<| td|vrd|vrd|d<tj}d}d}|jr| }|j|}|rz0|dd \}}t|}|D]\}}|dr|dr||ttj !|d qWnt"t#fy|j$|d}d}Ynw||j%vr2|jr2d|vr2|j&s2d|vr2|d|d<|jrE|rE||j'vrE|j$|||j'vrzd|vrz|d}|(ddd}|D]}d|}||}||d|krxd}nqa|jrs|rs||j'vs|ddkrsd|vrs|}|ddvrd }d!|vr|d krt)d"id|j*|d!|||d d#\}}t+||_,d$|j,_-nat.||}|d%kr|sd&|d<d'}t+|}|rd$|_-||fWS|d(krd|vr|j&sd)|vr|d|d)<d*|vrd*|vr|d*|d+<n|d,kr |/| | || ||||| \}}|j0d-kra|d krat1|D] }||||<q7t+|}t2|d.rO|j3|_3t4||||j||}d/|_0d$|_-n?|j0d/krj|}n;|j$||}n(t5|}d0|vrd&|d<t+|}d'}n#|/| | || ||||| \}}W||fSW||fSW||fSW||fSW||fSt6y3}zxt7|t8j } | r|j9|d} | r| :|j;rt7|t<r|j=}|j>}d1|_0t||_?n6t7|t8j rd2}t+d3d4t@|d5}d6|_?n(t|Ad7}t+d3d8t@|d5}d9|_?nWYd}~||fSWYd}~||fSWYd}~||fSd}~ww):a Performs a single HTTP request. The 'uri' is the URI of the HTTP resource and can begin with either 'http' or 'https'. The value of 'uri' must be an absolute URI. The 'method' is the HTTP method to perform, such as GET, POST, DELETE, etc. There is no restriction on the methods allowed. The 'body' is the entity body to be sent with the request. It is a string object. Any extra headers that are to be sent with the request should be provided in the 'headers' dictionary. The maximum number of redirect to follow before raising an exception is 'redirections. The default is 5. The return value is a tuple of (response, content), the first being and instance of the 'Response' class, the second being a string that contains the response entity body. rQNrmzPython-httplib2/%s (gzip)rz%20 z%0Drsz%0Ar5rrr) rErDrrrCrBrrrF)rrrCrBrr)rrrzaccept-encodingz gzip, deflates z=?z?=etagzif-matchrrRrr308)307r2r&r r$)rrr#Tr504rrr!z last-modifiedr"rrr'rrisRequest Timeoutz text/plain408)z content-typerrzRequest Timeoutr|400z Bad Request)Br __version__r rr{rrYSCHEME_TO_CONNECTIONrVrr issubclassrrrrCrBrrset_debuglevelrrrrrrZmessage_from_bytesrrrreplace_headerr=r decode_header IndexErrorrrrrrrrrrrr* fromcacherr/rr]rr'rrrr<rpoprrHttpLib2ErrorWithResponser\rrOr_r)!rrmrrrrr#connection_typeconn_keyrtruryrzrr/rr cached_valuerr[rrrrrrr.r\rentry_dispositionmerged_responserrc is_timeoutrrrrst                                     #)&      z Http.requestrr )r#r$r%rLrrrrr rrrrrr/rDEFAULT_MAX_REDIRECTSrrrrrrs, S   JO rc@s<eZdZdZ dZ dZ dZ dZdZddZ d d Z dS) rzr8rHr]recompilerjrnr{rASCIIrrrrrrUSE_WWW_AUTH_STRICT_PARSINGrrrrrrobjectr r'r/rMrergr r r{rrrrrrrrrHTTPSConnectionrr8rrrrrrrs            -    K*6 GN$#  W 2W '