Ϫfs\dZddlZddlZddlZddlZddlmZddlmZddl m Z m Z ddl m ZddlmZddlmZdd lmZdd lmZmZdd lmZmZdd lmZdd lmZmZm Z ddl!m"Z"m#Z#ddl$m%Z%ddl&m'Z'm(Z(ddl)m*Z*m+Z+m,Z,m-Z-ddl.m/Z/ddl0m1Z1dZ2gdZ3e%eddddddde%eddddddde*jhZ5e*jlZ7dZ8dZ dZ9ee+jtGd d!e'e*jvejxZ;ee+jzGd"d#Z>ee+j~Gd$d%Z@Gd&d'ZAGd(d)ejxZBe#d*ejZCeejGd+d,e*jZFy)-a This is a web server which integrates with the twisted.internet infrastructure. @var NOT_DONE_YET: A token value which L{twisted.web.resource.IResource.render} implementations can return to indicate that the application will later call C{.write} and C{.finish} to complete the request, and that the HTTP connection should be left open. @type NOT_DONE_YET: Opaque; do not depend on any particular type for this value. N)hexlify)escape)ListOptional)quote) implementer)Version) copyright)address interfaces) AlreadyCalledAlreadyCancelled)Logger) componentsfailurereflect) nativeString networkString)deprecatedModuleAttribute)Copyable ViewPoint)httpiwebresourceutil)UnsupportedMethod)unquote)supportedMethodsRequestSessionSiteversion NOT_DONE_YETGzipEncoderFactoryTwisted z4Please use twisted.web.http.datetimeToString insteadztwisted.web.serverdate_time_stringz4Please use twisted.web.http.stringToDatetime insteadstring_date_time)GETHEADsPOSTc\t|jdg|i|jdS)Ncharmap)_quotedecodeencode)stringargskwargss 4/usr/lib/python3/dist-packages/twisted/web/server.pyrrKs+ &-- * s r4sibLinkzRequest.sibLinks) == &/47 7Kr5ct|j}|dkDr |dz dz|zS|dk(r|St|jr$|jdr|jddz|zS|S)z Return the text that links to a child of the requested resource. @param name: The child resource @type name: C{bytes} @return: A relative URL. @rtype: C{bytes} rr`/)rarFrE)rKr>lpps r4 childLinkzRequest.childLinksn$--  71W&$. . AXK4<< T\\"%5||B'$.55 r5c |jjj}|||_y#t$r#t j j||YywxYw)a0 Called when HTTP channel got length of content in this request. This method is not intended for users. @param length: The length of the request body, as indicated by the request headers. L{None} if the request headers do not indicate a length. N)rOrQgetContentFilerPAttributeErrorrr gotLength)rKlengthris r4rkzRequest.gotLengthsO 2!\\..==N*&1DL 1 LL " "4 0 1s 0)AAc|jj|_|jdt|jdt j g|_ttt|jddjd|_ |jdk(r|jy |jj|}tj j#|r|j%|}|||_|j)|y#t*$r&|j-t/j0YywxYw)z Process a request. Find the addressed resource in this request's L{Site}, and call L{self.render()} with it. @see: L{Site.getResourceFor()} sserversdaterNre*)rOrQ setHeaderr#rdatetimeToStringrErZmaprpathsplitrF _handleStargetResourceForr_IEncodingResource providedBy getEncoder_encoderrender BaseExceptionprocessingFailedrFailure)rKresrcencoders r4processzRequest.processsLL%%  y'* w 5 5 78 S$))AB-*=*=d*CDE  99       5II,,T2E**55e<**40&$+DM KK  5  ! !'//"3 4 5s8A%D,E  E c|js|jtjtjfv}|j j d}|j j d}|xr|ddk(}|r7|5|j)|s'|j jd|jg|jsH|jr|jj|}tjj||yy)z Write data to the transport (if not responding to a HEAD request). @param data: A string to write to the response. @type data: L{bytes} content-typecontent-lengthr0N)startedWritingcoder NOT_MODIFIED NO_CONTENTresponseHeaders getRawHeadersrD setRawHeaders _inFakeHeadryr0r write)rKdataneedsCT contentType contentLengthcontentLengthZeros r4rz Request.writes"" ii(9(94??'KKG..<<_MK 00>>?PQM - L=3Ct3K '++7)$$22#d&=&=%>}}}}++D1 LL  tT * r5c|jr<|jj}|r tjj ||tjj|S)zH Override C{http.Request.finish} for possible encoding. )ryfinishrr rrKrs r4rzRequest.finish sI ===='')D ""4.||""4((r5c ~ |j|}|tury t/|t0st#j$t&j2ddt5j6t9j:|zdzdzt5j6t9j:|zdzdzt5j6t9j:|zj|}|jdk(r]t|dkDr=|jj d|| |jddt|fz|jd n0|jddt|fz|j||jy #t$r}|j}|jdk(rd|vr|jj d|d|_d|_|j|}|tur|jj d|n|jddt|fzd |_d|_|jd |jYd }~y |jtvr|jd d j|dtt|j t|jt|dkDxrdxsddj|Dcgc] }t|ncc}wc}dz}t#j$t&j(d|}|j|}n\t#j$t&j*ddt|jj-dd}|j|}Yd }~d }~wwxYw)!ah Ask a resource to render itself. If the resource does not support the requested method, generate a C{NOT IMPLEMENTED} or C{NOT ALLOWED} response. @param resrc: The resource to render. @type resrc: L{twisted.web.resource.IResource} @see: L{IResource.render()} r+r*z,Using GET to fake a HEAD request for {resrc})r~TzBTried to fake a HEAD request for {resrc}, but it got away from me.r%dFr5NAllows, zzYour browser approached me (at %(URI)s) with the method "%(method)s". I only allow the method%(plural)s %(allowed)s here.rsz, )URImethodpluralallowedzMethod Not AllowedzHuh?zI don't know how to treat a r-z request.zRequest did not return bytesz Request: z
z Resource: zValue: rzbWarning: HEAD request {slf} for resource {resrc} is returning a message body. I think I'll eat it.)slfr~)rzrallowedMethodsr_loginforr$rorarrrjoinrrurir_UnsafeErrorPager NOT_ALLOWEDNOT_IMPLEMENTEDr/r9bytesINTERNAL_SERVER_ERRORr_PREr safe_repr)rKr~bodyerr]repages r4rzzRequest.rendersF: *<<%Dx <  $&,,**.))G--d345  ))G--e45 6  ))G--d345 fTl  ;;' !4y1} F  0%3t9,2FG JJsO NN,es4yl.B C JJt  u!8 *--N w&V~-E  B%% #' ||D)<'IINN/##NN#4es4yl6JK#( %  3 {{/0xN)CDB &l488&<=".t{{";$'$7!$;#D"K#'99~-V!l1o-V-V#W !11$$&:A||D) 11((dkk00;<? ||D)q8 *s,F N<CN72B N7;L B$N77N<c|jjd||jjrdt j |zdz}nd}|j tj|jdd|jdd t|fz|j||j|S) aO Finish this request with an indication that processing failed and possibly display a traceback. @param reason: Reason this request has failed. @type reason: L{twisted.python.failure.Failure} @return: The reason passed to this method. @rtype: L{twisted.python.failure.Failure} r)rsweb.Server Traceback (most recent call last)web.Server Traceback (most recent call last): s s_Processing FailedProcessing FailedrrCrr) rrrQdisplayTracebacksr formatFailuresetResponseCoderrrorarr)rKreasonrs r4r|zRequest.processingFaileds "f- 99 & &5$$V, - * * :  T778  5 (%3t9,*>? 4  r5c&|j|y)z(Remote version of write; same interface.N)r)rKr\rs r4 view_writezRequest.view_writes 4r5c$|jy)z)Remote version of finish; same interface.N)rrKr\s r4 view_finishzRequest.view_finishs  r5c ,|j||fi|y)z,Remote version of addCookie; same interface.N) addCookie)rKr\kvr3s r4view_addCookiezRequest.view_addCookiesq!&v&r5c(|j||y)z,Remote version of setHeader; same interface.N)ro)rKr\rrs r4view_setHeaderzRequest.view_setHeaders q!r5c&|j|y)z2Remote version of setLastModified; same interface.N)setLastModified)rKr\whens r4view_setLastModifiedzRequest.view_setLastModifieds T"r5c&|j|y)z*Remote version of setETag; same interface.N)setETag)rKr\tags r4 view_setETagzRequest.view_setETags Sr5c(|j||y)zD Remote version of setResponseCode; same interface. N)r)rKr\rmessages r4view_setResponseCodezRequest.view_setResponseCodes T7+r5c:|jt||y)zbRemote version of registerProducer; same interface. (requires a remote producer.) N)registerProducer_RemoteProducerWrapper)rKr\producer streamings r4view_registerProducerzRequest.view_registerProducers 4X> Jr5c$|jyrH)unregisterProducerrs r4view_unregisterProducerzRequest.view_unregisterProducers !r5cR|jr |jS|jS)a If a session has already been created or looked up with L{Request.getSession}, this will return that object. (This will always be the session that matches the security of the request; so if C{forceNotSecure} is used on a secure request, this will not return that session.) @return: the session attribute @rtype: L{Session} or L{None} )isSecure_secureSession_insecureSessionrKs r4sessionzRequest.sessions% ==?&& &(( (r5c&|jxr| }|sd}d}nd}d}t||}| |j|dj |g|j z}|j|}|r |jj|}|s9|jj}|j||jd|t||||r|j|S|S#ttf$rd}YwxYw#t$rYwxYw) a Check if there is a session cookie, and if not, create it. By default, the cookie with be secure for HTTPS requests and not secure for HTTP requests. If for some reason you need access to the insecure cookie from a secure request you can set C{forceNotSecure = True}. @param forceNotSecure: Should we retrieve a session that will be transmitted over HTTP, even if this L{Request} was delivered over HTTPS? @type forceNotSecure: L{bool} sTWISTED_SESSIONrsTWISTED_SECURE_SESSIONrN_re)rrsecure)rgetattrtouchr rrsitepath getCookierQ getSessionKeyError makeSessionruidsetattr getComponent) rKsessionInterfaceforceNotSecurer cookieStringsessionAttributer cookiename sessionCookies r4rzRequest.getSessions 7%7-L1 4L/ $ 01     ?L>DMM#ABJ NN:6M"ii22=AG))//1z7;;T&Q&0 ''(89 9/"#34   s#C-5D-DD DDc d|jj}|jrd}nd}||k(rd}nd|z}td|jxrdxsddt |j |d}d j |Dcgc]}t|d c}}||zScc}w) NiPrz:%drrz:///rer5)safe)getHostr<rrrgetRequestHostnamerr)rKrEr<defaulthostportprefixsegmentrrs r4 _prePathURLzRequest._prePathURLs||~"" ==?GG 7?Ht|H 'C-2-T4467   yy'Jw%c2JK}Ks B-c8|j|jSrH)rrErs r4 prePathURLzRequest.prePathURL,s --r5cDddlm}|jj|S)Nr)urlpath)twisted.pythonrURLPath fromRequest)rKrs r4rzRequest.URLPath/s***400r5cN|j|jdd}||_y)z_ Remember the currently-processed part of the URL for later recalling. Nrd)rrE appRootURL)rKurls r4rememberRootURLzRequest.rememberRootURL4s& t||CR01r5c|jS)zn Get a previously-remembered URL. @return: An absolute URL. @rtype: L{bytes} )rrs r4 getRootURLzRequest.getRootURL<sr5c|jdk(r |jtjn1|jtj|j dd|j dd|j y)a Handle receiving a request whose path is '*'. RFC 7231 defines an OPTIONS * request as being something that a client can send as a low-effort way to probe server capabilities or readiness. Rather than bother the user with this, we simply fast-path it back to an empty 200 OK. Any non-OPTIONS verb gets a 405 Method Not Allowed telling the client they can only use OPTIONS. sOPTIONSrsContent-LengthrN)rrrOKrrorrs r4rtzRequest._handleStarEs^ ;;* $   )  !1!1 2 NN8Z 0 ($/ r5rH)NF)0__name__ __module__ __qualname____doc__rDrr__annotations__rQrrErrF __pychecker__rryrrrIr^rbrgrkrrrrzr|rrrrrrrrrrrpropertyrrrrrrrrtr5r4r r Xs +76 DJ%)GXd5k ")&*HhtE{#*(MKH 8D0. *2""5H$+L)hT!F'#, K " N )) 5n*.1 r5r c>eZdZdZej dZdZdZy)r%z~ @cvar compressLevel: The compression level used by the compressor, default to 9 (highest). @since: 12.3 s(:?^|[\s,])gzip(:?$|[\s,]) c`dj|jjdg}|jj |rh|j jd}|rdj|dgz}nd}|j j d|gt|j|Sy)zo Check the headers if the client accepts gzip encoding, and encodes the request if so. ,saccept-encodingscontent-encodingsgzipN) rrUr_gzipCheckRegexsearchrr _GzipEncoder compressLevel)rKrequest acceptHeadersencodings r4encoderForRequestz$GzipEncoderFactory.encoderForRequestgs   " " 0 01CR H     & &} 5..<<=PQH99X %9:"  # # 1 12Ez R 2 2G< < 6r5N) rrr r recompilerrrrr5r4r%r%[s$!bjj!?@OM=r5r%c&eZdZdZdZdZdZdZy)rz An encoder which supports gzip. @ivar _zlibCompressor: The zlib compressor instance used to compress the stream. @ivar _request: A reference to the originating request. @since: 12.3 Nctj|tjdtjz|_||_y)N)zlib compressobjDEFLATED MAX_WBITS_zlibCompressor_request)rKrrs r4rIz_GzipEncoder.__init__s2#// 4=="t~~*=   r5c|jjs%|jjjd|jj |S)zR Write to the request, automatically compressing data on the fly. r)r%rr removeHeaderr$compressrs r4r0z_GzipEncoder.encodesC}}++ MM ) ) 6 67H I##,,T22r5cH|jj}d|_|S)zf Finish handling the request request, flushing any data from the zlib buffer. N)r$flush)rKremains r4rz_GzipEncoder.finishs% %%++-# r5)rrr r r$rIr0rrr5r4rrzs O 3r5rceZdZdZy)rc|jd|_|jd|_|jd|_y)NresumeProducingpauseProducing stopProducing) remoteMethodr.r/r0)rKrSs r4rIz_RemoteProducerWrapper.__init__s=%223DE$112BC#00Ar5N)rrr rIrr5r4rrsBr5rcDeZdZdZdZdZd fd ZdZdZdZ dZ xZ S) r!a A user's session with a system. This utility class contains no functionality, but is used to represent a session. @ivar site: The L{Site} that generated the session. @type site: L{Site} @ivar uid: A unique identifier for the session. @type uid: L{bytes} @ivar _reactor: An object providing L{IReactorTime} to use for scheduling expiration. @ivar sessionTimeout: Time after last modification the session will expire, in seconds. @type sessionTimeout: L{float} @ivar lastModified: Time the C{touch()} method was last called (or time the session was created). A UNIX timestamp as returned by L{IReactorTime.seconds()}. @type lastModified: L{float} iNct|| |j}||_||_||_g|_|ji|_y)z Initialize a session with a unique ID for that session. @param reactor: L{IReactorTime} used to schedule expiration of the session. If C{None}, the reactor associated with I{site} is used. N) superrIreactor_reactorrQrexpireCallbacksrsessionNamespaces)rKrQrr5 __class__s r4rIzSession.__init__sL  ?llG  ! !#r5cn|jj|j|j|_y)zF Start expiration tracking. @return: L{None} N)r6 callLatersessionTimeoutexpire _expireCallrs r4startCheckingExpirationzSession.startCheckingExpirations'  ==2243F3F Tr5c:|jj|y)zJ Call this callback when the session expires or logs out. N)r7append)rKcallbacks r4notifyOnExpirezSession.notifyOnExpires ##H-r5c|jj|j=|jD] }| g|_|jr=|jj r"|jj d|_yyy)z/ Expire/logout of the session. N)rQsessionsrr7r>activecancel)rKcs r4r=zSession.expiresx II  txx (%% A C !    0 0 7 7 9    # # %#D !: r5c|jj|_|j&|jj |j yy)zN Mark the session as modified, which resets expiration timer. N)r6seconds lastModifiedr>resetr<rs r4rz Session.touchsD!MM113    '    " "4#6#6 7 (r5rH) rrr r r<r>rIr?rCr=r __classcell__r9s@r4r!r!s.2NK$&U. $8r5r!z TwistedWeb/ceZdZdZdZeZdZeZ dZ e jZ dfd ZdZdZdZd Zd Zfd ZdZd Zd ZdZdZxZS)r"a* A web site: manage log, sessions, and resources. @ivar requestFactory: A factory which is called with (channel) and creates L{Request} instances. Default to L{Request}. @ivar displayTracebacks: If set, unhandled exceptions raised during rendering are returned to the client as HTML. Default to C{False}. @ivar sessionFactory: factory for sessions objects. Default to L{Session}. @ivar sessions: Mapping of session IDs to objects returned by C{sessionFactory}. @type sessions: L{dict} mapping L{bytes} to L{Session} given the default C{sessionFactory} @ivar counter: The number of sessions that have been generated. @type counter: L{int} @ivar sessionCheckTime: Deprecated and unused. See L{Session.sessionTimeout} instead. rFicTt||i|i|_||_|||_yy)a @param resource: The root of the resource hierarchy. All request traversal for requests received by this factory will begin at this resource. @type resource: L{IResource} provider @param requestFactory: Overwrite for default requestFactory. @type requestFactory: C{callable} or C{class}. @see: L{twisted.web.http.HTTPFactory.__init__} N)r4rIrErrequestFactory)rKrrQr2r3r9s r4rIz Site.__init__"s8 $)&)    %"0D  &r5cddlm}|jtjj |tjj |S)Nr)logfile)rrSLogFileosrrbasenamedirname)rKrrrSs r4 _openLogFilezSite._openLogFile3s2*rww//5rwwt7LMMr5cD|jj}i|d<|S)NrE)rVrW)rKds r4 __getstate__zSite.__getstate__8s" MM   * r5c^|jdz|_t|jdS)zP (internal) Generate an opaque, unique ID for a user's session. r )counterr_entropyrs r4_mkuidz Site._mkuid=s(||a' t}}R())r5c|j}|j||x}|j|<|j|S)zU Generate a new Session instance, and store it for future reference. )r`sessionFactoryrEr?)rKrrs r4rzSite.makeSessionDs@kkm'+':':4'EE$--$'')r5c |j|S)z Get a previously generated session. @param uid: Unique ID of the session. @type uid: L{bytes}. @raise KeyError: If the session is not found. )rE)rKrs r4rzSite.getSessionMs}}S!!r5cVt||}|j|_||_|S)z; Generate a channel attached to this site. )r4 buildProtocolrQrQ)rKr@rOr9s r4rezSite.buildProtocolXs.''-!%!4!4 r5ch|j|jdz|jy)z@ Redirect because a Site is always a directory. reN)redirectrrrKrs r4rzz Site.rendercs* ++-45r5cH||_|jj||S)z7 Emulate a resource's getChild method. )rQrgetChildWithDefault)rKpathElrs r4rjzSite.getChildWithDefaultjs" }}00AAr5c||_tj|j|_t j |j|S)z Get a resource for a request. This iterates through the resource hierarchy, calling getChildWithDefault on each resource it finds for a path element, stopping when it hits an element where isLeaf is true. )rQrWrErrgetChildForRequestrhs r4ruzSite.getResourceForqs9  99W__5**4=='BBr5cPdg}tjr|jdd|S)z2 Protocols this server can speak. shttp/1.1rsh2)r H2_ENABLEDinsert)rK baseProtocolss r4acceptableProtocolszSite.acceptableProtocolss(% ??  E *r5rH)rrr r r^r rQrr!rbsessionCheckTimerUurandomr_rIrXr[r`rrreisLeafrzrjrurrrMrNs@r4r"r"so.GNNzzH1"N  * "FB C r5r")Gr rWrUrr binasciirhtmlrtypingrr urllib.parserr.zope.interfacer incrementalr twistedr twisted.internetr r twisted.internet.errorr rtwisted.loggerrrrrrtwisted.python.compatrrtwisted.python.deprecatertwisted.spread.pbrr twisted.webrrrrtwisted.web.errorrtwisted.web.httprr$__all__rpr(stringToDatetimer)rrAIRequestr rJ_IRequestEncoderFactoryr%_IRequestEncoderrrr!r#IProtocolNegotiationFactory HTTPFactoryr"rr5r4rs  !(&0B!77=>122/$   Ir1a :   Ir1a :  ((((.O T]]h j&>&>D T ) )*==+=< T " "#%%$%PBBR8j&&R8j +i&7&7%89 : Z 3 34F4  F5Fr5