lJc@s0dZddkZddkZddkZddkZddkZddkZddkZddkZddk Z ddk Z ddk Z ddk Z ddk Z yddklZWn#ej oddklZnXddklZlZlZlZlZlZlZlZlZlZlZlZlZlZl Z ddkl!Z!l"Z"l#Z#e i$d Z%da'ddZ(dZ)d e*fd YZ+d e+efd YZ,d e+fdYZ-ei.dZ/dZ0ddGdYZ1ddHdYZ2dZ3ddIdYZ4de4fdYZ5de4fdYZ6de4fdYZ7dZ8de4fd YZ9d!dJd"YZ:d#e:fd$YZ;d%dKd&YZ<d'e<e4fd(YZ=d)e<e4fd*YZ>d+Z?d,dLd-YZ@d.e4e@fd/YZAd0e4e@fd1YZBd2e4fd3YZCd4eCfd5YZDeEed6od7eCfd8YZFnd9e4fd:YZGd;e4fd<YZHd=ZId>ZJd?e4fd@YZKdAe4fdBYZLdCeLfdDYZMdEe4fdFYZNdS(Ms An extensible library for opening URLs using a variety of protocols The simplest way to use this module is to call the urlopen function, which accepts a string containing a URL or a Request object (described below). It opens the URL and returns the results as file-like object; the returned object has some extra methods described below. The OpenerDirector manages a collection of Handler objects that do all the actual work. Each Handler implements a particular protocol or option. The OpenerDirector is a composite object that invokes the Handlers needed to open the requested URL. For example, the HTTPHandler performs HTTP GET and POST requests and deals with non-error returns. The HTTPRedirectHandler automatically deals with HTTP 301, 302, 303 and 307 redirect errors, and the HTTPDigestAuthHandler deals with digest authentication. urlopen(url, data=None) -- basic usage is the same as original urllib. pass the url and optionally data to post to an HTTP URL, and get a file-like object back. One difference is that you can also pass a Request instance instead of URL. Raises a URLError (subclass of IOError); for HTTP errors, raises an HTTPError, which can also be treated as a valid response. build_opener -- function that creates a new OpenerDirector instance. will install the default handlers. accepts one or more Handlers as arguments, either instances or Handler classes that it will instantiate. if one of the argument is a subclass of the default handler, the argument will be installed instead of the default. install_opener -- installs a new opener as the default opener. objects of interest: OpenerDirector -- Request -- an object that encapsulates the state of a request. the state can be a simple as the URL. it can also include extra HTTP headers, e.g. a User-Agent. BaseHandler -- exceptions: URLError-- a subclass of IOError, individual protocols have their own specific subclass HTTPError-- also a valid HTTP response, so you can treat an HTTP error as an exceptional event or valid response internals: BaseHandler and parent _call_chain conventions Example usage: import urllib2 # set up authentication info authinfo = urllib2.HTTPBasicAuthHandler() authinfo.add_password('realm', 'host', 'username', 'password') proxy_support = urllib2.ProxyHandler({"http" : "http://ahad-haam:3128"}) # build a new opener that adds authentication and caching FTP handlers opener = urllib2.build_opener(proxy_support, authinfo, urllib2.CacheFTPHandler) # install it urllib2.install_opener(opener) f = urllib2.urlopen('http://www.python.org/') iN(tStringIO(tunwraptunquotet splittypet splithosttquotet addinfourlt splitporttsplitgophertypet splitqueryt splitattrt ftpwrappert noheaderst splitusert splitpasswdt splitvalue(t localhostt url2pathnamet getproxiesicCs*tdjo tanti||S(N(t_openertNonet build_openertopen(turltdata((s/sys/lib/python/urllib2.pyturlopenus  cCs |adS(N(R(topener((s/sys/lib/python/urllib2.pytinstall_opener{stURLErrorcBseZdZdZRS(cCs|f|_||_dS(N(targstreason(tselfR((s/sys/lib/python/urllib2.pyt__init__s cCs d|iS(Ns(R(R((s/sys/lib/python/urllib2.pyt__str__s(t__name__t __module__R R!(((s/sys/lib/python/urllib2.pyRs t HTTPErrorcBs)eZdZeiZdZdZRS(sBRaised when HTTP error occurs, but also acts like non-error returncCsU||_||_||_||_||_|dj o|i|||ndS(N(tcodetmsgthdrstfptfilenameRt_HTTPError__super_init(RRR%R&R'R(((s/sys/lib/python/urllib2.pyR s      cCsd|i|ifS(NsHTTP Error %s: %s(R%R&(R((s/sys/lib/python/urllib2.pyR!s(R"R#t__doc__RR R*R!(((s/sys/lib/python/urllib2.pyR$s  t GopherErrorcBseZRS((R"R#(((s/sys/lib/python/urllib2.pyR,ss:\d+$cCsa|i}ti|d}|djo|idd}ntid|d}|iS(sReturn request-host, as defined by RFC 2965. Variation from RFC: returned value is lowercased, for convenient comparison. ittHost(t get_full_urlturlparset get_headert _cut_port_retsubtlower(trequestRthost((s/sys/lib/python/urllib2.pyt request_hosts   tRequestcBseZdhdedZdZdZdZdZdZ dZ dZ dZ d Z d Zd Zd Zd ZdZdZddZdZRS(cCst||_d|_d|_d|_||_h|_x*|iD]\}}|i ||qIWh|_ |djot |}n||_ ||_ dS(N(Rt_Request__originalRttypeR6tportRtheaderstitemst add_headertunredirected_hdrsR7torigin_req_hostt unverifiable(RRRR<R@RAtkeytvalue((s/sys/lib/python/urllib2.pyR s         cCse|d djoG|d}ttd|o%t|d|t||SqXnt|dS(Ni t _Request__r_tget_(thasattrR8tgetattrtAttributeError(Rtattrtname((s/sys/lib/python/urllib2.pyt __getattr__s  cCs|iodSndSdS(NtPOSTtGET(thas_data(R((s/sys/lib/python/urllib2.pyt get_methods cCs ||_dS(N(R(RR((s/sys/lib/python/urllib2.pytadd_datascCs |idj S(N(RR(R((s/sys/lib/python/urllib2.pyRNscCs|iS(N(R(R((s/sys/lib/python/urllib2.pytget_datascCs|iS(N(R9(R((s/sys/lib/python/urllib2.pyR/scCsZ|idjoCt|i\|_|_|idjotd|iqSn|iS(Nsunknown url type: %s(R:RRR9t_Request__r_typet ValueError(R((s/sys/lib/python/urllib2.pytget_types cCsV|idjo?t|i\|_|_|iot|i|_qOn|iS(N(R6RRRRt_Request__r_hostR(R((s/sys/lib/python/urllib2.pytget_hosts  cCs|iS(N(RU(R((s/sys/lib/python/urllib2.pyt get_selectorscCs#|||_|_|i|_dS(N(R6R:R9RU(RR6R:((s/sys/lib/python/urllib2.pyt set_proxyscCs|iS(N(R@(R((s/sys/lib/python/urllib2.pytget_origin_req_hostscCs|iS(N(RA(R((s/sys/lib/python/urllib2.pytis_unverifiablescCs||i|iscCs||i|iR]R_R1Rd(((s/sys/lib/python/urllib2.pyR8s&               tOpenerDirectorcBsMeZdZdZdZdZddZddZdZ RS(cCsMdt}d|fg|_g|_h|_h|_h|_h|_dS(NsPython-urllib/%ss User-agent(t __version__t addheadersthandlerst handle_opent handle_errortprocess_responsetprocess_request(Rtclient_version((s/sys/lib/python/urllib2.pyR s     c Cst}xst|D]e}|d joqn|id}|| }||d}|idoq|id|d}||d}yt|}Wntj onX|ii|h} | |i||D]6}t||}||}|dj o|SqqWdS(N((R`RGR( RtchainRt meth_nameRRiRtfunctresult((s/sys/lib/python/urllib2.pyt _call_chainYs  c Cst|tot||}n%|}|dj o|i|n|i}|d}x8|ii|gD]!}t||}||}qsW|i ||}|d}x;|i i|gD]$}t||}|||}qW|S(Nt_requestt _response( t isinstancet basestringR8RRPRTRmR`RGt_openRl( RtfullurlRtreqRRt processorRRt((s/sys/lib/python/urllib2.pyRes$    cCs}|i|idd|}|o|Sn|i}|i|i||d|}|o|Sn|i|idd|S(NRat default_openRtunknownt unknown_open(RRjRT(RRRRR((s/sys/lib/python/urllib2.pyRs   cGs|d jo1|id}|d}d|}d}|}n|i}|d}d}|||f|}|i|}|o|Sn|o$|dd f|}|i|SndS( Nthttpthttpsis http_error_%sit_erroriRathttp_error_default(shttpshttps(RkR(RtprotoRtdictRthttp_errt orig_argsR((s/sys/lib/python/urllib2.pyRss        N( R"R#R RRRRRRRs(((s/sys/lib/python/urllib2.pyRfs ,   c sYddkfd}t}tttttttt g}t t do|i t ng}xr|D]j}xa|D]Y}||o%t||o|i |qq}t||o|i |q}q}WqpWx|D]}|i|qWx|D]}|i|qWx5|D]-}||o |}n|i|q$W|S(sCreate an opener object from a list of handlers. The opener will use several default handlers, including support for HTTP and FTP. If any of the handlers passed as arguments are subclasses of the default handlers, the default handlers will not be used. iNcs t|ip t|dS(Nt __bases__(Rt ClassTypeRF(tobj(ttypes(s/sys/lib/python/urllib2.pytisclassstHTTPS(RRft ProxyHandlertUnknownHandlert HTTPHandlertHTTPDefaultErrorHandlertHTTPRedirectHandlert FTPHandlert FileHandlertHTTPErrorProcessorRFthttplibR|t HTTPSHandlert issubclassRtremoveR(RiRRtdefault_classestskiptklasstcheckth((Rs/sys/lib/python/urllib2.pyRs<      t BaseHandlercBs)eZdZdZdZdZRS(icCs ||_dS(N(tparent(RR((s/sys/lib/python/urllib2.pyR~scCsdS(N((R((s/sys/lib/python/urllib2.pyRscCs(t|dptSn|i|ijS(Nt handler_order(RFR}R(Rtother((s/sys/lib/python/urllib2.pyt__lt__s(R"R#RR~RR(((s/sys/lib/python/urllib2.pyRs  RcBs#eZdZdZdZeZRS(sProcess HTTP error responses.icCsV|i|i|i}}}|djo%|iid|||||}n|S(NiiR(ii(R%R&tinfoRRs(RR5RtR%R&R'((s/sys/lib/python/urllib2.pyt http_responses    (R"R#R+RRthttps_response(((s/sys/lib/python/urllib2.pyRs RcBseZdZRS(cCs"t|i||||dS(N(R$R/(RRR(R%R&R'((s/sys/lib/python/urllib2.pyRs(R"R#R(((s/sys/lib/python/urllib2.pyRsRcBs:eZdZdZdZdZeZZZdZ RS(ii cCs|i}|djo |djp|djoH|djo;|idd }t|d |id |id tSnt|i||||d S(sReturn a Request or None in response to a redirect. This is called by the http_error_30x methods when a redirection response is received. If a redirection should take place, return a new Request to allow http_error_30x to perform the redirect. Otherwise, raise HTTPError if no-one else should try to handle this url. Return None if you can't but another Handler might. i-i.i/i3RMtHEADRLt s%20R<R@RAN(i-i.i/i3(sGETR(i-i.i/(ROtreplaceR8R<RYR}R$R/(RRR(R%R&R<tnewurltm((s/sys/lib/python/urllib2.pyRos     c Cshd|jo|idd}n)d|jo|idd}ndSti|i|}|i||||||}|djodSnt|doo|i}|_|i|d|i jpt ||i jo)t |i||i |||q*nh}|_|_|i|dd||<|i|i|ii|S(Ntlocationiturit redirect_dicti(t getheadersR0turljoinR/RoRRFRR`t max_repeatstlentmax_redirectionsR$tinf_msgtreadRRR( RRR(R%R&R<Rtnewtvisited((s/sys/lib/python/urllib2.pythttp_error_302s(     soThe HTTP server returned a redirect error that would lead to an infinite loop. The last 30x error message was: ( R"R#RRRoRthttp_error_301thttp_error_303thttp_error_307R(((s/sys/lib/python/urllib2.pyRs   %c Cst|\}}|idpd}|}n[|idptd|n|idd}|djo d}n|d|!}t|\}}|dj ot|\}}n d}}||||fS(s3Return (scheme, user, password, host/port) given a URL or an authority. If a URL is supplied, it must have an authority (host:port) component. According to RFC 3986, having an authority component means the URL must have two slashes after the scheme: >>> _parse_proxy('file:/ftp.example.com/') Traceback (most recent call last): ValueError: proxy URL with no authority: 'file:/ftp.example.com/' The first three items of the returned tuple may be None. Examples of authority parsing: >>> _parse_proxy('proxy.example.com') (None, None, None, 'proxy.example.com') >>> _parse_proxy('proxy.example.com:3128') (None, None, None, 'proxy.example.com:3128') The authority component may optionally include userinfo (assumed to be username:password): >>> _parse_proxy('joe:password@proxy.example.com') (None, 'joe', 'password', 'proxy.example.com') >>> _parse_proxy('joe:password@proxy.example.com:3128') (None, 'joe', 'password', 'proxy.example.com:3128') Same examples, but with URLs instead: >>> _parse_proxy('http://proxy.example.com/') ('http', None, None, 'proxy.example.com') >>> _parse_proxy('http://proxy.example.com:3128/') ('http', None, None, 'proxy.example.com:3128') >>> _parse_proxy('http://joe:password@proxy.example.com/') ('http', 'joe', 'password', 'proxy.example.com') >>> _parse_proxy('http://joe:password@proxy.example.com:3128') ('http', 'joe', 'password', 'proxy.example.com:3128') Everything after the authority is ignored: >>> _parse_proxy('ftp://joe:password@proxy.example.com/rubbish:3128') ('ftp', 'joe', 'password', 'proxy.example.com') Test for no trailing '/' case: >>> _parse_proxy('http://joe:password@proxy.example.com') ('http', 'joe', 'password', 'proxy.example.com') t/s//sproxy URL with no authority: %riiN(RRwRRSRvR R( tproxytschemetr_schemet authoritytendtuserinfothostporttusertpassword((s/sys/lib/python/urllib2.pyt _parse_proxyHs2      RcBs#eZdZddZdZRS(idcCs|djo t}nt|dp td||_x=|iD]/\}}t|d||||idqJWdS(Nthas_keysproxies must be a mappings%s_opencSs||||S(((trRR:R((s/sys/lib/python/urllib2.pyts(RRRFtAssertionErrortproxiesR=tsetattrRq(RRR:R((s/sys/lib/python/urllib2.pyR s     c Cs|i}t|\}}}}|djo |}n|oP|oIdt|t|f} ti| i} |idd| nt|}|i||||jodSn|i i |SdS(Ns%s:%ssProxy-authorizationsBasic ( RTRRRtbase64t b64encodetstripR>RXRR( RRRR:t orig_typet proxy_typeRRRt user_passtcreds((s/sys/lib/python/urllib2.pyRqs     N(R"R#RRR Rq(((s/sys/lib/python/urllib2.pyRs tHTTPPasswordMgrcBs8eZdZdZdZedZdZRS(cCs h|_dS(N(tpasswd(R((s/sys/lib/python/urllib2.pyR sc Cst|to |g}n||ijoh|i|RR(RR6RRRtpwtrawtauth((s/sys/lib/python/urllib2.pyRs N( R"R#tretcompiletIR RR RR(((s/sys/lib/python/urllib2.pyR s  tHTTPBasicAuthHandlercBseZdZdZRS(t AuthorizationcCs"|i}|id|||S(Nswww-authenticate(R/R(RRR(R%R&R<R((s/sys/lib/python/urllib2.pythttp_error_401-s  (R"R#RR(((s/sys/lib/python/urllib2.pyR)stProxyBasicAuthHandlercBseZdZdZRS(sProxy-authorizationcCs"|i}|id|||S(Nsproxy-authenticate(RVR(RRR(R%R&R<R((s/sys/lib/python/urllib2.pythttp_error_4077s  (R"R#RR(((s/sys/lib/python/urllib2.pyR3scCstiido-td}|i|}|i|SnGg}t|D]}|tti ddqQ~}di |SdS(sReturn n random bytes.s /dev/urandomiiR-N( tosRtexistsRRRtrangetchrtrandomt randrangetjoin(tntftsRRtL((s/sys/lib/python/urllib2.pyt randombytesAs  9tAbstractDigestAuthHandlercBsSeZddZdZdZdZdZdZdZ dZ RS( cCsH|djo t}n||_|ii|_d|_d|_dS(Ni(RRRRtretriedt nonce_count(RR((s/sys/lib/python/urllib2.pyR Zs     cCs d|_dS(Ni(R-(R((s/sys/lib/python/urllib2.pytreset_retry_countbscCs|i|d}|idjo"t|idd|dn|id7_|o;|id}|idjo|i||SqndS(Niisdigest auth failediitdigest(R`RR-R$R/tsplitR4tretry_http_digest_auth(RRR6RR<RR((s/sys/lib/python/urllib2.pyRescCs|idd\}}tt|}|i||}|o^d|}|ii|id|jodSn|i|i||i i |}|SndS(NRis Digest %s( R1tparse_keqv_listtparse_http_listtget_authorizationR<R`RRR]RR(RRRttokent challengetchaltauth_valtresp((s/sys/lib/python/urllib2.pyR2vs cCs<tid|i|titdfi}|d S(Ns %s:%s:%s:%sii(thashlibtsha1R.ttimetctimeR+t hexdigest(Rtnoncetdig((s/sys/lib/python/urllib2.pyt get_cnoncesc CsKyK|d}|d}|id}|idd}|idd}Wntj o dSnX|i|\}} |djodSn|ii||i\} } | djodSn|io|i|i |} nd} d| || f} d|i |i f}|d joc|i d 7_ d |i }|i |}d ||||||f}| || |}n7|djo)| || d|||f}nd | |||i |f}|o|d|7}n| o|d| 7}n|d|7}|o|d||f7}n|S(NRR@tqopt algorithmtMD5topaques%s:%s:%ss%s:%sRis%08xs%s:%s:%s:%s:%ss>username="%s", realm="%s", nonce="%s", uri="%s", response="%s"s , opaque="%s"s , digest="%s"s, algorithm="%s"s, qop=auth, nc=%s, cnonce="%s"(R`RtKeyErrortget_algorithm_implsRRR/RNtget_entity_digestRQRORWR.RB(RRR8RR@RCRDRFtHtKDRRtentdigtA1tA2tncvaluetcnoncetnoncebittrespdigR((s/sys/lib/python/urllib2.pyR5sN    !      ) csM|djo dn|djo dnfd}|fS(NREcSsti|iS((R;tmd5R?(tx((s/sys/lib/python/urllib2.pyRstSHAcSsti|iS((R;R<R?(RT((s/sys/lib/python/urllib2.pyRscsd||fS(s%s:%s((R)td(RJ(s/sys/lib/python/urllib2.pyRs((RRDRK((RJs/sys/lib/python/urllib2.pyRHs     cCsdS(N(R(RRR8((s/sys/lib/python/urllib2.pyRIsN( R"R#RR R/RR2RBR5RHRI(((s/sys/lib/python/urllib2.pyR,Os    8 tHTTPDigestAuthHandlercBs#eZdZdZdZdZRS(sAn authentication protocol defined by RFC 2069 Digest authentication improves on basic authentication because it does not transmit passwords in the clear. RicCs?ti|id}|id|||}|i|S(Niswww-authenticate(R0R/RR/(RRR(R%R&R<R6tretry((s/sys/lib/python/urllib2.pyRs   (R"R#R+RRR(((s/sys/lib/python/urllib2.pyRWstProxyDigestAuthHandlercBseZdZdZdZRS(sProxy-AuthorizationicCs2|i}|id|||}|i|S(Nsproxy-authenticate(RVRR/(RRR(R%R&R<R6RX((s/sys/lib/python/urllib2.pyRs    (R"R#RRR(((s/sys/lib/python/urllib2.pyRYstAbstractHTTPHandlercBs/eZddZdZdZdZRS(icCs ||_dS(N(t _debuglevel(Rt debuglevel((s/sys/lib/python/urllib2.pyR scCs ||_dS(N(R[(Rtlevel((s/sys/lib/python/urllib2.pytset_http_debuglevelsc Cs8|i}|ptdn|iob|i}|idp|iddn|idp|iddt|qnt|i\}}t |\}}|idp|id|p|nxJ|i i D]<\}} |i }|i|p|i|| qqW|S(Ns no host givens Content-types!application/x-www-form-urlencodedsContent-lengths%dR.( RVRRNRQR_R]RRRWRRRhR[( RR5R6RRtseltsel_hosttsel_pathRJRC((s/sys/lib/python/urllib2.pyt do_request_s,      c Cs8|i}|ptdn||}|i|it|i}|i|id|d.s(RVRtset_debuglevelR[RR<RcR?R=R5RORWRt getresponsetsocketRsRtrecvt _fileobjectR}RR&R/tstatusR%R( Rt http_classRR6RR<RterrR(R:((s/sys/lib/python/urllib2.pyRps*   %   (R"R#R R^RbRp(((s/sys/lib/python/urllib2.pyRZs   RcBseZdZeiZRS(cCs|iti|S(N(RpRtHTTPConnection(RR((s/sys/lib/python/urllib2.pyt http_openKs(R"R#RoRZRbt http_request(((s/sys/lib/python/urllib2.pyRIs RRcBseZdZeiZRS(cCs|iti|S(N(RpRtHTTPSConnection(RR((s/sys/lib/python/urllib2.pyt https_openSs(R"R#RrRZRbt https_request(((s/sys/lib/python/urllib2.pyRQs tHTTPCookieProcessorcBs2eZddZdZdZeZeZRS(cCs6ddk}|djo|i}n||_dS(Ni(t cookielibRt CookieJart cookiejar(RRwRu((s/sys/lib/python/urllib2.pyR Ys  cCs|ii||S(N(Rwtadd_cookie_header(RR5((s/sys/lib/python/urllib2.pyRp_scCs|ii|||S(N(Rwtextract_cookies(RR5Rt((s/sys/lib/python/urllib2.pyRcsN(R"R#RR RpRRsR(((s/sys/lib/python/urllib2.pyRtXs    RcBseZdZRS(cCs |i}td|dS(Nsunknown url type: %s(RTR(RRR:((s/sys/lib/python/urllib2.pyRks (R"R#R(((s/sys/lib/python/urllib2.pyRjscCsph}xc|D][}|idd\}}|ddjo"|ddjo|dd!}n|||Parse list of key=value strings where keys are not duplicated.t=iit"i(R1(tltparsedtelttktv((s/sys/lib/python/urllib2.pyR3os"cCsg}d}t}}x|D]}|o||7}t}qn|oB|djo t}qn|djo t}n||7}qn|djo|i|d}qn|djo t}n||7}qW|o|i|ng}|D]}||iq~S(spParse lists as described by RFC 2068 Section 2. In particular, parse comma-separated lists where the elements of the list may include quoted-strings. A quoted-string could contain a comma. A non-quoted string could have quotes in the middle. Neither commas nor quotes count if they are escaped. Only double-quotes count, not single-quotes. R-s\R{t,(ReR}R|R(R)trestparttescapeRtcurR((s/sys/lib/python/urllib2.pyR4ys6           RcBs)eZdZdZdZdZRS(cCs_|i}|d djo1|dd!djod|_|ii|Sn|i|SdS(Nis//iRtftp(RWR:RRtopen_local_file(RRR((s/sys/lib/python/urllib2.pyt file_opens  % cCsttidjo]y+tidtitift_Wqmtij otidft_qmXntiS(NR(RtnamesRRht gethostbynamet gethostnametgaierror(R((s/sys/lib/python/urllib2.pyt get_namess c Cs%ddk}ddk}|i}|i}t|}ti|}|i}|ii |i dt } |i |d} t itd| pd|| f} |ot|\}} n| p$| o=ti||ijo!tt|d| d|SntddS( Nitusegmtis6Content-type: %s Content-length: %d Last-modified: %s s text/plaintrbsfile:sfile not on local host(t email.Utilst mimetypesRVRWRR tstattst_sizetUtilst formatdatetst_mtimeR}t guess_typet mimetoolstMessageRRRhRRRRR( RRtemailRR6tfilet localfiletstatstsizetmodifiedtmtypeR<R;((s/sys/lib/python/urllib2.pyRs&       $N(R"R#RRRRR(((s/sys/lib/python/urllib2.pyRs  RcBseZdZdZRS(cCsddk}ddk}|i}|p tdnt|\}}|djo |i}n t|}t|\}}|ot |\}}nd}t |}t |pd}t |pd}yt i |}Wn$t i j o}t|nXt|i\} } | id} tt | } | d | d} } | o| d o| d} ny3|i||||| } | odpd }xP| D]H}t|\}}|id jo|djo|i}qqW| i| |\}}d}|i|id}|o|d|7}n|dj o|djo|d|7}nt|}ti|}t|||iSWn4|ij o%}td|fti dnXdS(Nis ftp errors no host givenR-RiiRtDR:tatARRVsContent-type: %s sContent-length: %d i(s ftp errors no host given(RRRRRVR(!tftplibRRVtIOErrorRRtFTP_PORTRxR RRRhRRsRR RWR1tmapt connect_ftpRR4tuppertretrfileRR/RRRRt all_errorstsystexc_info(RRRRR6R;RRR&RtattrstdirsRtfwR:RIRCR(tretrlenR<Rtsf((s/sys/lib/python/urllib2.pytftp_opens^          cCst|||||}|S(N(R (RRRR6R;RR((s/sys/lib/python/urllib2.pyRs(R"R#RR(((s/sys/lib/python/urllib2.pyRs 5tCacheFTPHandlercBs5eZdZdZdZdZdZRS(cCs1h|_h|_d|_d|_d|_dS(Nii<i(tcachettimeouttsoonesttdelayt max_conns(R((s/sys/lib/python/urllib2.pyR s     cCs ||_dS(N(R(Rtt((s/sys/lib/python/urllib2.pyt setTimeoutscCs ||_dS(N(R(RR((s/sys/lib/python/urllib2.pyt setMaxConnsscCs|||di|f}||ijoti|i|i|Gst             d     e 'S H%@ *   X ++;.