úέŞöÿ²      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹Œ‘’“”•–—˜™š›œŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖרÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN O P Q R S T U V W X Y Z [ \ ] ^ _ ` a bcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰ Š ‹ Œ     ‘ ’ “ ” • – — ˜ ™ š › œ   Ÿ   ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± Safe<V2?Print out the provided debug message prefixed by the thread ID.Example: ?ghci> debug "Some debug message" [ 225] Some debug message 1Print out the error message corresponding to the   value returned by  q together with any additional information provided by the user (usually the location where the error occurred).Example: ghci> debugErrno "pathtoSource.hs:34" [ 323] pathtoSource.hs:34: failed (Success) NoneYß_A key-value map that represents a collection of HTTP header fields. Keys are case-insensitive.*An empty collection of HTTP header fields.Example: ghci> H. H {unH = []} 2Is a given collection of HTTP header fields empty?Example: 'ghci> :set -XOverloadedStrings ghci> H. H. True ghci> H. $ H. [("Host", "localhost")] False ADoes this collection of HTTP header fields contain a given field?Example: 'ghci> :set -XOverloadedStrings ghci> H. "host" $ H.& [("Host", "localhost")] True ghci> H. "Accept" $ H. [("Host", "localhost")] False /Look up the value of a given HTTP header field.Example: 'ghci> :set -XOverloadedStrings ghci> H. "host" $ H.2 [("Host", "localhost")] Just "localhost" ghci> H. "Accept" $ H.! [("Host", "localhost")] Nothing {Look up the value of a given HTTP header field or return the provided default value when that header field is not present.Example: 2ghci> :set -XOverloadedStrings ghci> let hdrs = H.! [("Host", "localhost")] ghci> H./ "host" "127.0.0.1" $ hdrs "localhost" ghci> H.+ "Accept" "text/plain" $ hdrs "text/plain" xInsert a key-value pair into the headers map. If the key already exists in the map, the values are catenated with ", ".Example: 2ghci> :set -XOverloadedStrings ghci> let hdrs = H. "Accept" "text/plain" $ H.8 ghci> hdrs H {unH = [("accept","text/plain")]} ghci> H.K "Accept" "text/html" $ hdrs H {unH = [("accept","text/plain,text/html")]} kInsert a key-value pair into the headers map, without checking whether the header already exists. The key must; be already case-folded, or none of the lookups will work!Example: 2ghci> :set -XOverloadedStrings ghci> let hdrs = H.  "accept" "text/plain" $ H.D ghci> hdrs H {unH = [("accept","text/plain")]} ghci> let hdrs' = H. m "accept" "text/html" $ hdrs ghci> hdrs' H {unH = [("accept","text/html"), ("accept","text/plain")]} ghci> H.! "accept" hdrs' Just "text/html" PSet the value of a HTTP header field to a given value, replacing the old value.Example: 'ghci> :set -XOverloadedStrings ghci> H.  "accept" "text/plain" $ H.- H {unH = [("accept","text/plain")]} ghci> H.  "accept" "text/html" $ H.? [("Accept", "text/plain")] H {unH = [("accept","text/html")]} ODelete all key-value pairs associated with the given key from the headers map.Example: 'ghci> :set -XOverloadedStrings ghci> H.  "accept" $ H.) [("Accept", "text/plain")] H {unH = []} =Strict left fold over all key-value pairs in the headers map.Example: ,ghci> :set -XOverloadedStrings ghci> import  Data.Monoid ghci> let hdrs = H.y [("Accept", "text/plain"), ("Accept", "text/html")] ghci> let f (cntr, acc) _ val = (cntr+1, val <> ";" <> acc) ghci> H. , f (0, "") hdrs (2,"text/html;text/plain;") Same as  #, but the key parameter is of type ² instead of ³ ²%. The key is case-folded (lowercase).7Right fold over all key-value pairs in the headers map.Example: ,ghci> :set -XOverloadedStrings ghci> import  Data.Monoid ghci> let hdrs = H.y [("Accept", "text/plain"), ("Accept", "text/html")] ghci> let f _ val (cntr, acc) = (cntr+1, val <> ";" <> acc) ghci> H., f (0, "") hdrs (2,"text/plain;text/html;") Same as #, but the key parameter is of type ² instead of ³ ²%. The key is case-folded (lowercase). Convert a $ value to a list of key-value pairs.Example: ighci> :set -XOverloadedStrings ghci> let l = [("Accept", "text/plain"), ("Accept", "text/html")] ghci> H. . H.6 $ l [("accept","text/plain"),("accept","text/html")] Build a & value from a list of key-value pairs.Example: 'ghci> :set -XOverloadedStrings ghci> H.p [("Accept", "text/plain"), ("Accept", "text/html")] H {unH = [("accept","text/plain"),("accept","text/html")]} Like E, but the keys are assumed to be already case-folded (in lowercase).Like #, but does not convert the keys to ³ ²-, so key comparisons will be case-sensitive.   ´µNone;=CQV`IRepresents an HTTP response.­We will need to inspect the content length no matter what, and looking up "content-length" in the headers and parsing the number out of the text will be too expensive.Returns the HTTP status code.Example: ghci> rspStatus b 200 +Returns the HTTP status explanation string.Example: ghci> rspStatusReason b OK 4If true, we are transforming the request body with transformRequestBody+output body is a function that writes to a ¶ stream Noutput body is sendfile(), optional second argument is a byte range to send"?Contains all of the information about an incoming HTTP request.$BThe server name of the request, as it came in from the request's Host: header.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.Map° as M ghci> :{ ghci| rq <- T.buildRequest $ do ghci| T.get "/foo/bar" M.empty ghci| T.setHeader "host" "example.com" ghci| :} ghci> rqHostName rq "example.com" %The remote IP address.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapV as M ghci> rqClientAddr `fmap` T.buildRequest (T.get "/foo/bar" M.empty) "127.0.0.1" &The remote TCP port number.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapR as M ghci> rqClientPort `fmap` T.buildRequest (T.get "/foo/bar" M.empty) "60000" '&The local IP address for this request.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapV as M ghci> rqServerAddr `fmap` T.buildRequest (T.get "/foo/bar" M.empty) "127.0.0.1" (§Returns the port number the HTTP server is listening on. This may be useless from the perspective of external requests, e.g. if the server is running behind a proxy.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapO as M ghci> rqServerPort `fmap` T.buildRequest (T.get "/foo/bar" M.empty) 8080 )fReturns the HTTP server's idea of its local hostname, including port. This is as configured with the Config object at startup.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapY as M ghci> rqLocalHostname `fmap` T.buildRequest (T.get "/foo/bar" M.empty) "localhost" *Returns True if this is an HTTPS session.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapN as M ghci> rqIsSecure `fmap` T.buildRequest (T.get "/foo/bar" M.empty) False +Contains all HTTP  associated with this request.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.Maph as M ghci> rqHeaders `fmap` T.buildRequest (T.get "/foo/bar" M.empty) H {unH = [("host","localhost")]} ,Actual body of the request.- Returns the Content-Length of the HTTP request body.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapU as M ghci> rqContentLength `fmap` T.buildRequest (T.get "/foo/bar" M.empty) Nothing . Returns the HTTP request method.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapJ as M ghci> rqMethod `fmap` T.buildRequest (T.get "/foo/bar" M.empty) GET /,Returns the HTTP version used by the client.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapM as M ghci> rqVersion `fmap` T.buildRequest (T.get "/foo/bar" M.empty) (1,1) 0JReturns a list of the cookies that came in from the HTTP request headers.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapJ as M ghci> rqCookies `fmap` T.buildRequest (T.get "/foo/bar" M.empty) [] 1Handlers can be hung on a URI^ "entry point"; this is called the "context path". If a handler is hung on the context path "/foo/", and you request  "/foo/bar", the value of 1 will be "bar".The following identity holds: ÿrqURI r == S.concat [ rqContextPath r , rqPathInfo r , let q = rqQueryString r in if S.null q then "" else S.append "?" q ]Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapR as M ghci> rqPathInfo `fmap` T.buildRequest (T.get "/foo/bar" M.empty) "foo/bar" 2.The "context path" of the request; catenating 2, and 1% should get you back to the original 3 (ignoring query strings). The 2' always begins and ends with a slash ("/"k) character, and represents the path (relative to your component/snaplet) you took to get to your handler.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapO as M ghci> rqContextPath `fmap` T.buildRequest (T.get "/foo/bar" M.empty) "/" 3 Returns the URI requested by the client.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.MapM as M ghci> rqURI `fmap` T.buildRequest (T.get "/foo/bar" M.empty) "foo/bar" 4'Returns the HTTP query string for this ".Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.Map{ as M ghci> rq <- T.buildRequest (T.get "/foo/bar" (M.fromList [("name", ["value"])])) ghci> rqQueryString rq "name=value" 5(Returns the parameters mapping for this "J. "Parameters" are automatically decoded from the URI's query string and POST* body and entered into this mapping. The 5 value is thus a union of 6 and 7.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.Mapã as M ghci> :{ ghci| rq <- T.buildRequest $ do ghci| T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])] ghci| T.setQueryStringRaw "baz=quux" ghci| :} ghci> rqParams rq fromList [("baz",["qux","quux"])] 6:The parameter mapping decoded from the URI's query string.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.Mapâ as M ghci> :{ ghci| rq <- T.buildRequest $ do ghci| T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])] ghci| T.setQueryStringRaw "baz=quux" ghci| :} ghci> rqQueryParams rq fromList [("baz",["quux"])] 7|The parameter mapping decoded from the POST body. Note that Snap only auto-decodes POST request bodies when the request's  Content-Type is !application/x-www-form-urlencoded. For multipart/form-data use 3 to decode the POST request and fill this mapping.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.Mapà as M ghci> :{ ghci| rq <- T.buildRequest $ do ghci| T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])] ghci| T.setQueryStringRaw "baz=quux" ghci| :} ghci> rqPostParams rq fromList [("baz",["qux"])] 8TA type alias for the HTTP parameters mapping. Each parameter key maps to a list of ²= values; if a parameter is specified multiple times (e.g.: "GET /foo?param=bar1&param=bar2"), looking up "param" in the mapping will give you ["bar1", "bar2"].9'A datatype representing an HTTP cookie.;The name of the cookie.<The cookie's string value.=-The cookie's expiration value, if it has one.>+The cookie's "domain" value, if it has one.?The cookie path.@Tag as secure cookie?A HTTP only?B9Represents a (major, minor) version of the HTTP protocol.C(Enumerates the HTTP method values (see  5http://tools.ietf.org/html/rfc2068.html#section-5.1.1).N5A typeclass for datatypes which contain HTTP headers.OModify the datatype's headers.P6Retrieve the headers from a datatype that has headers.U$Adds a header key-value-pair to the Nj datatype. If a header with the same name already exists, the new value is appended to the headers list.Example: ghci> import qualified Snap.Types.Headers as H ghci> U "Host" "localhost" H.empty( H {unH = [("host","localhost")]} ghci> UB "Host" "127.0.0.1" it H {unH = [("host","localhost,127.0.0.1")]} V"Sets a header key-value-pair in a N` datatype. If a header with the same name already exists, it is overwritten with the new value.Example: ghci> import qualified Snap.Types.Headers as H ghci> V "Host" "localhost" H.emptyi H {unH = [("host","localhost")]} ghci> setHeader "Host" "127.0.0.1" it H {unH = [("host","127.0.0.1")]} WGets a header value out of a N datatype.Example: ghci> import qualified Snap.Types.Headers as H ghci> W "Host" $ V "Host" "localhost" H.empty Just "localhost" XLists all the headers out of a NX datatype. If many headers came in with the same name, they will be catenated together.Example: ghci> import qualified Snap.Types.Headers as H ghci> X $ V "Host" "localhost" H.empty [("host","localhost")] YClears a header value from a N datatype.Example: ghci> import qualified Snap.Types.Headers as H ghci> Y "Host" $ V "Host" "localhost" H.empty H {unH = []} Z?Equate the special case constructors with their corresponding  Method name variant.]Looks up the value(s) for the given named parameter. Parameters initially come from the request's query string and any decoded POST body (if the request's  Content-Type is !application/x-www-form-urlencodedL). Parameter values can be modified within handlers using "rqModifyParams".Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.Mapµ as M ghci> :{ ghci| rq <- T.buildRequest $ do ghci| T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])] ghci| T.setQueryStringRaw "baz=quux" ghci| :} ghci> ] "baz" rq Just ["qux","quux"] ^TLooks up the value(s) for the given named parameter in the POST parameters mapping.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.Mapµ as M ghci> :{ ghci| rq <- T.buildRequest $ do ghci| T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])] ghci| T.setQueryStringRaw "baz=quux" ghci| :} ghci> ^ "baz" rq Just ["qux"] _ULooks up the value(s) for the given named parameter in the query parameters mapping.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.Mapµ as M ghci> :{ ghci| rq <- T.buildRequest $ do ghci| T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])] ghci| T.setQueryStringRaw "baz=quux" ghci| :} ghci> _ "baz" rq Just ["quux"] `,Modifies the parameters mapping (which is a Map ByteString ByteString) in a " using the given function.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.Mapµ as M ghci> :{ ghci| rq <- T.buildRequest $ do ghci| T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])] ghci| T.setQueryStringRaw "baz=quux" ghci| :} ghci> 5, rq fromList [("baz",["qux","quux"])] ghci> 5 $ `! (M.delete "baz") rq fromList [] aLWrites a key-value pair to the parameters mapping within the given request.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Snap.Test as T ghci> import qualified Data.Mapµ as M ghci> :{ ghci| rq <- T.buildRequest $ do ghci| T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])] ghci| T.setQueryStringRaw "baz=quux" ghci| :} ghci> 5, rq fromList [("baz",["qux","quux"])] ghci> 5 $ a2 "baz" ["corge"] rq fromList [("baz", ["corge"])] b An empty .Example: ghci> b HTTP/1.1 200 OK c9Sets an HTTP response body to the given stream procedure.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified System.IO.Streams# as Streams ghci> import qualified Data.ByteString.Builder# as Builder ghci> :{ ghci| let r = cJ ghci| (out -> do ghci| Streams.write (Just $ Builder.·B "Hello, world!") out ghci| return out) ghci| b1 ghci| :} ghci> r HTTP/1.1 200 OK Hello, world! d=Sets the HTTP response status. Note: normally you would use e1 unless you needed a custom response explanation.Example: Sghci> :set -XOverloadedStrings ghci> setResponseStatus 500 "Internal Server Error" b& HTTP/1.1 500 Internal Server Error eSets the HTTP response code.Example: ghci> setResponseCode 404 b HTTP/1.1 404 Not Found fModifies a response body.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified System.IO.Streams# as Streams ghci> import qualified Data.ByteString.Builder# as Builder ghci> :{ ghci| let r = cJ ghci| (out -> do ghci| Streams.write (Just $ Builder.·B "Hello, world!") out ghci| return out) ghci| bI ghci| :} ghci> r HTTP/1.1 200 OK Hello, world! ghci> :{ ghci| let r' = fo ghci| (f out -> do ghci| out' <- f out ghci| Streams.write (Just $ Builder.·v "\nBye, world!") out' ghci| return out') r ghci| :} ghci> r' HTTP/1.1 200 OK Hello, world! Bye, world! g Sets the  Content-Type in the  headers.Example: @ghci> :set -XOverloadedStrings ghci> setContentType "text/html" b+ HTTP/1.1 200 OK content-type: text/html hConvert 9 into ² for output.fTODO: Remove duplication. This function is copied from snap-server/Snap.Internal.Http.Server.Session.iRender cookies from a given  to .fTODO: Remove duplication. This function is copied from snap-server/Snap.Internal.Http.Server.Session.j Adds an HTTP 9 to  headers.Example: 2ghci> :set -XOverloadedStrings ghci> let cookie = 9: "name" "value" Nothing Nothing Nothing False False ghci> k "name" $ j cookie bA Just (Cookie {cookieName = "name", cookieValue = "value", ...}) k Gets an HTTP 9 with the given name from  headers.Example: %ghci> :set -XOverloadedStrings ghci> k "cookie-name" b Nothing lReturns a list of 9 s present in Example: ghci> l b [] mDeletes an HTTP 9 from the Z headers. Please note this does not necessarily erase the cookie from the client browser.Example: 2ghci> :set -XOverloadedStrings ghci> let cookie = 9G "name" "value" Nothing Nothing Nothing False False ghci> let rsp = j cookie b ghci> kR "name" rsp Just (Cookie {cookieName = "name", cookieValue = "value", ...}) ghci> k "name" $ m "name" rsp Nothing nModifies an HTTP 9 with given name in - headers. Nothing will happen if a matching 9 can not be found in .Example: ,ghci> :set -XOverloadedStrings ghci> import  Data.Monoid ghci> let cookie = 9G "name" "value" Nothing Nothing Nothing False False ghci> let rsp = j cookie b ghci> k\ "name" rsp Just (Cookie {cookieName = "name", cookieValue = "value", ...}) ghci> let f ck@(9J { cookieName = name }) = ck { cookieName = name <> "'"} ghci> let rsp' = n "name" f rsp ghci> k> "name'" rsp' Just (Cookie {cookieName = "name'", ...}) ghci> k6 "name" rsp' Just (Cookie {cookieName = "name", ...}) o$A note here: if you want to set the Content-Lengtho for the response, Snap forces you to do it with this function rather than by setting it in the headers; the Content-Length in the headers will be ignored.@The reason for this is that Snap needs to look up the value of Content-Length€ for each request, and looking the string value up in the headers and parsing the number out of the text will be too expensive.vIf you don't set a content length in your response, HTTP keep-alive will be disabled for HTTP/1.0 clients, forcing a Connection: closeO. For HTTP/1.1 clients, Snap will switch to the chunked transfer encoding if Content-Length is not specified.Example: ghci> setContentLength 400 b' HTTP/1.1 200 OK Content-Length: 400 p Removes any Content-Length set in the .Example: ghci> clearContentLength $ o 400 b HTTP/1.1 200 OK q Convert a ¸ into common log entry format.r Convert a ¸ into an HTTP timestamp.Example: ghci> r . ¹& $ 10 "Thu, 01 Jan 1970 00:00:10 GMT" s"Converts an HTTP timestamp into a ¸.Example: %ghci> :set -XOverloadedStrings ghci> s$ "Thu, 01 Jan 1970 00:00:10 GMT" 10 uSee %.vSee &. ]parameter name to look up HTTP request^parameter name to look up HTTP request_parameter name to look up HTTP requestaparameter nameparameter valuesrequestcnew response bodyresponse to modifydHTTP response integer codeHTTP response explanationResponse to be modifiedeHTTP response integer codeResponse to be modifiedj cookie valueresponse to modifyk cookie nameresponse to querylresponse to querym cookie nameresponse to modifyn cookie namemodifier functionresponse to modifyb !"#,76543210/.-*)('&%$+89:A@?>=<;BCLKJIGFEDHMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuviTSRQNOPUVWXYCDEFGHIJKLMyxZB9:;<=>?@A8"#$%&'()*+,-./01234567{zw! [\}|]^_`abcdefghijklmnoprqstuv "#$%&'()*+,-./012345679:;<=>?@AC DEFGHIJKLMNOPNone†‰‚Given a , return its body as a ².Example: ghci> ‚  emptyResponse "" ƒGiven a 4, assert that its HTTP status code is 200 (success).Example: 6ghci> :set -XOverloadedStrings ghci> import qualified  Test.HUnit= as T ghci> let test = T.runTestTT . T.TestCase ghci> test $ ƒ q Cases: 1 Tried: 1 Errors: 0 Failures: 0 Counts {cases = 1, tried = 1, errors = 0, failures = 0} ghci> test $ ƒ ( 500 "Internal Server Error" ³) ### Failure: Expected success (200) but got (500) expected: 200 but got: 500 Cases: 1 Tried: 1 Errors: 0 Failures: 1 Counts {cases = 1, tried = 1, errors = 0, failures = 1} „Given a 6, assert that its HTTP status code is 404 (Not Found).Example: %ghci> :set -XOverloadedStrings ghci> „ $  404 "Not Found"  ghci> „ d *** Exception: HUnitFailure "Expected Not Found (404) but got (200)\nexpected: 404\n but got: 200" …Given a m, assert that its HTTP status code is between 300 and 399 (a redirect), and that the Location header of the  points to the specified URI.Example: .ghci> :set -XOverloadedStrings ghci> let r' =  301 "Moved Permanently"  ghci> let r = ' "Location" "www.example.com" r' ghci> … "www.example.com" r ghci> … "www.example.com" K *** Exception: HUnitFailure "Expected redirect but got status code (200)" †Given a H, assert that its HTTP status code is between 300 and 399 (a redirect).Example: %ghci> :set -XOverloadedStrings ghci> † $  301 "Moved Permanently"  ghci> † K *** Exception: HUnitFailure "Expected redirect but got status code (200)" ‡Given a =, assert that its body matches the given regular expression.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified System.IO.Streams# as Streams ghci> import qualified Data.ByteString.Builder# as Builder ghci> :{ ghci| let r = – ghci| (out -> do ghci| Streams.write (Just $ Builder.byteString "Hello, world!") out ghci| return out) ghci|  ghci| :} ghci> ‡ "^Hello" r ghci> ‡] "Bye" r *** Exception: HUnitFailure "Expected body to match regexp \"\"Bye\"\", but didn't" …)The Response should redirect to this URI‡'Regexp that will match the body content‚ƒ„…†‡NoneD¡«“Parser for request headers.¤ Used for ")field-name", and field-name = token, so "Ftoken": comma-separated tokens/field-names, like a header field list.§#Decode an URL-escaped string (see  3http://tools.ietf.org/html/rfc2396.html#section-2.4)Example: ghci> §R "1+attoparsec+%7e%3d+3+*+10%5e-2+meters" Just "1 attoparsec ~= 3 * 10^-2 meters" ¨URL-escape a string (see  3http://tools.ietf.org/html/rfc2396.html#section-2.4)Example: ghci> ¨M "1 attoparsec ~= 3 * 10^-2 meters" "1+attoparsec+%7e%3d+3+*+10%5e-2+meters" ©URL-escape a string (see  3http://tools.ietf.org/html/rfc2396.html#section-2.4 ) into a ¶.Example:  ghci> import Data.ByteString.Builder ghci> º . ©O $ "1 attoparsec ~= 3 * 10^-2 meters" "1+attoparsec+%7e%3d+3+*+10%5e-2+meters" ­Parse a string encoded in !application/x-www-form-urlencoded  Ihttp://en.wikipedia.org/wiki/POST_%28HTTP%29#Use_for_submitting_web_formsformat.Example: ghci> ­F "Name=John+Doe&Name=Jane+Doe&Age=23&Formula=a+%2B+b+%3D%3D+13%25%21"  [(Age ,["23"]),(Formula,["a + b == 13%!"]),(Name,["John Doe","Jane Doe"])] ®Like ¯, but produces a ¶ instead of a ²G. Useful for constructing a large string efficiently in a single step.Example:  ghci> import Data.Map ghci> import  Data.Monoid ghci> import Data.ByteString.Builder ghci> let bldr = ® ( [(Name, ["John Doe"]), (Age, ["23"])]) ghci> º $ · " http://example.com/script?" <> bldr " /http://example.com/script?Age=23&Name=John+Doe" ¯VGiven a collection of key-value pairs with possibly duplicate keys (represented as a »), construct a string in !application/x-www-form-urlencoded format.Example: ghci> ¯ ( [(Name, ["John Doe"]), (Age#, ["23"])]) "Age=23&Name=John+Doe" ,ˆ‰Š‹Œ‘’“”•–—˜™š›œŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³,‰Š‹Œ‘’“”•–—˜™š›œŸ ¡¢£¤¥ˆ¦§¨©ª«¬­®¯°±²³Š0None01;<=>?CFKQTVtÀ>´6This exception is thrown if the handler you supply to ÷ fails.¼¼ is the ¼ that user web handlers run in. ¼ gives you: +Stateful access to fetch or modify an HTTP ". 3printRqContextPath :: Snap () printRqContextPath = é . 2 =<< Ü +Stateful access to fetch or modify an HTTP . 7printRspStatusReason :: Snap () printRspStatusReason = é .  =<< Ş  Failure / ½ / ¾ semantics: a ¼9 handler can choose not to handle a given request, using ¿ or its synonym Ñ0, and you can try alternative handlers with the À operator: a :: Snap String a = Ñ< b :: Snap String b = return "foo" c :: Snap String c = a À8 b -- try running a, if it fails then try b Convenience functions (é, ê, ë, ì, ç+) for queueing output to be written to the ), or for streaming to the response using  -http://hackage.haskell.org/package/io-streams io-streams:  example :: (Á ¶ -> IO (Á ¶*)) -> Snap () example streamProc = do é! "I'm a strict bytestring" ê "I'm a lazy bytestring" ë "I'm strict text" ç streamProc Early termination: if you call Ï: a :: Snap () a = do ã $ d! 500 "Internal Server Error" é "500 error" r <- Ş Ï r @then any subsequent processing will be skipped and the supplied  value will be returned from ÷ as-is.Access to the  monad through a à instance: a :: Snap () a = Ä fireTheMissiles PThe ability to set or extend a timeout which will kill the handler thread after N3 seconds of inactivity (the default is 20 seconds): a :: Snap () a =  30 #Throw and catch exceptions using a Å instance: import Control.Exception.Lifted (Æ, Ç, È() foo :: Snap () foo = bar `catch` (e::Æ) -> baz where bar = Ç FooException Log a message to the error log: foo :: Snap () foo = æ "grumble." JYou may notice that most of the type signatures in this module contain a (Ê m) => ... typeclass constraint. ÊB is a typeclass which, in essence, says "you can get back to the ¼ monad from here". Using Ê you can extend the ¼K monad with additional functionality and still have access to most of the ¼ functions without writing Y everywhere. Instances are already provided for most of the common monad transformers (, , É, etc.).ÃUsed internally to implement ö.Æ#Type of external handler passed to ö.ÊÊ is a type class, analogous to à for Â, that makes it easy to wrap ¼ inside monad transformers.ËLift a computation from the ¼ monad.ÌMPass the request body stream to a consuming procedure, returning the result.‰If the consuming procedure you pass in here throws an exception, Snap will attempt to clear the rest of the unread request body (using 0) before rethrowing the exception. If you used õ?, however, Snap will give up and immediately close the socket. To prevent slowloris attacks, the connection will be also terminated if the input socket produces data too slowly (500 bytes per second is the default limit).Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.ByteString.Char8 as B8 ghci> import qualified Data.ByteString.Lazy as L ghci> import  Data.Char" (toUpper) ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified System.IO.Streamsó as Streams ghci> let r = T.put "/foo" "text/plain" "some text" ghci> :{ ghci| let f s = do u <- Streams.map (B8.map toUpper) s ghci| l <- Streams.toList u ghci| return $ L.fromChunks l ghci| :} ghci> T.runHandler r (Ì f >>= êS) HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 20:48:40 GMT SOME TEXT ÍhReturns the request body as a lazy bytestring. /Note that the request is not actually provided lazily!/Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestP as T ghci> let r = T.put "/foo" "text/plain" "some text" ghci> T.runHandler r (Í 2048 >>= êS) HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 20:08:44 GMT some text  Since: 0.6ÎxNormally Snap is careful to ensure that the request body is fully consumed after your web handler runs, but before the ‹ body is streamed out the socket. If you want to transform the request body into some output in O(1) space, you should use this function.nTake care: in order for this to work, the HTTP client must be written with input-to-output streaming in mind.[Note that upon calling this function, response processing finishes early as if you called Ï]. Make sure you set any content types, headers, cookies, etc. before you call this function.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.ByteString.Char8 as B8 ghci> import  Data.Char" (toUpper) ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified System.IO.Streams as Streams ghci> let r = T.put "/foo" "text/plain" "some text" ghci> let f = Streams.map (B8.map toUpper) ghci> T.runHandler r (Î f >> Í 2048 >>= êS) HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 20:30:15 GMT SOME TEXT ÏShort-circuits a ¼( monad action early, storing the given  value in its state.LIMPORTANT: Be vary careful when using this with things like a DB library's withTransactionƒ function or any other kind of setup/teardown block, as it can prevent the cleanup from being called and result in resource leaks.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import Control.Applicative8 ghci> let r = T.get "/" M.empty ghci> T.runHandler r ((Ù $ é "TOP") <|> Ï b) HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 16:58:57 GMT TOP ghci> let r' = T.get "/foo/bar" M.empty ghci> T.runHandler r' ((Ù $ é "TOP") <|> Ï bJ) HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 17:50:50 GMT Ğ4Capture the flow of control in case a handler calls Ï.WARNING: in the event of a call to ÎX it is possible to violate HTTP protocol safety when using this function. If you call Ğ9 it is suggested that you do not modify the body of the  which was passed to the Ï call.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.ByteString.Char8 as B8 ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import Control.Applicative7 ghci> let r = T.get "/foo/bar" M.empty ghci> let h = (Ù $ é "TOP") <|> Ï b ghci> T.runHandler r (Ğ h >>= éq . B8.pack . show) HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 18:35:42 GMT Left HTTP/1.1 200 OK ÑFails out of a ¼t monad action. This is used to indicate that you choose not to handle the given request within the given handler.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestB as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r ѹ HTTP/1.1 404 Not Found server: Snap/test date: Thu, 07 Aug 2014 13:35:42 GMT <!DOCTYPE html> <html> <head> <title>Not found</title> </head> <body> <code>No handler accepted "/foo/bar" /code </body></html> ÒRuns a ¼J monad action only if the request's HTTP method matches the given method.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (Ò D $ ég "OK") HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 13:38:48 GMT OK ghci> T.runHandler r (Ò F $ é" "OK") HTTP/1.1 404 Not Found ... ÓRuns a ¼R monad action only if the request's HTTP method matches one of the given methods.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (Ó [D, F] $ ég "OK") HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 13:38:48 GMT OK ghci> T.runHandler r (Ó [F] $ é" "OK") HTTP/1.1 404 Not Found ... ÖRuns a ¼ monad action only when the 19 of the request starts with the given path. For example, dir "foo" handler Will fail if 1 is not "/foo" or "/foo/...", and will add "foo/" to the handler's local 2.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (Ö "foo" $ ég "OK") HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 14:52:24 GMT OK ghci> T.runHandler r (Ö "baz" $ é" "OK") HTTP/1.1 404 Not Found ... ×Runs a ¼& monad action only for requests where 1K is exactly equal to the given string. If the path matches, locally sets 2 to the old value of 1, sets 1!="", and runs the given handler.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test1 as T ghci> T.runHandler (T.get "/foo" M.empty) (× "foo" $ é~ "bar") HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 14:15:42 GMT bar ghci> T.runHandler (T.get "/foo" M.empty) (× "bar" $ é# "baz") HTTP/1.1 404 Not Found ... ØRuns a ¼z monad action only when the first path component is successfully parsed as the argument to the supplied handler function.CNote that the path segment is url-decoded prior to being passed to fromBS$; this is new as of snap-core 0.10.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestU as T ghci> let r = T.get "/11/foo/bar" M.empty ghci> let f = (\i -> if i == 11 then é "11" else é "???") ghci> T.runHandler r (Ø f) HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 14:27:10 GMT 11 ghci> let r' = T.get "/foo/11/bar" M.empty ghci> T.runHandler r' (Ø f) HTTP/1.1 404 Not Found ... ÙRuns a ¼ monad action only when 1 is empty.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test< as T ghci> let r = T.get "/" M.empty ghci> T.runHandler r (Ù $ é OK‡) HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 14:56:39 GMT OK ghci> let r' = T.get "/foo" M.empty ghci> T.runHandler r' (Ù $ é" "OK") HTTP/1.1 404 Not Found ... ÚLocal Snap version of get.ÛLocal Snap monad version of modify.Ü Grabs the " object out of the ¼ monad.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (é . 3 =<< ÜR) HTTP/1.1 200 OK server: Snap/test date: Sat, 02 Aug 2014 07:51:54 GMT /foo/bar İGrabs something out of the "3 object, using the given projection function. See gets.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (é =<< İ 3R) HTTP/1.1 200 OK server: Snap/test date: Sat, 02 Aug 2014 07:51:54 GMT /foo/bar Ş Grabs the  object out of the ¼ monad.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (é .  =<< ŞL) HTTP/1.1 200 OK server: Snap/test date: Sat, 02 Aug 2014 15:06:00 GMT OK ßGrabs something out of the 3 object, using the given projection function. See gets.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (é =<< ß L) HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 13:35:45 GMT OK à Puts a new  object into the ¼ monad.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> let rsp = e 404 bB ghci> let req = T.get "/foo/bar" M.empty ghci> T.runHandler req (àU rsp) HTTP/1.1 404 Not Found server: Snap/test date: Wed, 06 Aug 2014 13:59:58 GMT á Puts a new " object into the ¼ monad. Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Testi as T ghci> :{ ghci| let hndlr = do rq <- T.buildRequest (T.get "/bar/foo" M.empty) ghci| á! rq ghci| uri' <- İ 3 ghci| é“ uri' ghci| :} ghci> T.runHandler (T.get "/foo/bar" M.empty) hndlr HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 15:13:46 GMT /bar/foo â Modifies the " object stored in a ¼ monad. Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Testy as T ghci> let r = T.get "/foo/bar" M.empty ghci> r' <- T.buildRequest $ T.get "/bar/foo" M.empty ghci> T.runHandler r (â (const r') >> İ 3 >>= éR) HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 15:24:25 GMT /bar/foo ã Modifes the  object stored in a ¼ monad. Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (ã $ eU 404) HTTP/1.1 404 Not Found server: Snap/test date: Wed, 06 Aug 2014 15:27:11 GMT ä#Performs a redirect by setting the LocationH header to the given target URL/path and the status code to 302 in the  object stored in a ¼N monad. Note that the target URL is not validated in any way. Consider using å> instead, which allows you to choose the correct status code.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (ä¯ "http://snapframework.com") HTTP/1.1 302 Found content-length: 0 location: http://snapframework.com server: Snap/test date: Thu, 07 Aug 2014 08:52:11 GMT Content-Length: 0 å#Performs a redirect by setting the Locationj header to the given target URL/path and the status code (should be one of 301, 302, 303 or 307) in the  object stored in a ¼> monad. Note that the target URL is not validated in any way.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (åÀ "http://snapframework.com" 301) HTTP/1.1 307 Temporary Redirect content-length: 0 location: http://snapframework.com server: Snap/test date: Thu, 07 Aug 2014 08:55:51 GMT Content-Length: 0 æLog an error message in the ¼ monad.Example: ghci> import qualified Data.ByteString.Char8 as B8 ghci> ÷ (æ "fatal error!") (error> . B8.unpack) undefined undefined *** Exception: fatal error! ç9Run the given stream procedure, adding its output to the  stored in the ¼ monad state.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified Data.ByteString.Builder as B ghci> import qualified System.IO.StreamsÏ as Streams ghci> let r = T.get "/foo/bar" M.empty ghci> :{ ghci| let f str = do { ghci| Streams.write (Just $ B.byteString "Hello, streams world") str; ghci| return str } ghci| :} ghci> T.runHandler r (ç` f) HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 17:55:47 GMT Hello, streams world èAdds the given ¶ to the body of the  stored in the | ¼ monad state.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified Data.ByteString.BuilderC as B ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (èt $ B.byteString "Hello, world") HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 17:33:33 GMT Hello, world éAdds the given strict ² to the body of the  stored in the ¼ monad state.vWarning: This function is intentionally non-strict. If any pure exceptions are raised by the expression creating the ²B, the exception won't actually be raised within the Snap handler.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (é{ "Hello, bytestring world") HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 17:34:27 GMT Hello, bytestring world êAdds the given lazy Ê to the body of the  stored in the ¼ monad state.vWarning: This function is intentionally non-strict. If any pure exceptions are raised by the expression creating the ²B, the exception won't actually be raised within the Snap handler.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (ê… "Hello, lazy bytestring world") HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 17:35:15 GMT Hello, lazy bytestring world ëAdds the given strict Ë to the body of the  stored in the ¼ monad state.vWarning: This function is intentionally non-strict. If any pure exceptions are raised by the expression creating the ²B, the exception won't actually be raised within the Snap handler.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (ëo "Hello, text world") HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 17:36:38 GMT Hello, text world ìAdds the given lazy Ì to the body of the  stored in the ¼ monad state.vWarning: This function is intentionally non-strict. If any pure exceptions are raised by the expression creating the ²B, the exception won't actually be raised within the Snap handler.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (ìy "Hello, lazy text world") HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 17:37:41 GMT Hello, lazy text world í9Sets the output to be the contents of the specified file.Calling í5 will overwrite any output queued to be sent in the :. If the response body is not modified after the call to í, Snap will use the efficient  sendfile()+ system call on platforms that support it.(If the response body is modified (using f ), the file will be read using mmap().Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci>  writeFileg "/tmp/snap-file" "Hello, sendFile world" ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (í– "/tmp/snap-file") HTTP/1.1 200 OK content-length: 21 server: Snap/test date: Wed, 06 Aug 2014 17:45:10 GMT Content-Length: 21 Hello, sendFile world î^Sets the output to be the contents of the specified file, within the given (start,end) range.Calling î5 will overwrite any output queued to be sent in the :. If the response body is not modified after the call to î, Snap will use the efficient  sendfile()+ system call on platforms that support it.(If the response body is modified (using f ), the file will be read using mmap().Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci>  writeFilen "/tmp/snap-file" "Hello, sendFilePartial world" ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (î "/tmp/snap-file" (7, 28)) HTTP/1.1 200 OK content-length: 21 server: Snap/test date: Wed, 06 Aug 2014 17:47:20 GMT Content-Length: 21 sendFilePartial world ïRuns a ¼ action with a locally-modified " state object. The "\ object in the Snap monad state after the call to localRequest will be unchanged. Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Testz as T ghci> let r = T.get "/foo/bar" M.empty ghci> r' <- T.buildRequest $ T.get "/bar/foo" M.empty ghci> let printRqURI = İ 3 >>= é >> é* "\n" ghci> T.runHandler r (printRqURI >> ïr (const r') printRqURI) HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 15:34:12 GMT /foo/bar /bar/foo ğ Fetches the "7 from state and hands it to the given action. Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import Control.Monad.IO.Class6 ghci> let r = T.get "/foo/bar" M.empty ghci> let h = ğ (\rq -> Ä (T.requestToString rq) >>= éˆ) ghci> T.runHandler r h HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 15:44:24 GMT GET /foo/bar HTTP/1.1 host: localhost ñ Fetches the 7 from state and hands it to the given action. Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.TestC as T ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (ñ $ é . L) HTTP/1.1 200 OK server: Snap/test date: Wed, 06 Aug 2014 15:48:45 GMT OK ò Modifies the " in the state to set the  rqRemoteAddrm field to the value in the X-Forwarded-For header. If the header is not present, this action has no effect.ÇThis action should be used only when working behind a reverse http proxy that sets the X-Forwarded-For header. This is the only way to ensure the value in the X-Forwarded-For header can be trusted.ÛThis is provided as a filter so actions that require the remote address can get it in a uniform manner. It has specifically limited functionality to ensure that its transformation can be trusted, when used correctly.ó Modifies the " in the state to set the  rqRemoteAddrt field to the value from the header specified. If the header specified is not present, this action has no effect.·This action should be used only when working behind a reverse http proxy that sets the header being looked at. This is the only way to ensure the value in the header can be trusted.ÛThis is provided as a filter so actions that require the remote address can get it in a uniform manner. It has specifically limited functionality to ensure that its transformation can be trusted, when used correctly.ôsThis function brackets a Snap action in resource acquisition and release. This is provided because MonadCatchIO's bracketh function doesn't work properly in the case of a short-circuit return from the action being bracketed.¼In order to prevent confusion regarding the effects of the aquisition and release actions on the Snap state, this function doesn't accept Snap actions for the acquire or release actions.£This function will run the release action in all cases where the acquire action succeeded. This includes the following behaviors from the bracketed Snap action. Normal completion.Short-circuit completion, either from calling Í or ÏAn exception being thrown.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> let br = ôÊ (putStrLn "before") (const $ putStrLn "after") ghci> T.runHandler (T.get "/" M.empty) (br $ const $ writeBS "OK") before after HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 18:41:50 GMT OK õ4Terminate the HTTP session with the given exception.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified Control.Exception¯ as E ghci> let r = T.get "/foo/bar" M.empty ghci> T.runHandler r (terminateConnection $ E.AssertionFailed "Assertion failed!") *** Exception: <terminated: Assertion failed!> öiTerminate the HTTP session and hand control to some external handler, escaping all further HTTP traffic.‚The external handler takes three arguments: a function to modify the thread's timeout, and a read and a write ends to the socket.÷Runs a ¼ monad action.KThis function is mostly intended for library writers; instead of invoking ÷ directly, use  ! or " (for testing).ø'Post-process a finalized HTTP response:fixup content-length header!properly handle 204/304 responses)if request was HEAD, remove response bodyVNote that we do NOT deal with transfer-encoding: chunked or "connection: close" here.ûSee ]9. Looks up a value for the given named parameter in the "D. If more than one value was entered for the given parameter name, û gloms the values together with Î " ".Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified Data.ByteString.Char8\ as B8 ghci> let r = T.get "/foo/bar" $ M.fromList [("foo", ["bar"])] ghci> T.runHandler r (û "foo" >>= ée . B8.pack . show) HTTP/1.1 200 OK server: Snap/test date: Mon, 11 Aug 2014 12:57:20 GMT Just "bar" üSee ^Y. Looks up a value for the given named parameter in the POST form parameters mapping in "D. If more than one value was entered for the given parameter name, ü" gloms the values together with: Î " ".Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified Data.ByteString.Char8g as B8 ghci> let r = T.postUrlEncoded "/foo/bar" $ M.fromList [("foo", ["bar"])] ghci> T.runHandler r (ü "foo" >>= ée . B8.pack . show) HTTP/1.1 200 OK server: Snap/test date: Mon, 11 Aug 2014 13:01:04 GMT Just "bar" ıSee _\. Looks up a value for the given named parameter in the query string parameters mapping in "D. If more than one value was entered for the given parameter name, ı" gloms the values together with Î " ".Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified Data.ByteString.Char8x as B8 ghci> let r = T.postUrlEncoded "/foo/bar" M.empty >> T.setQueryStringRaw "foo=bar&foo=baz" ghci> T.runHandler r (ı "foo" >>= éi . B8.pack . show) HTTP/1.1 200 OK server: Snap/test date: Mon, 11 Aug 2014 13:06:50 GMT Just "bar baz" şSee 5!. Convenience function to return 8 from the " inside of a Ê instance.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified Data.ByteString.Char8\ as B8 ghci> let r = T.get "/foo/bar" $ M.fromList [("foo", ["bar"])] ghci> T.runHandler r (ş >>= éu . B8.pack . show) HTTP/1.1 200 OK server: Snap/test date: Mon, 11 Aug 2014 13:02:54 GMT fromList [("foo",["bar"])] ÿSee 5!. Convenience function to return 8 from the " inside of a Ê instance.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified Data.ByteString.Char8g as B8 ghci> let r = T.postUrlEncoded "/foo/bar" $ M.fromList [("foo", ["bar"])] ghci> T.runHandler r (ÿ >>= éu . B8.pack . show) HTTP/1.1 200 OK server: Snap/test date: Mon, 11 Aug 2014 13:04:34 GMT fromList [("foo",["bar"])] See 5!. Convenience function to return 8 from the " inside of a Ê instance.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified Data.ByteString.Char8x as B8 ghci> let r = T.postUrlEncoded "/foo/bar" M.empty >> T.setQueryStringRaw "foo=bar&foo=baz" ghci> T.runHandler r ( >>= é{ . B8.pack . show) HTTP/1.1 200 OK server: Snap/test date: Mon, 11 Aug 2014 13:10:17 GMT fromList [("foo",["bar","baz"])] Gets the HTTP 9 with the specified name.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified Data.ByteString.Char8 as B8 ghci> let cookie = 9Š "name" "value" Nothing Nothing Nothing False False ghci> let r = T.get "/foo/bar" M.empty >> T.addCookies [cookie] ghci> T.runHandler r ( "name" >>= éš . B8.pack . show) HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 12:16:58 GMT Just (Cookie {cookieName = "name", cookieValue = "value", ...}) Gets the HTTP 9Y with the specified name and decodes it. If the decoding fails, the handler calls pass.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> let cookie = 9Š "name" "value" Nothing Nothing Nothing False False ghci> let r = T.get "/foo/bar" M.empty >> T.addCookies [cookie] ghci> T.runHandler r ( "name" >>= éO) HTTP/1.1 200 OK server: Snap/test date: Thu, 07 Aug 2014 12:20:09 GMT value  Expire given 9 in client's browser.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test” as T ghci> let r = T.get "/foo/bar" M.empty ghci> let cookie = Cookie "name" "" Nothing (Just "/subsite") Nothing True False ghci> T.runHandler r (ÿD cookie) HTTP/1.1 200 OK set-cookie: name=; path=/subsite; expires=Sat, 24 Dec 1994 06:28:16 GMT; Secure server: Snap/test date: Thu, 07 Aug 2014 12:21:27 GMT ghci> let cookie = Cookie "name" "value" Nothing Nothing Nothing False False ghci> let r2 = T.get "/foo/bar" M.empty >> T.addCookies [cookie] ghci> T.runHandler r ( "name" >>= maybe (return ()) _) HTTP/1.1 200 OK set-cookie: name=; expires=Sat, 24 Dec 1994 06:28:16 GMT server: Snap/test 'Causes the handler thread to be killed n seconds from now.0Causes the handler thread to be killed at least n seconds from now.CModifies the amount of time remaining before the request times out. Returns an Â6 action which you can use to modify the timeout value. Ætimeout modifiersocket read endsocket write endÍnsize of the largest request body we're willing to accept. If a request body longer than this is received, a TooManyBytesReadException is thrown. See takeNoMoreThan.Îthe Ï from the "5 is passed to this function, and then the resulting Ï is fed to the output.Öpath component to matchhandler to run×path to match againsthandler to runç output to add÷Action to run.Error logging action.Timeout action. HTTP request.ûparameter name to look upüparameter name to look upıparameter name to look up® !"#+$%&'()*-./01234567,89:;<=>?@ABCMHDEFGIJKLNPOUVWXYZ[\]^_`abcdefgjklmnopqrst´µ¶·¸¹º»¼½¾¿ÂÀÁÃÄÅÆÇÉÈÊËÌÍÎÏĞÑÒÓÔÕÖרÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿTÊËÇÈÉÆÃÄÅ¿ÀÁ¼½¾¶·¸¹º»ÌÍÎÏĞÑÒÓÔÕÖרÙÚÛÜŞİßáàâãäåæçèéêëìíîïğñòóô´µõö÷øùúûüışÿ´µĞÑÒ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÇÈÉÊË#None<QV½ ÓXThe internal data type you use to build a routing tree. Matching is done unambiguously.Ô and Õ$ routes can have a "fallback" route:For Ô9, the fallback is routed when there is nothing to captureFor Õ>, the fallback is routed when we can't find a route in its map3Fallback routes are stacked: i.e. for a route like: 5Dir [("foo", Capture "bar" (Action bar) NoRoute)] baz¾visiting the URI foo/ will result in the "bar" capture being empty and triggering its fallback. It's NoRoute, so we go to the nearest parent fallback and try that, which is the baz action.€A web handler which, given a mapping from URL entry points to web handlers, efficiently routes requests to the correct handler.Usage>The URL entry points are given as relative paths, for example: &route [ ("foo/bar/quux", fooBarQuux) ]&If the URI of the incoming request is  /foo/bar/quux or /foo/bar/quux/...anything...% then the request will be routed to  "fooBarQuux", with 2 set to "/foo/bar/quux/" and 1 set to "...anything...".CA path component within an URL entry point beginning with a colon (":") is treated as a variable captureT; the corresponding path component within the request URI will be entered into the 5K parameters mapping with the given name. For instance, if the routes were: )route [ ("foo/:bar/baz", fooBazHandler) ]Then a request for "/foo/saskatchewan/baz" would be routed to  fooBazHandler with a mapping for "bar" => "saskatchewan" in its parameters table.kLonger paths are matched first, and specific routes are matched before captures. That is, if given routes: ([ ("a", h1), ("a/b", h2), ("a/:x", h3) ]a request for "/a/b" will go to h2, "/a/s" for any s will go to h3, and "/a" will go to h1.The following example matches  "/article" to an article index, "/login" to a login, and "/article/..." to an article renderer. _ [ ("article", renderIndex) , ("article/:id", renderArticle) , ("login", $ POST doLogin) ] Note: URL decodingQA short note about URL decoding: path matching and variable capture are done on decoded URLs, but the contents of 2 and 1m will contain the original encoded URL, i.e. what the user entered. For example, in the following scenario: route [ ("a b c d/", foo ) ]A request for "/a+b+c+d" will be sent to foo with 2 set to "a+b+c+d".hThis behaviour changed as of Snap 0.6.1; previous versions had unspecified (and buggy!) semantics here.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as Map ghci> import qualified Data.ByteString.Char8 as B8 ghci> import  Snap.Test& ghci> :{ ghci| let handler = do r <- Ü ghci| % $ "rqContextPath: " <> 2" r <> "\n" ghci| % $ "rqPathInfo: " <> 1" r <> "\n" ghci| %% $ "rqParams: " <> (B8.pack . show $ 5 r) ghci| :} ghci> " (& "/foo/bar" "Map.empty") ( [("foo", handler)]) HTTP/1.1 200 OK server: Snap/test date: Sat, 02 Aug 2014 05:16:59 GMT rqContextPath: /foo/ rqPathInfo: bar rqParams: fromList [] ghci> " (& "/foo/bar" "Map.empty") (k [("foo/:bar", handler)]) [...] rqContextPath: /foo/bar/ rqPathInfo: rqParams: fromList [("bar",["bar"])] The  function is the same as , except it doesn't change the request's context path. This is useful if you want to route to a particular handler but you want that handler to receive the 1 as it is.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified Data.ByteString.Char8 as B8 ghci> import  Snap.Test& ghci> :{ ghci| let handler = do r <- Ü ghci| % $ "rqContextPath: " <> 2" r <> "\n" ghci| % $ "rqPathInfo: " <> 1" r <> "\n" ghci| %% $ "rqParams: " <> (B8.pack . show $ 5 r) ghci| :} ghci> " (& "/foo/bar" M.empty) (‡ [("foo", handler)]) HTTP/1.1 200 OK server: Snap/test date: Sat, 02 Aug 2014 05:17:28 GMT rqContextPath: / rqPathInfo: foo/bar ghci> " (& "/foo/bar" M.empty) (k [("foo/:bar", handler)]) [...] rqContextPath: / rqPathInfo: foo/bar rqParams: fromList [("bar",["bar"])] Ö-action to run before we call the user handler^the "context"; the list of path segments we've already successfully matched, in reverse order0the list of path segments we haven't yet matched Ó×ÔÕØÙÚÛÜÓ×ÔÕØ'NoneU½”None½Í’"76543210/.-*)('&%$+89:;<=>?@ABCMHDEFGIJKLNPOUVWXY]^_`abcdefgjklmnoprsuv§¨©­®¯´µ¼ÃÄÅÆÊËÌÍÎÏĞÑÒÓÖרÙÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷ûüışÿ§¼÷ÊË´µôÏĞÑÆÃÄÅöõÒÓרÖÙÜİŞßáàâãïğñæÌÍÎ"$%&'()*+-./01234567NOP8CDEFGHIJKLM9:;<=>?@ABUVWXYòó+$%&'()*-./01234567]^_ûüışÿ`auvbedgjklmnopäåcfçèéìëêíîrs­®¯¨©§(None1<CVf€5 A form parameter name-value pair6Upload policy can be set on an "general" basis (using …), but handlers can also make policy decisions on individual files/parts uploaded. For each part uploaded, handlers can decide:'whether to allow the file upload at all.the maximum size of uploaded files, if allowed4File upload policy, if any policy is violated then  is thrown0 controls overall policy decisions relating to multipart/form-data uploads, specifically:Qwhether to treat parts without filenames as form input (reading them into the 5 map)†because form input is read into memory, the maximum size of a form input read in this manner, and the maximum number of form inputsåthe minimum upload rate a client must maintain before we kill the connection; if very low-bitrate uploads were allowed then a Snap server would be vulnerable to a trivial denial-of-service using a "slowloris"-type attackuthe minimum number of seconds which must elapse before we start killing uploads for having too low an upload rate.pthe amount of time we should wait before timing out the connection whenever we receive input from the client.Thrown when an  or  is violated.3Human-readable error message corresponding to the .KThrown when a part is invalid in some way (e.g. the headers are too large). 2Human-readable error message corresponding to the .!<All of the exceptions defined in this package inherit from !, so if you write .foo `catch` \(e :: FileUploadException) -> ...you can catch a , a , etc.""A contains information about a "part" in a request uploaded with !Content-type: multipart/form-data.#EField name associated with this part (i.e., the name specified with <input name="partFieldName" ...).$Name of the uploaded file.%Content type of this part.&#Disposition type of this part. See (.',Remaining headers associated with this part.(2Represents the disposition type specified via the Content-Disposition header field. See  $https://www.ietf.org/rfc/rfc1806.txtRFC 1806.)Content-Disposition: attachment.*Content-Disposition: file.+Content-Disposition: form-data.,Any other value.-EA type alias for a function that will process one of the parts of a multipart/form-data- HTTP request body without usinc accumulator..EA type alias for a function that will process one of the parts of a multipart/form-data$ HTTP request body with accumulator./Contents of form field of type file1Name of a field2Result of storing file3ZReads uploaded files into a temporary directory and calls a user handler to process them.Note: %THE REQUEST MUST BE CORRECTLY ENCODED. If the request's  Content-type is not "multipart/formdata)", this function skips processing using pass.‘Given a temporary directory, global and file-specific upload policies, and a user handler, this function consumes a request body uploaded with !Content-type: multipart/form-dataˆ. Each file is read into the temporary directory, and is then passed to the user handler. After the user handler runs (but before the Response¾ body is streamed to the client), the files are deleted from disk; so if you want to retain or use the uploaded files in the generated response, you need to move or otherwise process them.3The argument passed to the user handler is a tuple: 4(PartInfo, Either PolicyViolationException FilePath)"The first half of this tuple is a "Ÿ, which contains the information the client browser sent about the given upload part (like filename, content-type, etc). The second half of this tuple is an İ stipulating that either: Dthe file was rejected on a policy basis because of the provided  handler3the file was accepted and exists at the given path. ExceptionsFIf the client's upload rate passes below the configured minimum (see @ and BŒ), this function terminates the connection. This setting is there to protect the server against slowloris-style denial of service attacks. If the given ; stipulates that you wish form inputs to be placed in the 5 parameter map (using :U), and a form input exceeds the maximum allowable size, this function will throw a .If an uploaded part contains MIME headers longer than a fixed internal threshold (currently 32KB), this function will throw a .4GProcesses form data and calls provided storage function on file parts.You can use this together with M, L7 or provide your own callback to store uploaded files.cIf you need to process uploaded file mime type or file name, do it in the store callback function. See also 5.DExample using with small files which can safely be stored in memory. ÿU import qualified Data.ByteString.Lazy as Lazy handleSmallFiles :: MonadSnap m => [(ByteString, ByteString, Lazy.ByteString)] handleSmallFiles = handleFormUploads uploadPolicy filePolicy store where uploadPolicy = defaultUploadPolicy filePolicy = setMaximumFileSize (64*1024) $ setMaximumNumberOfFiles 5 defaultUploadPolicy store partInfo stream = do content <- storeAsLazyByteString partInfo stream let fileName = partFileName partInfo fileMime = partContentType partInfo in (fileName, fileMime, content) 5iGiven an upload policy and a function to consume uploaded "parts", consume a request body uploaded with !Content-type: multipart/form-data.If : is Ş, then parts with disposition  form-data… (a form parameter) will be processed and returned as first element of resulting pair. Parts with other disposition will be fed to . handler.If : is ß2, then parts with any disposition will be fed to .› handler and first element of returned pair will be empty. In this case it is important that you limit number of form inputs and sizes of inputs in your .% handler to avoid common DOS attacks.Note: %THE REQUEST MUST BE CORRECTLY ENCODED. If the request's  Content-type is not "multipart/formdata)", this function skips processing using pass.)Most users will opt for the higher-level 30, which writes to temporary files, rather than 6«. This function should be chosen, however, if you need to stream uploaded files directly to your own processing function: e.g. to a database or a remote service via RPC.FIf the client's upload rate passes below the configured minimum (see @ and BŒ), this function terminates the connection. This setting is there to protect the server against slowloris-style denial of service attacks. Exceptions If the given > stipulates that you wish form inputs to be processed (using :‚), and a form input exceeds the maximum allowable size or the form exceeds maximum number of inputs, this function will throw a .If an uploaded part contains MIME headers longer than a fixed internal threshold (currently 32KB), this function will throw a .Since: 1.0.3.06 A variant of 57 accumulating results into a list. Also puts captured &s into rqPostParams and rqParams maps.72Human-readable error message corresponding to the !.8FA reasonable set of defaults for upload policy. The default policy is: maximum form input size128kBmaximum number of form inputs10minimum upload rate1kB/s%seconds before rate limiting kicks in10inactivity timeout 20 seconds9_Does this upload policy stipulate that we want to treat parts without filenames as form input?:ISet the upload policy for treating parts without filenames as form input.;DGet the maximum size of a form input which will be read into our 5 map.<DSet the maximum size of a form input which will be read into our 5 map.=DGet the maximum size of a form input which will be read into our 5 map.>DSet the maximum size of a form input which will be read into our 5 map.?Get the minimum rate (in  bytes/second:) a client must maintain before we kill the connection.@Set the minimum rate (in  bytes/second:) a client must maintain before we kill the connection.A]Get the amount of time which must elapse before we begin enforcing the upload rate minimumB]Set the amount of time which must elapse before we begin enforcing the upload rate minimumC‡Get the "upload timeout". Whenever input is received from the client, the connection timeout is set this many seconds in the future.DSet the upload timeout.E A default  maximum file size1MBmaximum number of files10skip files without nameyesmaximum size of skipped file0F%Maximum size of single uploaded file.G!Maximum number of uploaded files.H!Skip files with empty file names.DIf set, parts without filenames will not be fed to storage function.®HTML5 form data encoding standard states that form input fields of type file, without value set, are encoded same way as if file with empty body, empty file name, and type application/octet-stream was set as value.\You most likely want to use this with zero bytes allowed to avoid storing such fields (see I).+By default files without names are skipped.Since: 1.0.3.0I7Maximum size of file without name which can be skipped. Ignored if H is False.1If skipped file is larger than this setting then ! is thrown."By default maximum file size is 0.Since: 1.0.3.0J"Disallows the file to be uploaded.K2Allows the file to be uploaded, with maximum size n.L.Stores file body in memory as Lazy ByteString.MDStore files in a temporary directory, and clean up on function exit.-Files are safe to move until function exists.PIf asynchronous exception is thrown during cleanup, temporary files may remain. %uploadsHandler = withTemporaryStore "varçtmp" "upload-" $ store -> do (inputs, files) <- handleFormUploads defaultUploadpolicy defaultFileUploadPolicy (const store) saveFiles files à‰Assuming we've already identified the boundary value and split the input up into parts which match and parts which don't, run the given ²E InputStream over each part and grab a list of the resulting values.TODO/FIXME: fix description3temporary directorygeneral upload policyper-part upload policy(user handler (see function description)4general upload policyUpload policy for filesA file storage function5global upload policypart processorseed accumulator6global upload policypart processorMtemporary directoryfile name patternAction taking store functionámaximum size of form inputfile reading codeâmax num fieldsboundary valuepart processorGãäåæçèéêëìíîïğñ !ò"ó#$%'&()*+,-./0123456ô789:;<=>?@ABCDEFGHIJKLM õö÷øùúûüıãäæåçèéîïíëìêğñ şÿ!ò"ó#$%&'()*+,/012)NoneV©|NDA collection of options for serving static files out of a directory.PBFiles to look for when a directory is requested (e.g., index.html)Q=Handler to generate a directory listing if there is no index.R—Map of extensions to pass to dynamic file handlers. This could be used, for example, to implement CGI dispatch, pretty printing of source code, etc.S'MIME type map to look up content types.T†Handler that is called before a file is served. It will only be called when a file is actually found, not for generated index pages.UA type alias for MIME typeV!A type alias for dynamic handlersWGets a path from the " using 1¤ and makes sure it is safe to use for opening files. A path is safe if it is a relative path and has no ".." elements to escape the intended directory structure.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Test as T ghci> import qualified Data.ByteString.Char86 as B8 ghci> T.runHandler (T.get "/foo/bar" M.empty) (W >>= é . B8.pack) HTTP/1.1 200 OK server: Snap/test date: Fri, 08 Aug 2014 16:13:20 GMT foo/bar ghci> T.runHandler (T.get "/foo/../bar" M.empty) (W >>= é' . B8.pack) HTTP/1.1 404 Not Found ... XLThe default set of mime type mappings we use when serving files. Its value: ÿ¥Map.fromList [ ( ".asc" , "text/plain" ), ( ".asf" , "video/x-ms-asf" ), ( ".asx" , "video/x-ms-asf" ), ( ".au" , "audio/basic" ), ( ".avi" , "video/x-msvideo" ), ( ".bmp" , "image/bmp" ), ( ".bz2" , "application/x-bzip" ), ( ".c" , "text/plain" ), ( ".class" , "application/octet-stream" ), ( ".conf" , "text/plain" ), ( ".cpp" , "text/plain" ), ( ".css" , "text/css" ), ( ".cxx" , "text/plain" ), ( ".doc" , "application/msword" ), ( ".docx" , S.append "application/vnd.openxmlformats-officedocument" ".wordprocessingml.document" ), ( ".dotx" , S.append "application/vnd.openxmlformats-officedocument" ".wordprocessingml.template" ), ( ".dtd" , "application/xml-dtd" ), ( ".dvi" , "application/x-dvi" ), ( ".exe" , "application/octet-stream" ), ( ".flv" , "video/x-flv" ), ( ".gif" , "image/gif" ), ( ".gz" , "application/x-gzip" ), ( ".hs" , "text/plain" ), ( ".htm" , "text/html" ), ( ".html" , "text/html" ), ( ".ico" , "image/x-icon" ), ( ".jar" , "application/x-java-archive" ), ( ".jpeg" , "image/jpeg" ), ( ".jpg" , "image/jpeg" ), ( ".js" , "text/javascript" ), ( ".json" , "application/json" ), ( ".log" , "text/plain" ), ( ".m3u" , "audio/x-mpegurl" ), ( ".m3u8" , "application/x-mpegURL" ), ( ".mka" , "audio/x-matroska" ), ( ".mk3d" , "video/x-matroska" ), ( ".mkv" , "video/x-matroska" ), ( ".mov" , "video/quicktime" ), ( ".mp3" , "audio/mpeg" ), ( ".mp4" , "video/mp4" ), ( ".mpeg" , "video/mpeg" ), ( ".mpg" , "video/mpeg" ), ( ".ogg" , "application/ogg" ), ( ".pac" , "application/x-ns-proxy-autoconfig" ), ( ".pdf" , "application/pdf" ), ( ".png" , "image/png" ), ( ".potx" , S.append "application/vnd.openxmlformats-officedocument" ".presentationml.template" ), ( ".ppsx" , S.append "application/vnd.openxmlformats-officedocument" ".presentationml.slideshow" ), ( ".ppt" , "application/vnd.ms-powerpoint" ), ( ".pptx" , S.append "application/vnd.openxmlformats-officedocument" ".presentationml.presentation" ), ( ".ps" , "application/postscript" ), ( ".qt" , "video/quicktime" ), ( ".rtf" , "text/rtf" ), ( ".sig" , "application/pgp-signature" ), ( ".sldx" , S.append "application/vnd.openxmlformats-officedocument" ".presentationml.slide" ), ( ".spl" , "application/futuresplash" ), ( ".svg" , "image/svg+xml" ), ( ".swf" , "application/x-shockwave-flash" ), ( ".tar" , "application/x-tar" ), ( ".tar.bz2" , "application/x-bzip-compressed-tar" ), ( ".tar.gz" , "application/x-tgz" ), ( ".tbz" , "application/x-bzip-compressed-tar" ), ( ".text" , "text/plain" ), ( ".tif" , "image/tiff" ), ( ".tiff" , "image/tiff" ), ( ".tgz" , "application/x-tgz" ), ( ".torrent" , "application/x-bittorrent" ), ( ".ts" , "video/mp2t" ), ( ".txt" , "text/plain" ), ( ".wav" , "audio/x-wav" ), ( ".wax" , "audio/x-ms-wax" ), ( ".webm" , "video/webm" ), ( ".wma" , "audio/x-ms-wma" ), ( ".wmv" , "video/x-ms-wmv" ), ( ".xbm" , "image/x-xbitmap" ), ( ".xlam" , "application/vnd.ms-excel.addin.macroEnabled.12" ), ( ".xls" , "application/vnd.ms-excel" ), ( ".xlsb" , "application/vnd.ms-excel.sheet.binary.macroEnabled.12" ), ( ".xlsx" , S.append "application/vnd.openxmlformats-officedocument." "spreadsheetml.sheet" ), ( ".xltx" , S.append "application/vnd.openxmlformats-officedocument." "spreadsheetml.template" ), ( ".xml" , "text/xml" ), ( ".xpm" , "image/x-xpixmap" ), ( ".xwd" , "image/x-xwindowdump" ), ( ".zip" , "application/zip" ) ]<Style information for the default directory index generator.YAn automatic index generator, which is fairly small and does not rely on any external files (which may not be there depending on external request routing).A U‘ is passed in to display the types of files in the directory listing based on their extension. Preferably, this is the same as the map in the Nÿ The styles parameter allows you to apply styles to the directory listing. The listing itself consists of a table, containing a header row using th elements, and one row per file using td elements, so styles for those pieces may be attached to the appropriate tags.ZfA very simple configuration for directory serving. This configuration uses built-in MIME types from XF, and has no index files, index generator, dynamic file handlers, or T.[mA reasonable default configuration for directory serving. This configuration uses built-in MIME types from X, serves common index files  index.html and  index.htmX, but does not autogenerate directory indexes, nor have any dynamic file handlers. The T will not do anything.\dA more elaborate configuration for file serving. This configuration uses built-in MIME types from X, serves common index files  index.html and  index.htmj, and autogenerates directory indexes with a Snap-like feel. It still has no dynamic file handlers, nor T#, which should be added as needed.$Files recognized as indexes include  index.html,  index.htm,  default.html,  default.htm,  home.html<Example of how the autogenerated directory index looks like: ÿ¤şdata:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAf8AAAFWCAIAAADogAPPAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94IChYlE8/LMqEAACAASURBVHja7J13fBTFF8DfzOzutVwagST0KqH33nsHKwIWRAHpUhQUUSwoKCKoFCmiAlIEKUGaEHrvAqEJBEgigZByuX67O/P74y6Vu5DwQwJkvp/9fAh7uzNv3rx5++bt7C4q8kxb4HA4HE4hQwBAXAscDodT+Lw/d/4cDofDY38Oh8PhcO/P4XA4nKfU+yPu/DkcDofH/hwOh8MpDGCuAg6HwymUsT9P/XA4HA6P/TkcDodTOGJ/nvfncDicQuj9Ec/8cDgcTuGDZ344HA6nUMb+PPPD4XA4PPbncDgcTiGJ/Xnen8PhcHjsz+FwOJxCEfvzNT8cDofDY38Oh8PhFI7Yn6/54XA4HO79ORwOh1NIvD93/hwOh8Njfw6Hw+EUBvhdXw6HwymUsT9f8cnhcDg89udwOBxO4Yj9ed6fw+FwCqX355kfDofDKXzwzA+Hw+EUztifZ344HA6nEHp/nvjhcDgcHvtzOBwOp1DA8/4cDodTOGN/nvrhcDicwuj9eeaHw+FwCh8888PhcDiFMvbn7/nhcDgcHvtzOBwOp3DE/jzvz+FwOIXS+3Pnz+FwODz253A4HE5hgOf9ORwOh8f+HA6Hwykk3p8v+ORwOJxCCAZABbHh4I6T44/9lnM7svjU6o/nDm9RK4B4O0vb+JMF8cd++bWJvoDEzpRfX7bhoGdLaQtYjNw3ocwrX8Uf++38J1X09znyoSjWq04eny7Lw4ZDXvn5t/hV3csJGTtJUJ2eC1fNjzv2W/yxJfvee0b3+LciH63jW6HeCirzk16pevf8ZbPivhAJkl9gkbJlK/d6o3Kv55t9MuT7Rf84mJezMqQvMDQRL29b2j1s57QV6+Mf40s7yvIHysOR/5difejkcemyPIVCgRHPVoXri8/EK+miGqp+PuPlrkaw3vjn1B1X/NkU+YnNlHppHaeQZ34evTEzYKCqKmUAAKd/fm7gEZPHQyBAWBNWc+jkMRMa1fhkTv+rLy/YmZru/xmlzHps2ug6Pwh2s70gxyADQR9YJIeDfcxgwIAqzK1koLnJ+VAU61Unj0+X5akJzFi9cT2c/OveWy7kaRQpUqaaESBuTY/eqy4oBOMn9q2I97aOw71/ATgwyqjiVGUFAIBaFbtJAQDGAAEgot48NPOdVGHZ9HEVm0/pt7XN3JtOj/Uy6rI57KZbZj0RtYAKaLUSA0YVVaWe/zy2Lo1SKjsVRb2vnA9BsT508rh0Wd7aQKlUvWOEJmX/nzFOABEAGFMZQwIAJF+/YzEzQcdEjJDwJPr+zNZd87SOwymQAckYU5nKMpMDCCGMARBQRZVtSuqZBTP2mQDKdGtVRZP1PE3jL39POL3i1ya6LHu1LaYtjD/6+aA6jb/4eW780SU3/vr43QgpW4VScKtXB65eM/fG0SXxRxedXDr6o66ljT6ajnRhnd4YuHrNnJijS+KP/nRyyagJ7cL1mc5T02rGr1cXtQwA0Lf94NLRJYeHl9bkLCG82+DhGzfMj3NXt2zM5J7lA71U50tyodKAr+KPLjk1oaIu+/FNJ8+NP7pgQTNDHq45lFGVupXM2P06xKti3QZirP9i/+Ur59w4uiT+6JJ/Nn2+9L12DYNIjqyPT534LFnbdMr8+KNfDIqo0Ofd93b99XP80SXxu2esm9y1eQjxHqcEPTNg4gcHdi2JP7okZvOnc9+oXqnV2JijS3b2K5bVH5OwdtuOLok/+mm/ojg/FglMKvFcI13a4T2XbO76wket+S12bZ/yAFDz3XPRWxOi3q6ry6p4pC1Re/ik97ZvWhB7dEn80SU3dnyz7tOebcPuvTzkr7H3s0DIr4Vka52dOz1OuhkVwFveslaJdaIhSHJHjAyoKquylSrOpFNRp5QWrYtGNChK/o6nAICQABqJEAQAgHGWMtx/Fh/8zbDiLPbg0YTQsMRT/yoZByB9uRGzJk6oJUHi5ci1MYk4pH6bekM+qdul9qxnvzqVSHP4uogP5r8/tAKiCRcj195M1ZVo26n+qKm1m3w/ue9vcQ4ABq5Lvy+cHN/p41cqkGs7vlh/K+FcippFGhJce8qCMa+VAppwaeP62FRNaNO2dQZPqvNs04XPfrz/pnyvIu6VnF3f+tfpof1rd2hXb87VA9b0o/2rvtnWD1L2LD5lg/t2W7bfEfJ9vG/FAiBtvZEfb3glVP33/MY/Ym8r2nJ1G3V8qX/bJsV6vrrypD0j9PeuE5xLyZ4GhA+dPTnUeX7J78sXJktV23Ue0K3Pqhp+XV9bfcaR3UxDGnz764jnQ8By5dSq0ylC6Wo9h41vl+CQ0huH7m13bo32EhxryzVuE+g8vOWmlRCEEKOmnT8utJav8+7g+gGJ+6cvuWoy34xVSUaZUtnOK5f2bSApMceOr9iV5tIG12hcr2GXF5fWL/JSn18PWdiDNfa+FggAAGr+LOSe1nHHx3FnfgoIjwUKWNCmB2kMEQlhrDCgttuXkqB1aEClIgLEuwAAEAN2T/6CUUpdlAKAWNy69YU+Px8yI0QEBCT9UKnmoBETakmmXfO6fLDrugsBQnhmxWE/fDLx2be/PPTe27vNWfy/VPOtt4dWQKlRczpN3BMrI0BIWth5+co3mg59peu26WsTFabIcXs3/5xWaewrFcRr+5csv2zNmgvGxg7jh7xWCu5s+a7bJwfiZQQICcE1Jy6YOKTtWz+cvPTC6kTlPpIjRlXXvwfnH+43r3G9N+oaDu6zMgBgrEij9u11EL/mr1P2h5px8qpYt4z6CkNeCIXkXX36zN9voYAQEv7o8/2Mbxu1HVYncuBBm7shPnXiq2RGKXUxCgBCqGVTz5eXHrNSAITWH45fNnNSxTZvVokcfcqZxSP6tRnz5vMhcHXZ5z1nnUtmCCHxi7aDNn/d0s+Ta8pMNcnxO15se0ASwGJW864lxnDZNvXD1AufRjsZ0gBTmZLy96bIs6WEAYPrByScWr7ywB0koozkFfJrO+qFBpJ67Jv3XlzuMVCkK/POkq8nVGj8asTKQ8cdD9TY+1ngXcoYA6rky0JytI77fk5G5qeg1htlXAQylwwiTLCgw6IOUZfVBQCCQfBIyBijLofqSWV4TmSUqi67e+e1NRsO305VnBamyCy9ZKavMLhnCLCLn37+52WTSbabZLtJSY3+6dudd0DXqV+tEJwpANOUfa1rMMA/X07dcjXN5HKkKg6T/cqWSdMj5/505BZDjDKqOqni9NxNpS6quJgn040AAAXWGNRKB87jE77YGmP2lOC8fWT6p1tvA67Xp3l5Ed1Hcgaq4pRtcVG/HkkDbfveNdwSUhTYsXd1EWKXrotxMciPhu/Vc7bNq2IBEDBgKhMQgH947eIqs6cpdpNqjVnz/ujGnUYMOWhPb4hPnfgqmVGqOu2KygDg4vLIE8lmxWFWHCbFcuPg8RQAQ9lQLcrSChRQ9a02ekjbPeH7/betqarDpDpS47cu+GCPKz2vhQAQA8RUWbbdTUqIvXvX5KR5NUUGwHBw+3ahcG7vsTSMADHKVNmhyg5GKQAAc6myg1HVo0mGGFOurlw48auZY1dctNnTFLtJtqcqqVf2HEsG0IUZhQdr7H0tEAABY/mykHtah/lKR76lr/gsiMwPZJ2o5xAAEyyIKtX5awHAZXYxzwGMUeqiGSlshACAIaCqTBkAqDfOJbgQQggxjJHbpzNKQirU8ANQpMav9S9L3eVQYID8ggkALhtRVnvwjt0To+HAUjUDAP49efyujDBBwChVgCZHr1p8SeOHiAAEIVVAOH3ujAgiAiCcIaEY/kwlDHB574kUipC7BBVUm/nCgWO2zt2LR1TUo8tpkJvkCANCTHUmH1mzPqn56/U7tCt2fEWCSsIbvVkT4Mz6tXEqwxK6b1SLUOYl4F4lZ49771UsAFBVUVJP/7AmocMrER+uXD3u30u79h+L2ns46nDMTeaPRI1Hhlx04qNkAEapTCkDUOKvJsmYYMBUlVXZZkl1AACRMEKIpUunKV6lKgF2ad9Zq/v+EKiqk7luHd8RA60qAzDImQZ023ae15gyRkKq9yoP0V9HJyIREEYIIyIikq1RCGP3jWvGqOpKOhe18RxViV/RyrXLVygTWqZUyapVI5q3CAYALGbKn4/G5sUCEcq3heRsHQ/9OQWe+fGZEEIAGBmKVykCACkX78r3H7wAAE4z1Qk6LULYnT8BAEoVIvn5AYBQvveA8l7O1Pnp06fyVFWxqNUDgM3iFP1FUQTKVMVBXTaquihVMBEAESxqsSoDdueyNVhId4LugSrq9ADUYnZK/qIgAgOqOFWXhTpTE20AetFPQlkyFV4lx5hImEjUdumXtbdfH1RxQJuQ1b/dqdCjfQQoe3879i8T0CNYaMQAmMxcqQe+GNLpYv+RfVp3rla5S+/KXXq/CpB2av3K8d8dvOC+auamk/uiOkEraDUIkKo4mMPunkDgzNvUDFQFNH4GAKfZpWr8RSIApapsU1SL+a6V5kglElHQBAAAImLedcQoK1qvWXWI++qIWUESAgBCCNIySgFjAACkwZIOaPodWqYyVSHBNUZ8PHJsx9J6z17XrQvRl+PUkmWJj9vs92lsXiwQgXuGnA8L8dI6Difd+6MC8PDZKkU50tAI4SIN2tfDAPEnjyRTAHLPkSjLY0TuvxAT9ESkWdwXY6oqW1PtAHBtaYu+W66qBAAYU1WXhbqsWNAIuiAsaDwZY6ZQS5odAAxFDFoDljEQhjBRMcGiRgvI6c5kI0AIe0YXEgCR9AALqKIo1lQrgNa/mFFrsDIMAIAFYFQm+mIGANVmcrL7So6wiAUNVc2X1kaeHzSoWs/6Jdef6dcjFKz7Fx52ANbnrctyVbKPmzDZz8IMGFLSTq//ZdDmVYJfWI261Vs2q/dizzp1nh28Aic3//KyBSAXnfguGWVE6QjrMFHdlWGiZLkoIrdWVVWV01KsAMGBIQYp1gGYEYYBY1XxCzLg7MaAMEKikE27ebjOMaZv2K0S+nd91C23VAgBAiQgTNIbhRESs0wwCNJVGLXo64kRKPHwlinr/z75T9w/1++k2RwNPlvSqmxg9iW2eWts3izQM6nJu4V4ax33ehzPCHdnBR7xltUt5PwVENKVe/udhlqAC3/suSYjzykoy0nZjvcUiBDJWg4GBqA648+ddwCUq98owKY6U1VnKnWZmeIUwpq+N+GNMb0qBBPmKZxRV+KlaDNAePW6wQJCgBBCRBSkoNrjZl87+tOytkaPh0OZ0XuWGhkCxXHj7ysUoELjuoEexWJCEJH0FZvW1wHEX7zuuL/kiGAsaBAizthdC05SKN+4Z9MW3YtB0rYNR6wCQnnushx5IF994VWxGBAh2tKtRkwYM+WFIsSW4kq6cnLX5u+nTu08cFMcQEi9qqWkLBV504mvLoOssuH05mCEEEY5C2EIFMf1ExdUgIr1qvphhAAjRARChKCarUvnNAaE3Gkb93qfvG0U+ZV9vrZwZ9/R6yrJdqIvBRJseKbt6xEIEre8MWbR4i1HTl2+aXaYKdJUqhgIAAjj/DY2HxaYPwvx3Tq+FfoNF+gt33vvRmJtWNXh0z4YUw7gVuSHa267skkI93tzQPbSGCDz2R83pgCqMvmjdhVFlaoKVWXQlHz1i4nvvd77tSrYpeLMhLTt4uI/kwAqvjusbpiAABBCWCrZbHzPIFBiNkbbWcadNNWlAGiMOhFluUcKiCYdm7fTDto6n4+sH+4ugWESUHXc5z1DAc78ceCqcn/JEWCEJSxoQEnctuS4HUqNGtMmDO78/vsNGxYB/f9K9npkDsUijEWiLfHsWz0GvTu4exiiiktxmF02sy4kOABAvXM7Wc1+7/Renfgo2Ydsmf2AMva7tZp8Yu5fFvBv/ln/ygGeu/RicOO+X3TUeSkZS/6B/kUC9RLO2y1fynTPNGuqtezZccuBhDwpkDJVVRgAiKKe2lXFwVSZMVKq05BJdQAARImgfDY2XxaYdwvJtXV843d9C5Zar67+2epeSwFE9C8SUiZYAgC4e+C9QYuOWP2w+H9MVBECZjs4/fM5Nb4Z3mLkge2d/9x9JQEF1mjWuFEogpjNo+ZftyICAOlu3XFs1tR5DaYP7TTsYNXo9YfjzfribTpWLyfad09bvO5O5gpCJSk2EaBIg2Gbfrp2Nmr5qN/iHO65PU3d+tlXS5/55LWuww7WurDxcGyKFNqkba0qBkjZPWvo77dUZsjLzBsTggWNqjjuHvwjMrXhy0VFuLp5eQwCTB5ADQFtB/1RwZEzFe2Mnf3hr5uTaC43U5SEQ5OXdtjwWuMfty3us+30+STZv1T1nu0qGFnMd7OO5XhU4l6dPITnitxaZWlR0777o8GHL7w24VCj05vPJEP4M92blZQcAFrwrMRJhxRtvmr9q9Xh+vieX6xIpHlI+pOIjjX87X9vuKLk6SFYxih12S7+teRCrw+rtF+xKmDpjmtJOKBi3Ua9amsv/J1atFagsaiegJnmp6H5tcA8Wki+W8cpXHn/Aljzk2X5BwmpGhGS+ZNsjb14fvfWjfOX7rmi+AlaETDytjooa/7I6wHAEEaYACYs7cwXA9450b/v291qd3mhEgGw3b72588bZiw+clnWYuzJECNMEMbUdPrzN8acfrPfkG61XnqpGoAz7vTuKXN/XXDCzkQ9YPdsHMmxW979vu68IfVLVakcmFRMvyLeQTHCAiCsJO5/v9+4QwP7DO5S87kXqgC1/3vx8PfLfpuz8YpZG0xElD0W9rUmhyBRwrJA06KX7jC9/GLA6ZX7bjIJEZx3v5mZfNGFVo+49wgSrs2RjMtULANgqqy6zEdnfdgttt/Ylxo27dG1NYBquX1i87KFP67dckuPRG2mj/amE7v3Lsve3oy/s2VJMg7AgAVASL2zZ0xfNXp03wFtar/8DMiJVzd889FyvyFrh5Rw2mSaZTXRPRrI3ZMzKob1aBEon9r3t13w3OPNKjDKvoYKPHeOqP3S92+OcU0cMqh9gwEDG4Aj5ezRQ2P6/rrO2mtvZL/yLSJCl92JU/PR2HxYYJ4tJNfWcTiASjZ56xFXyaiiONIUuwkwEXUBSJDSF5kwpsqqy6IqTixoRF0gEXUZL4ehilO2pzDZRXRGQeOPMPHstCZT1SXoAgSNEWUPfKjiku2pqmwlREO0fpho3DsVpwWYQiSDoPFHREhfceFS7Kmq04ZFjaDxQ0QCxlTZrjrTAGFBFyRIBkCIMao6zbItBSEi6AKIqAfPYkdGFZdiS1UUGyFaQWtERARgVHGqDgulMtEYRa0/ImJmc3xL7l6wpDrSZMVv+B9LPit/cniXaRssBpTn2J9RWbGbFIcZE4lojUgQs19/CSIEIQyAvCqWAaMuu2JPZVQlGqP7LT2MKorTospWIuhEffoNc/cKSG868Vqyp+22FKo4s7adqi7FbqKyjWj8BE1Aer8wqrgUpyMsVHImW0xMj4nAKFVlq2KXm361YuNz4saRo4edUNOXXamguAAABAljct87nIyqisOsylYiGXL2AqOK0yLbUhAWREMRknGpY1RxWmVbMmNM1AUSSQcIMaqoLqtqtzCggi5Q1AZk2lWeG5tHC8y7heTWOg6nANf8MMaY4lTsJkAEkHvVDQNGARgWNILGHwu6XFePIN87M+6xiYLGDxilipPZ0txjjKkKAwVjDRa0CGU6CIxEIvkxSpnqVOxpgAUASlUFASGiHgsaSF8NghABRFTVhRxmYEAkAxABACEiYY0fAcoUWbabEBYAGKMyMEpEPZH0gMUcS0FyuYeBkIAEXbFmr4+qDCmRa6JMEhJIfjrLrWSqyg7KVJRNk4AFiWiNWNAi70/euV+4J2BBUp02xZmmyg6MEaOUUhkTCYt6lKUtuejERxvvvR/gs38RkYih1PClXw4udumDLu/+FMfcbk0q3WFMZ39wnd5yxeVeuMwAmCIrDhMACLoAhvXo/t6fUtUFgBCWIOfVAvlaCoUEEQsaKjtUl5mpTvfT0oyqgDEwxihljKH8NzaPFph3C8m1dRxOwbznB2MiEknHFJkhhBj1rHpDgIiEBImIOixoMcr29mmMCSEaChgT0b2ow10SFjUIE4IFjHHOmT4hBOkQworLxlQnoyogQAQT4kdEAxa12aIhz8FIddmo4mJUAUBYkIigJZIeESldUcQdmlGXjQEwRhFKX8+HMJL0GGFVziwBYZEIGizpiaDJ+pLL+0guhr/99eCXi/tXLGlE8tkPFly2EiPKz8ydIYyJiEUdqApDCBjN5tYYQ8yzAMSrYgEQIRLSGBEiquJgVKXuF/eIWizqiKRH2XrHu058lAwIu5esYELEjLZjRLCgAcZQjoMBI5q08o+YgcMqT93wY6dtp84nK4awim07VC9F7Hun/bQ1NXP5jOcpP/dZCOXhmTjARAAiEEHE2V9BygBjLBBRhzDBOMu7cRAioAGdv4oJVWVKFYwwwgKRtABMVZyYEPeqo3w3Nq8WmGcL8d06DgcK5mkvjImoQ0QESu+JVgnGBGFy79uAESZEayRURVjM+BUjQdAYgdHskWb2s0QtJiKliscDIoyw+0Xt3qoQdYhILP1ghAnCImCc6UcQICwJWn8m6gC5F2tmPo6AMCGSDglZSkAYYREwyeHf7yO5arlp969U0miPPTZ78jfLbolIk79pO0KESAZ39sBrF+D056G8KtajKEErYJFQA2MUgCFAgAWEBYRwjijZq058lYyRIGj9gNKsEwjAhEh64r4kZ01fMMpU+8Vfp3S89eyYPk1a9ezeGgAU8z/Htn288NdfT8pUG5ARTmMiifogAMB5e9oLEwFpjO5p4j3XBYRFrYgxIIyJkMNOBFGPiQiq6n6nBcIEYQEYI6LsbveDNTZPFphnC8mldRwOAKBSTQdzLTxeMEqpzBRFdVlV2YpFnagLwoJUOGfuVHEq9lRKFSLpsaBFCLsX3SiONISJYAgmoqHQvbSSWwjn4cT+3GAeN39HFcVpVp1WRlVMRCLqkSAU3tezYAwEU0WmdhMmdoTdL0+SAWMsGbAgFcKUBrcQzsPK/HCjedwiu/S7CIJAJAORdFnvThe6ySl2v7qHUNnBmMpUdzpEwqKeSHqEC2XAyy2E85C8P+dxC3YFQeMPogEQBiIU8oGNEAJBEpA/SHrGKDAGyJNnR4gUzoCXWwiHx/5P6+AmmC/NznoBAISIBETiquAWwnmY3p9/5o3D4XAKYxTBVcDhcDiFMfbnmR8Oh8MplN6fO38Oh8PhsT+Hw+FwCgM878/hcDiFMvYPLFuHa4HD4XB47M/hcDgc7v05HA6Hw70/h8PhcLj353A4HA73/hwOh8Ph3p/D4XA43PtzOBwOh3t/DofD4XDvz+FwOJxHD7p+x861wOFwODz253A4HA73/hwOh8N5GhH4+505HA6Hx/4cDofDKRyxP/+4C4fD4fDYn8PhcDiFI/bnoT+Hw+Hw2J/D4XA43PtzOBwO5ylFQDz1w+FwODz253A4HA73/hwOh8N5OhGAL/jncDicQuj9ue/ncDicQhn7c/fP4XA4hQ+e9+dwOJxCGfvz0J/D4XB47M/hcDgc7v05HA6H85TCn/XlcDgcHvtzOBwOh3t/DofD4XDvz+FwOJynB77ik8PhcAql9+fP+nI4HE6h9P7c/XM4HE7hg+f9ORwOp1DG/jzy53A4HB77czgcDod7fw6Hw+E8pfA3PXA4HA6P/TkcDofDvT+Hw+Fwnlb4mh8Oh8PhsT+Hw+FwCknszx/15XA4HB77czgcDqdwxP489OdwOBwe+3M4HA6ncMT+BfWOzzqd3uba53A4HDents1/1N6fP+vL4XA4Bc6jd8U888PhcDiFEe79ORwOh3v/xxltxa+2LI49lHPb82a4qIv4Yfvi2ENTR5cTIOvf+Sn24Mjy+vQZWEiXD2MPLb7ydXU/biDe0Xee66UvYg8tjo3sW1PD9VNASKUnrV8ce2jRsqa6h+EbtJXbdXyh9D3jSF9l3k5Pd0f1K+b52VBtXpRn546+xYQHEfvbz6tKOcavplSzGT9/d+PQ4th9079rW292voZ2jpI59/YwAiiQ7YFhaSnxt5PSt4SYZIWBkpbidJgtVvXBiy3Vr/9b5QVuEHnsBMu/8fG3k+JvJye63Hust24nxd9Oun7D5KBcP08+pMiLU7/eMaV70yCSy1GVWlYMwgAA2jK1G+gfSsVZx7Km7lt9e0cY8d3LW/ecO/6v1fR/D/PHmUfvhJ+MZ30ZU5kiMwYAzq3vj33riB0AAGGECSAENPaD5wZMJCIAMK2Lec7JQ7GUphcLAKXGvtd83YhdsbLCFJbXIgohlFJq2jN5XAMGAGLEkG92DgqFEz+2GXzMjAkiAkKEK6kgxghlikwZADD2f5suw7ryFf0ALDlKyjpkKAB+pm51/cGdaTi8bpVQ94hBAIw90NAGxhRqPucZyxgDFQOL6QHg9LzvBkWmqsDQcwMmEhEhkhevlb3kJ2Es87u+3jtSVRSHRXXbnCNZtiXJtiTZnkJlO1WcCi7z/e7lcUe+Gl2aKnarewC4fbcQFDHii0//PrA49tCCY4sGDqzhR7KZh6w43McDAAi1e3/SygiyXZYVd63uPvGv1uGHn2deO7Q49tDimC2fzn+9cjAGEtpmy6HFsev6D3p75K7ti2MPLTgy+6VOVeuOnznt0qHFsVFfLOhbzojhfjI8gc6fqYrLIltTZGuSy3JXllUAAGqWbcmKLL007+fYQ4t3vxEuuvNqVfoeO7Q4dutbTYrVWn5gcezOMQNf7r9h46LYQz+dXvxmv4oat8E/ZSoqoDEiK04L9Rn7eDdjAKlch34r18yJPbQ49tCis6vGTmodIqEiAxd/NrI4APj1nj8v5tuafumlUuqSHVYKAHB7zz8q6Cp0KCsyqqnbvDhA0t5oB3iuC55+bfnaoPXr58UeWhy7Y9rKd1tUNXg8KBEeJwAAIABJREFUnFCk+rhvvrxwaHHcrmk/9a8QhACAgSJnjuVKpd9bO2dBHQCA2h/Nid31diN9ac9P5UguNuO9ZOAT0ic388OoKssAAKDpOvOnUzt/O7Xzt1M7luz7pkUYRlnWSqmqIjNI9/7aMmPmjJ/QthS7eHrj/jhNtaaTfxwzqEx6eochxlSquNymvGFbAoC207svNjdQqmbG/iigxtSZfZ+N8Is9cmT9vuu2wFJdhw4ZVyU9jRjW6uOObMfyLdvvCsXrdVn004je7PT8lWfv6sO7jHp7aHnhPjI8qVNUBAgzYIwqarq/QQghmhK16qwToEKXemVEABArdawfBpC4c/ffNgAA0NWYPKpqyv6oVSfSilRp/tXctzoH46dSRQUzJ1MUj9u/J9T1ZcZSxe5LPmvfLOjWulVbFm6+QktXf3vqqMFlnJcPnI5jAACJ585sPJWqQIb7V6nsnl5bzkTFAAQ0b1BE0JfqEgGQdGJPvJzp/bFfmwkf/TasSb1Q5eqFG7FCsWYvDNj8Q7eqGgCxxLBZY0c3C/Mz34g6nFRpwJsvh7qlZJljWTGf2X7wlBUAwHb+6IbN5++oWZZE+rIZXyU/CbF/QWR+njjXExBSMiD9P+ZASRAwFtOD+SyXFQb+dXsMKgdw8ZdeQ6L+VaUyfT7ZNbLcwBdK/fJtjCPnfMsRvXheYq1pA8Nafj1o8/PRmdMDkG+v/va3C9rLv665lAqBz86fN7duQJVwwhLcIyJx9ruzpl6mZazVO4wpBUk7Bo3/+birWEr97z6rWLRecdG/WJ5keJLiBUxA44clHVNl1eHEbpVjvaALQowmHdmy3Vqre+mmXYtvnRUf2rN1EEDSunXXLHIEAwBwbHv/o4E7TVTcEv3zt59F1B/ZOvBIwtOmoscwK+TdjIuLWnu50gBw5+q+qL+2nU1ZtKl2BXv8mZiEhBlzG7RbMKakeeesme+eZYDxPSkK9e7p4zFQsVyLiqUOl66vAeeBg5ftTTKOEUq3mdw9EODmN69PnnneQYLrfb383T5Vek5qufet+NavVwSQo8f2nbYi3iaUf3HvH33LAQAiWEgfy65bG77+Fqo3/ak+XFg+f/gWq6qtnFG4r6G9YmtT7yVzvPHEeX/nlmFvDzziZAghjBEWmEIpdrkv7QhlvcKjsKoldAAQ8cb+vW9k7A2tHOqHYhws62UCAICmnp7x2e7n57Yu/fqwtxe6MnNDyf9EbTOjrs0mTHmuQd3qVYsiABAEqjjtDAAg4cT1uy4bTUu0AQDEn7uWkiIzescCAEgUxfBnvMkQUSyHDE/U5RdjggFEijAVqMcVIBETibnM8p2jP+1I694r7Pk2IQt31+seBhAXtfJiqoxtlAFA3PYTcQ6bjLDj8NG7EBFSulpo6eCnTkWPX7KOejVjEdIObt6YUq1X2Q7fLugAYIs5eXzd6rgjJ2xM9WPuWwiKgzEReUkRI0fciSOp/cpVbNyrc5EiACd3XDE3zLze+FeqVgEALv65/GS8iyLsOrw0KqXPy0E1m4QG7C0ZCgBXdu++kaio4LpyYF9y33LB4JlYuOuV7UxJn1dSF6OK6vkJgPoa2kWLnPJRMser93/invWlzhSXzQEIsKgTJD/GaGa2J6tPpx7bUU7O7zvjko2pgAiRDOBKNTG4J5BBDNS7e+dP3NP4x1alBw3KqExFxZr/smZ0RyOLP7F3028LdnYaOqIKYqrsqVSVZQpMVRR3+luxuxhQxaGoHqv1LoMzyfTU+TWGABhQxXRi+a6EXr0qdG7UVtu4JMDlP3b+46RUdF9QBT+JAJOpywEYAQBTC5GKCqhjfJux7HD9u31w12ub+3R/vl2DltWLlavbcmzdpo00bz+/Omtu2EeiwnZja7TSp1nV0b0BIH7H32lqw4z8kKy4VPc4dCduVadNVRkAMCqr7vtq7gQRVZnqGT3ZxnJWx4QIozQ948QYk73YjMZALbdTSrfwWvKTEVbxu773t2XmvofDMm7tej9Otsb9fcMJIJQs6bx25ejJa84mvce/3rJFMa/nIERE6krY+OWiw0rW3WKpts92NIJ8eHq7ATMmzt910YHSbZp5AmHJSMT05dVIQzR+iKTPXlWLdxmKsqfPsyFEEJEAYduFP1fGAZTp/uWroQBXf9uRLOOMm7hle3evbNT5Y79ynZoXAYCYUzFXCo2KCq5vfJgxpUUb9Rg/tHu9pMiB/QaWqzfgjT/TAIRaTUtrMWYMAIgo6gD7uAfPLH9HxQCACAApZ/fG08zIX3GlXDh1HQCqdO9Xt4So8SdF6rzSIRhAPr0nJvFqdBwAlG1UNzQISwZN8bpNi95rTTosSB6HSHSYZK5O9Dq033u1RYtisun+JXOyZX6erOAfYW2QqNcDQghhhEXGVG/unDEmp+xfsji24dBS3dauCNtwSd+2U5UgiD/9y0rF21UQCzrATkdM5Lgfuh4YUz69NmpJTHFCWU2tLkN7QVyFTh/XAQDQGCSUeaKEiAulBylYkBBS02esPmT4aYkC4lPn/REmIhE0iuvmqt9vjB5bJpgAnN285TbOmjSuOnzavlYXE4Ij6hUHMO3+dvu/SZbCoqJHBWn98ZQD1sxRYf17ycBd3szYqFFJpVdf7xwKTWvU2XnCEty8jT+A4+CuW07muG0FAMMLX3xW6fjqVz47k8ruDVVZwvFjN6FSaQDXuaOXXaRyxuCjsuufdVO29VjUqey7S2Y/G31HqlCutBbkM8smRyXaHZFzTjw/tV7DeQvGNNxnqda9bZV7zYlgQJ55B8ICYAwU5T60T803Wy/fv+THeQzx2P++tq0lkp6IOixoEMK5TRKs0Z+99uGMnddNpeq90KkKiTk2c+Tn0y/KPsIjHSEaxpwXFn81J9bjvKniTNwxa8jSc7elGu98Nnx4lZgZ8y9TgPJNyvln9BUC9yoYz5DwrDdNl8KrDJeezvVnCAtIkBCoMX9u+BsAgB5edTIBhCx3429+P33b9WKV6xVHiWc2vfPazG3JrFCp6BERGFK6RNGMrUpJKcW7GVeAEz93G/X71su4wXMvjHitTcWUM8umTBq5PUlVkzbNiTxrAQgJL6bTa5E3V0UE540jh9MAAC7svmHOMRjVpPXjh70+78DJ22LFauVKq7f2Lfu6w8A1F50Ayq3FI8ZP2RHnKN9wcJ9qcuR3X0bnc/5/j818O2Ly1+dd/2/JhW1OmGqRC6Ti6u0H5/1gKtudlrtAVUEfKGiMKGMqykBVbC5LEmOqqC+CEXLZUhhTRV0AMFAcaQBI0BoREajiZJQJkg6LeuSORRmosk22JVFKJUMwEXSqbJNtqapiRwgLGqOg9aeqU7GnAUKCxggIKY40xqioMQLCssOEAImGECJKisOiONIQESV9MAC4bMlUdQkaPwBQnVYvMgiajOzQkwtVXYojTXGYsaiVdMFY1ABjVHG4bCn6WkOOrng21HX87S5fb7LoVdku44prjnzRmlz9oNuHP8e7FKcZqEokP0BPs4oeaXe47G7DI5IfkfSeMYLcSxfsqsOcw4wFyQ8LEqUyUIYIYaqqyjamKoLWiAWN4jBT1SVojILWDxMJ3J6dMVW2uSxJDJio82eqqjjSGJWxqBe0flR2qopT1PgRjZGqTtmWApQSrT+RtFR2qU4zZVTQGhHCiiMNGAg6fyxoqWyX7akIkKgPAkRkewpjqqQPRkSQbalMlQWtv6AxUuryDHMfQ5uIWsZU7yUbgohoQORxX+FybseCR575eRrf8IwQAUKwoKGyQ3FZESDGVEREhpCvWysIYSxqiaRnVGGe57wAIQKAgDGquhAgxigwRhnFKA9zJoQxFpmg3CsDQ0/pe7URNtbrN/3V8tUbVwsFSNq0ZneaACRrW5nqSFMcMqMKFrRE1AJCTC1MKvqPYVRRXRaqONKzJgQTEdyPxGQ3Y3eChikyU2WkCoCAAcNERERCmCBMQGGqbEMIg5Zggr0MMQEjhBnC2PP8LcocS0TCok6VbarToso2YBQYI6JWEHUMEBacVHYoTguWHYyqjKp5d82+hjbCCCHJs/+BSi58iZ8nZcUnwkTUMEoxEbK5BcQQYCJoGKOYEMSQ+2+EBUwkpGUqJlRxAQAmIpb0mEiZyS7EECJY0CJGESIMIYxEIukZU5mqIEFCWECYCBqDqjiBMcCIiDpgFCOCMCGC1p3qBsCIECxosPvxdAAiaBDCmIhY0CCM7pXh6XgXAkIYEZGIOiSI6StDGGX+dVtUKwG2K1G/jZ15yYqM6J7TEMJY1BONDolaBEjw1k38dRH5T+JiLEjAKPO4egYACChCCBEJSSiHGbvHCABQBIyqwIAQDRa1RNQijImkZ8CAUkAoSyYTASZY1AIwhAWEEJZ0iEpY0iEiYqoCACICQhghImj8ECJUcTKmIkywoCGiHhENAhA0RgUwoy738QTpESKABYQzxy9ChAgaijAiBDAginMf2ohoEMKCBu4tGWEBeCzhPfNjLaDMT7t8ZH7cHpkBw1jIFmW4XzxCXcDAnShgVPb8jTEwylQVmMoAEGAgBGGCIMe5MjCG0l8e4q4IKAVCMBIAAXVHEMAAsDs+QoARQsxj6yIgDExhqgoIYSICAFVlYAxhATABuI8MT3CYyZh7noQAYywAQoxRSmXVYVGcZowF94wbABSXTbbeBcYEXSARNIDc72hydyVj7KlV0aPtDspU2W2WWcNJt/tjjOY0Y4QREhhQoApjDBhDCHuMFgFQlVIFUQaEYCxA+mT33uHGGMNEACCMKUCpuwTkvv5QlTLF/ZwtwgLGJD2DRKmqAFUZQu4jARAQghAwVfEU7vmbIUIACcBYZr25DG2fJZPHfzJ5LuqRZ36eiEGGEEEC8ZVfQVibdZKQ5TefZ2U5V5N7RZhg8JaAzpaVRiLCmf/FQtYy7yPDkxz7I0REyFiZQylVnKrTosg2AIRELcISZAkcGQJEBCRqs49DhNBTq6JHPRUTNL6TCsS7GQMG7C0BgAXibX8uww2BBCRHxwrEa3YBYSx4f+UyEoQsf5NspWWp1+fQ9l0yT/x4qdFUQLE/5ynDZrWfjr6wLWrfv7duVyhXunXzxjWrVtYbdKpKz124vHbjNlVVn+3WoWb1CEnkt3M5nMfgemOyce/PeQgoipqcmppw+67L5QoKDAwtGmww6BFCjDFTmjn+39uMseLFiwX6+2PMvyjH4TwG3j+Ne38Oh8MpfPAojMPhcLj3f5SkKd3CbZvS8vnTf1Hdwy754hz7M3qzv+G/qe4BhYzsphf99aK/vn1OqdIiu4W3f9ja/g/KzEd1jotzejyjF/0N7R+jLuBwHjfvX1Bfd/G8wcPr5i9svqXv7p99Z5rSLdy2Oe1Bq/Na5n/REKv6wyzaZ7efyfpfVfdAze+52SabE/5oEeDtp1s7HlzUtMhu4e1z9sv/WaZnY+ZdA2u3+eG6nN8uOPHDrKt9dt81WXc83C6gSft+eLNpRLDor9eUa9R7yvrLdvYfdFaWS3U2xbpurBvbopJR9DeW6jB2Tawr10Lkq7Pri/71Z8XID0MkZr2yfvKrjYoH6UX/gJItXv1qz23Fu0i+hHdvyo2fOxm8/5R720G+9dcXrzcpVVQv+ofVG/rLWatXzTPbjW3Th7QpF6IX/QNLpcvJ7BeXjm1fPlQv+uv9q3UYseKSDfJee+bO9K1o711mX7qSE/6a8kqD8CC96F+i/tvzT5hTI7sZxJZzY1QABMqNuQ39c5SWi7r+4w0DQgWzed6N858dX1ANUeGmFTWKwBg99qI+tmW6NyVm2WcHmk7uX1bKbxek3LQWbxQR+JC7QL3xa78+K4JHr76YlpySsHNmD9cfPxy1/AcND+i12a6YE9a2CMyqWOXagj6jD7eafzE14eLPTQ8N77/wquy7EJpyeFMMxjGRR1LYQxDJcnjmr3caf7Q5+rbt7s2dH5Rc3b/P/BjFm0jehXdv9Nbadz6/WMZf69tgvJ8Oafvf6/zmX+UmbDp313rr+Kwax34+4VXzlkPfLIqt8/7Gc4m2uzd2Tiq//s0+P8ZYz8/qN/Z06wXHbtuSbp+Z3er0hH4zLrjyXLt7p2dL2TawdOlXxzby9yo/mA990H3IgTpT911PMd/Y9WX16JWnbQgATi/+/ZqMQL76x+JTgFqtTFDMnorS/7ZHdQt41A6hQPP+Kts+3hquSwtrYP/D/WI1k9JVl2bUpRl11k2m9MPcO8Ns+1LVPmGZPzE7XTXGGhGYZjRaXpiuplAAADlWHt3EbNSllWziWJt7maHWqV/aagSmGYMtw9dSxZeQJqVrMcuYIdZwXVp4Q8f6OM9uOVYe1dBs1Jlbvqckqtnk3JOq9g3LXt3DUJb58rqPOxU36rQVW41YHeMEADBFdi1Wc8yQhuE6IbzhsPVxss+d3psW2VUnGHWCUdcuq6jMfnnVmFYRgYLRWP6F6QdTqO/adYIx7Pl9qXv6hKUX4qNMOXb16CYhRp1QssnwtbHpcoY2mvrlCzUCBWNwjeFr47J3AUvbP3U+DBvfPAD5aJEcu2ZUwyCjLqjle9vSu8At0nN7Uvf0Dcspw/+L7fyf0RVHv9+7Zqhe1AaXb/b658tmt2aRXcPTazGl/32fpj0Q8vXIpQmdp73frqSfoWSH8dO63Fqy/qbvvjWfWvtP5fdGV7684VRaNtmy/638u35MkyCjLrj1sHcahfpWl3/7uet/HNmjTgl/SRNYueu74565vOlSWv5EoklbPnz/bI8f3q+pzWfb6a0/v1hX4dtVnzxXK8yg8SvVcvjcma38vcs5e80PQzrXCPeTNIHPdHrnnQr/bL1sunk8sdqwoe3L+EuSf7k2Q0dWuXM01vlAg/BW5Fcbig0fVd/gXc6ETVNWl/7ql3EdKgVqdcGVO4364ZuWfgCGMm3g9xWXnM6Lv62TupT143l/ALDQnUbNyTvG5W3V98YoSQwgQNhs9zcn6FsEZjkscydZmeBvthu6BQAAO/GJbfx5Yf4ZY2Ks/jWnctEKQNnm0Y49zXSX7hh/aaqMHS3fpT7KBACLutYkbY43Hp+ON05yRTtykzPKT3PyjvG3Nsq4cUoyA2Bs6xjH/ja6f+74fWxULlpykfMhYdo2uO9CadSef5Nurnrx0sQBi264PYrlfJTflJN3Yn9rs3vcuC3JzPfOewnomSXSycB64pOe4893mn8mNTF202vOHRetPmrPPN0dv0R1C/BRJk3cPHrknmbLL9258UvTnWNHb7zrfoOn5cRa06DN8SnHp5fcOGlOti6Qry37dH/Tyf3Lij5axO5uHTNqf5vV/9w597FxR3oXeBPpYaEt36zEuekfL9h9Odl1348P5NK0B8Nx8/idEi2e8bgd/TOtiicevemzWNvFjaeDur34XLegMxsv2HwdxZK3jxu+q8mKi3eiJxv/Om/OqzNOPrbpenDtcJYfkVjq/k9G7Wv5/eSWQfl+rMn2T9Q/RapcGd+kmGDUGat3m7j1lpIZwYR7v2gp5pidc2dfq9ihYnCNF+rHL1q466ZZls3X9yz4Mb5+72r6+5zuDeeln6ZFN5/Up5yPB1Zsl3dcLt6tSdGcXlUo2aWvceMvh4/8uin0je4lHptHGws072/AQ4cLxY2o1VCpxCn5gjXnN9+9fgje818bXbIehszUtC6NdIH4uUmapkZANjXyNB48XChhRG1GSKVOKxdtPssEAxk2UihtQJV7iZVT6S1nnuQsfkK+YANkVTecwoOGCuFG1GaEVN2QveRcbmk88BbQdeWJzR91q+SvL1b/lcEVYnZcsbllqzF0eNvixvBWQ4cUP7H2gu+deVbsmSXrxSEz321d2k8XWOW5SR83NfqsPc9lno88XWrw8LYljCXajBhS6vT6ix456w4b2aG0wVi51+uVU09l6QJm3j91Pgyb0DwAg48WWaM3nCoxaGjrcGOJNiOGPYoukCLe2fD7q/Lykc2LFQko1eaNr/ckyDnqyvjbd9Pydz8psxXUnubSBOowsh2Z2GP8SQjSOE0O6uNc59XtB1CzDpUrd2iJDmy77gTvctrOrTtWfPDI9iWN4S2HDs2hQ183Y2xnf3hj4N4WX46uIeYmUo4usB2f+s6GmlOndQnBeeqdbMeo5sTEsxuvt1t43pKUcGxK+XWDB65MUH33tSmyq04IKlbp2TmBH/48rKKu1Ms/fBY2v2O1YrrgYhV7zCs66fu+pYQ8W2/GTtOeGYuVV99vXwT5EFu1JNr1xYwkQwajrt2mNAAQSnR5PWTd8HHbKr3VIRR7M5gC2Qo09hdQySAAACEQ+dmZOV/fYJPZDQuqGp5jYgaJdvCUGXS/MgkUMwIAIBGJGW/1vK+cNpamAKhwxw4lAz0VBTyKd+XJ8Rvf7fyMn59O8CvR90Ci2fPNWyGwZJDg/tfPlpCm+N6Z13qSb1hCqoZLeao9z1mrRLvRI1JQKT/7bU+/EGMxIwEAJBpEluUbfPK1ZZ/ub5YR+HttkWq+YzeWDPSU+Ui6AMTw9mMW7Tl3x3Xn4rqhRVa9/tLsq75066tpDx6n6fwlZ6qdgr7R1I1f14MUlyZA52P4Kgn7tqfU7h6h10f0rJWy5UCCDymVtASbsVS6YvOgQ5py8PNeHadpPtoyu0coybtIzujZw5eU+GTWc+EPFPdirTGowdhPXqsVotUERPSaOL7i2bXRNs9sb8utqO4BOSe1W+xySsLFP95O/nLI4uuOmF8GTIh/c/PZBFtywqW1b8VPGrAwRvZ9ug9lxf4+ZVel8YOr+c5bEUMRrT3RonpKzjIDJuFdXisfc7vB4JZFHqNF9rggV6IoLM4EgEAxMase+Yv3WQ+E3N/rdP9XQmX82PmE7McIUFQHnjJTmUWHjILvMiEvy49yyukpU0RheohPr8ik5HEx0/+x2Y58Nmpt+Wkn4s1y2s1fG/mnr3hQUuNMCiBQTPEWXTFPe73uRO7XGFGF5rpiRgou43f3fIIrT7Xf2y9eyxSMRXVmj0ipcRZdqFHIpQtY2oGpP8Kw8S0CUGYX3NMi0T9Mb4lPL/NRdEHmhvUl6vee+O4z17b/4yAilu0KAwSq9bZFzb915XElk650/dD4/Vc8E2Tblb3xxRqW1nlfoJN6bN2ZOxueDxP8wrpvvPP3hmMpDHmTU/QP06fdTPGhw3smFDfWvN3muVVV5h5ZMay6Ad9PpKzCO6/uPpu4Z3jFQJ3g57lR1O7PtDy3XVuidilNlp9YHlSKxMCKHUeNKhe98WLyhU0Xyg0Z3qFcoCQFVugwclSFi5suOfK5HtHx97xZNzt/+EJxwfdZ+kptysVtPZ5Mc5QDAELxV6Ossb+0Mz4s23gYW4Fmfqx0/jzltoUd+NEVX0+sps9VJwTCJHYomnl8lx6/3hPmj3Puj2MuE9001XnYDEhPetakC+cqty1s/zxXbE2hij7/zt+kdAmzbjL5kLOuWFUPSI971aWLflTuWNi+ea5z1v/e81CXXSaGoACt62bUrBnHLBmynZ0/b/dtS8KBH+fH132+qt7nTgSApPAqATd2nLxLczF1fc3Xezrnj5u5P87qMl3eNPXzw2aftSMARPzDpNhD0Sm5llmlZ83YhXP33Lbc2j9vXmzNXu5+8d4F8rVln+xv9kn/cmLWLrinRfqqverGL/px3x3LrX3z5j6KLkiLGtXn3V+izsSlOl3JFzfP/PZ8eLNy/iVqBV5c/uc/VlvcnjmzT1vva12RXcLaZbWuvLogsWzPV8O2vv/17nirLT5qxvtbir/2bBnR64nmsxsuVpt+2eRQrA7HuenVL23426rxJqe++vMNby38fnu8KXb3nHnnbLmYn+nEjJ4tR115JXL/98+X1uRBpGzCB/Tc6lCs7u322haBrVbdjuoRkOe2SxV6dbf9MGnZ2SSHnHoxcur0KzWer673ps+0nWNenbji4LU0p+JIPLvh6+nnSzQv71+qbkj0nDnbr6fJijlm59zvo0Pql9bk1h332A9N2vbFKr8hY5v441y6jIT3nNAxeuygOXuvW2Vn0qW/78j/V9j5VGd+/HCbJGfNEHPvKGHGt0IwAjApnbVphlDbvlT15dA0g9b6Z8YNGQMZOhAtbWf217l3ogaf6adVVAZUMQeHWxeCEGEAwKjbd9rme+wVQsz99pAZ34lFca5l5lnO1nedNUPMvXeQb2YKIRgAoc7faptG2cuHWCYlC1UewU18Y5OJH9Xa0qtkkdDW88QetTJq9KvS+u6EmiEle+9o9s3Mbp6kqtedAKCrNXJSo509wvy17f40AZgiO2sFQ+jz+1L3vBwqGNw7wdDgs8hpFf8cUCUgOLzDQmgTYfBdOwAY6g0dGLa0XVF/ne8ycbFu333XfE/vCiGl+u1pNeO7HkV92l2WpT7ZuuCeFqGQzt/Oahr1XPmQiEnJ7R5JFzQe+ZJu24QOVcIMwcWbTTzZ/LuVYyv7Vx/6ea/YMVVDw9os1L9Qx5h7Ecx8Zuu/lbpU1ud+h99rv4gVh6yY2WDngEoBxSq9vrfR7F/fruj95qP90qYTxg6tSgjumLNVZ+OJjZeYNzlRcMcZs9sc6ls5tNYUR5fqRuzzfqx5z6QPo5JS9n3auqhRKxi0gkHb6Jd/sReRvAuf99UNXk+XIkYvG6+b36u0X1BY/YlXnl34Ux/vOSRj45F9dH+OalwiQBtSpv2UK13mrxlb2Vh93Irp1XcOqldMF1i0+tCoGtNWjK+qyXvtAPKVZV8dqTdhQMX7vD8UB3X4IfLLMpsH1gg1Gso9t6Hmh580MTy+T3shq0MBTm7mqHSu7BxxydA94DGULbJz5e9GXMqeuPS680lBvjqnfbeznxyZ1yaL93+iW5S9dXM7dvt70uEf2wU+bm9WV+MXtWu5+7O/l7X042O+sFBg3/YyaJ+kZ/D3hT6gtFaHPzey/NxXrTB8z8WnuHXDdj1mrTPv/+zbWy+NaGP77aebVUbdZ1LCecpu6wdDAAAgAElEQVS8f0F98cbmfELcoknp/IxzxOXHMvZHni+2Zv9ciredTzRPX4seH/yqdzZM6Vqib9ozfb5d+1wY/8pOYQLZnDzzw+FwOIUO/oZnDofDKYwIfDLN4XA4hdH7F8THhDkcDodTwPDMD4fD4RTO2J+H/hwOh1MIY//H5eNTfMvLZorsVKztnyauCr5xc+LbE/2mh3xhkjsWs240Fe6LdUDPv+7s7PHonjxgpp1vVWv5/TWZx0kAAOrdvbP6NynvT7SSWKL+i5+uu2TN5V2npsiOxdo+iMWaIjtKRCsRrZTl9Myd9/zk8/Q8HJxXQ7BeXvdxn/phBoloDcUb9522y/3eUNf1NaObl9ERra5E69Frbrh8CJ+Bcn1Re9195Lm3TAA5fuPETuWDJKLVl2g1YvlVR/7kzOvpXoX31XbvyLe2ff5y3VCDRLRh9d6cd9yUEtlRQ5rMvqYAACgxsxtoc/bOQ+qjB4j9+ZDm+Lbka0vTX7jGAeX6z31e/i149LrLZnPa7b2zerpWf3/U/B9UFNDzL5fqSFzXMsf3iAJbrU5UHS73lmsQkO3I+x2cF8yHZvx8u8nkzZfv2k1xuz4stfqV3j9ek+Wr8/qMOtjyp39Md//5pfmBoa/+eEX2JTwAgHprzahPLpYNyO3bXt7KVONXvTlgfbmpB2/bUm78+aZ5Sv/vLrjyLqcjz6d7Fd57271ffNIOTOg8eH+dafvj0iz/7vmy5rkVp20AAKcW/X7VBeC6snrRSUDpvZO4rmVmTz3KqO4xyPyAna58x1LBaNLqzc9+paZQQADmy/KkDmlayVSmhf33GPf8VO4ombRFbXtTlZeKmrSS1edc1SR3LGIeNdhSVDIVrW9fF5e+s6jliym2KkaTNsA89A/qfrutGi+PapimldKaD7HXC7E+7vPfLFFJpqimyI56EuwX1GjIFyMbh9Z8/5gdAIFqvrxuUodwraQp02L47zFO5Gnv+lENA7VSUPMho+qFeAphKfu/7lkhQCLBtd9ced2V4zseafu+nAfDP2gRgE2RHYvUHDW4YVGJFK0/dF2c7Km9aKMvpjxfxUi0ATWG/hGn+q7oadhs5yOjK437oHftML2kDa7Y/PUvl89p6+9N2+7OKvrc3tQ9LxXN3mUP+oLnfL0P0uuRXvsa1Lt/vduwqERC6r29Jlb2WaZ/+wWR80f3qFvSX9IGVe7x7riIy39eMl3fsPRWl68/6FDSz1iyw/tfd/l3yfqbsk8Z2N0t7084++zs92tpc/kYvbcyTdHro58Z/9FLVYM0+qJ1XvtijHb9uuuuPMuZlOfTvSrQa5le34dKEzZ9vrr0179O6FgpWKsrUrnTmDkzWvsBGMq0hd+XX3K6Li5bK3Up5/f4vOOzwCpnxz62jjsvLo72N/1r6O+SL9gA0pS3eruk0X6JJv8/XqLj+7uuqwCB4nY5wHlX3zJQWHM3wCkbegT6LtZCdxi1Z5P9V7VR3hkjJ7m1a1bXmKTtt/3//hZvmOg65wQAtm2cfWdT/bVk4+f+SrT5sfc9gT23y6rz7rqWOdoulHj5ixcTF8+x9HkJ1v56zgGQtu2t3guk0XsTTbF/vHRpfP9F11UASN42btjOpiuvJZ//3H+7p72Qtm/8qz8Vm3ridvyfL0Z/8M6GOyzrVw2uLf1kf/NP+5eT3IqN3mGccjY5blWbPe+M2ZKu2ONrTIO33079+9sSGybOPuf0UdHTsenKtyhxdtpHC3b9k+zKGLVetZ3ZWa3W3FWd8s7cLDbvXty8p1840UjEWKpe70833nDlx/376mtLdJT/lLPJcb+33Tdm9Ka7efJGNOn4n9eCaheHm8fulGxZ2eDeb6jcumTikZtOX9eu1H2TR+5p9cOnrYJy83lO72V6vkGeXrIj7mScu/n/a+88w6K41gB8Zivbl94WFbCiYsHeQNQYTWJPtScxNpT0m2ZN1GiK3ZhritGYGwsq2AsgikaNHezS3KUKbO+7M/cHi1JmllkRWfR7H548cThtzpz99syZ4byapCF+sfs0TtvJdT07quvcPch+a7xz9E7wK318a86pWSEvjxcl/n727OaDAe+8ImO6zf7+jXYfbcA370Wz1nBjmmMenowx8z36ihCSsHZeFSx4mSHmY90ncFrlWO8aXCxWwJw9hxUowqLjOMEXrQ4BkIAZF88KEWBtRnLaqu0FZoQM9oTzjBnvs4JF2IDZnI6CJrscwW0e8+KQUHH4i8MG+GuzyiwISYbvvHpowcutxHy/7hOmt8o5dteAkCEj4XzwjPcHB4sCB8ye6Thfw7VtJ/zi541p5RXQ+91ZLTL2VDHAEupTSzeg2Z/1r9xrUxA5e05soCgwOm5G8MWEyo6NiosfEiIQtRk5ua36coGZoqJnA07bD/btnGT7a2YvX5FA1m/SitRCK3lvN8wjn2Mmu9ZoNxnVdw580Sbt7UHxqSqqpw6qtHE+TC774U/svkKKa13lssouJdzQ03gCkLF2wtsno7/9oCPHqLZwpTwGMpz9dPgnF5An16w24uTZdP8unZ0YuWL5MB/nWwnhZGV6dBjd8e73y/beUVlMpVe2LVxxoVxrwmm30+sxstdVJunilV1XYuRXON2QOmlIRc+rEULMoJcm+e6eHX+o5bQX/N3nLcvGW/mx4nk6RvuAmscLEk1DwtVctpobYDhVgsyEi8WysBApwhBiSxgiA6GzVVgXsAAxwhBicBAbRzhCmI0oMmDNKlNKWU12SoqxhTwPFoMt5Hkw7GY7QhiyFiR+NCRcwGUzuQFvnCrRmgmE2bRFBlEzKQtDiC2ROc7Xps5XXPywFZfLZvKavf1PfrHW/kixsnVBer9Fk8Me+kNY0pDK7CJDUWXHCgPETAwhBkfAxq04oqjoWfnhBA3++Le02+VW1d09cd7bx49dl2Ul6+0GvVtnCYM6jV34+wKfAxsv6yiSSaMTSu0W68OflBECimtd9bIaS3R257XjytNfvxy7jLvg8MaR/iwGT8Ixq404xu/13cHvuiOlmSvhka4mmK+vnblFtnj1uCBmXdo0sjLZQa//+uuI2x939+VJWk061uyVjn6+IqbDG3P8QcoIidN2Ml3NTuPcye0uAh8PY6nO7ii5dE+01PErdsCwyWHZxT2nR3sx4J0fhNiM5kL8elH1g3rb/DnWsOWiEoPEpOD3qr4NKIYQXqdO1kbI1QghZFPjWh4mpJposLAAPpGnRAghmwpXPUs73enPzp+zO2z5pRKDzaTY0ktMIIQQSxTA1+QpbQghm0rhOF+WRNY8eku+zREjLMmVz50cE//P+1fZZN+mkqttCCGbOl/L86PuWLKKnrn3pPnB3d/44uM22UfvlJL1tksj9rHAGCwG4UrZVNe6ymXV8QNEznZ8N+fteK//iO3tNp7fNauDAEPIo1l3P8XJu477Bf3dNIVvz+akk2JTVuq1B6kzwvlsJsdndJoqbawPxSsuFGWyg19ZdjRbY7VblFe+a32ztNXQVnza7UQuZadbJgm8VoNC5Qf+LSe5r2AFTUo1FP0xSOxOf1/VeNGfz5gyAv30gTlNTpjV+L6l5jNahHBksCKBJ+ZhwY+uNJ/XVUnPxPy5eHpmdf262jrEt/proHr7T+tthTri5AaHhZGidua4HvjGVTaFGk9ea8kwPEOhCbcaKi2MR1f+4OhDfsdxPQo2rjqmUMuT127IqLzrHz9Q8e3Xe+6qzdrclNUzPzqhdbzqs2VBer9F1V/10V/7af2JQl3RyQ0/53cdS92xZBU9G2iSZ7320a/Hr8pVZnP5rf0//ng9oF8oh6y3HSNW7M+Vp2cqq4/YpCG+j/VunyYlfvKCnRfkWotFnXtibfzXBbFTO9NfWKO61lUva9TY9lSXFVf/+/0rveOyJuxPXz+2mcNwxW4xalLgoU+XJyv0ekXyd58eCp48qjmbYtnq4Y1I6Z5oaXRCKcUrLqRlGlM/mrnutEJvMRRf2/3VWx9kjZo3IpBB1p+k7dTQzk7/3ElhBo747IXMD95dk5artZof3Lpa7N6vSjfiU1+sxxLBilbWSW00Ij/dz4jZVoiQmDlvPvPAKxqxj34Dh9VZWCW9kBk3DdsyUMPj6Ks9panx2ETIGFhmivDUjD3GWrma7cukMGkysKEreYPOGMJ8dIvNrI4ihLn5ooMmacijeROTw658VIVq/Vfce978TgdeCRb7RG/gvOzoQ4bX0JXrB515I8wncrF5WEcRA8MQwsT9V2x7u3RBbx++d/dPM7pO6CpECCPU6Us3oNmfD5BU6xNhxMCy/0R4Bo891mfl6peoO5a0omfiR9wr/nXeoU+GtPTli/z7fHqp79qdH7b1IettR49FxU0L3DLQh8d5+FyR0Fw7lN9qeFuB69daFDWlX+G6cW28BTzfzu/sly05sGGYN5P+Sz+k1xohYfvY8v9EeAaPO95v1aph3lTWWl3aF58nlypPLhjg48FmcthMDrvnbwWMlrP+t6Zn6uRwsWf4xBO912+b2ZJNNVDpvr3EJilTFDWp679xHcVCSfOXlt4d9EfKd9FVBieqq52aznSzkzae/NxJ18gYXkPXHVrWfP87Hbz5/JBRiZHzFvYWOX15q1Gf+mJWG/7szM7U1sHh5rlZwhGuvDlrV1gG9LMtyeTHPB9OO7ti04B+J5ZkbiM/X2vW2oHDri7+d1NsVbdi4uDw1XOzUlzsWKcVPYdYs9YNGnZ5/vlfBrud2RF4Dmk0syObpWqgktO8H6fkIVKL1SZ9li+19tSC7wtfnxNr+PPX++3mtqW6x2eHz0m/8zQqeg5hh8edvAPdADzv0b9BQq1Lc3+cOPudftyXNnVrzpq9vKmtn/XZmKDjMP43LwS8oW795pq9YwIYTb8iAADqwbO18gMAAADQnPuDKRsAAOA5BG7LAQAAIPoDAAAAzwdgdQcAAIC5PwAAAPC8RP9G/hNWa6y3LklDa0foG2t0MqaKyaKZ/rHb0GAVNWY/J8YyGUwmg8mMrXlSmsRY79gn3aUNUKYL1ZlurHlJxmQwWbHPzhWEH/h54js8N3IDJOzUcuFIOnvs6e0rf8AnnpHY7PTSP/ZW6g1cUSP188hUHMeVe2KkVc704a/KUx7/TNWJg7xik9RPtMyHepnkd9r0XZ1tdfUKXlj5Q9bEM0qbPeWJXUF14iAGg1nzp9aJPxnzhf5OwvxXu/hzGAwmN7Db68tSimyPfmvL/e9AD+dV46Unf5zYqxmfwWSw/LuMW5Bw20A0TJMsuTvn9g1mM5jsoP5zd+ZZqnZUlRYShpyDy6f2bcZjMJgeQTXPqMZP7TIRsimSPhscKmQwmJygfrO2ZZloXiZHG+qV3aXGI2vh4cXjOvlxGAymT9cp6y9olImDmIzua7LtCGHIlrOmG5NkIDXYWHpGvL42IlfP6NUWYzwzFQHOsWZvnn+q/+IpYa56JW3lufqgXm0lT/IKSkam4Dju+AaN2aOs+EfKyIaw8WnPfPdbcZ+Fh3JUJmPRifkhO98Y+1OWY78we8GOufNvOpUj2nJ/efW1rV7v78vWmQ0lZ9a8Ytm55qy2IZpkvbf+9VmnozdnazTZm/unz3xzwz1rRUdVzjMqs5/+9md51Jf7szUmY+GJReF7x4/dkEW+AxpZmfb8v6ZM3R227N8yoz7/wDvab8avpFAzIoQeXZ3KC1TP7C40ntCk/2fwO6e7rjhdYtA/SF8amfm/S3qEELq0afs9C0KWe9s3XUJYZRVPYSw5B28slOYYVI5QOUKaKt2N2/W2rbM1Mm45YqmGL7GU2qqmrJJeaY4RqWe+rRahclEn3Y48pxWRpTTnmt/rpERIGTVFFyGqLLN2Re6CVXVz139i/BBiBfSaue2e0TF6RO1nvh0lQkjUafqOPDPlQZLIhePKPTGOURBT/RLc2jq7n4yLEKvZ8CWnSm3UtVcbSjF7lJRlmnP/ntFVihCSdp3xd25lOyXdFiwcFcZFiBfxzvb7lmrna1cem9qy98q7ZsozMuduf6+TCCFR1JQZEaIatZO04QmN21p9KCX5MNvKTn4zvAUXIX77KVuzTPWp0F60ta/XC0kVxZYkvhnY7L1dv0VLqU9Nte9F775bi+w1DpM0yclQodOkktvfdpJNTFZXHFQfnyDrtPy2mayXamQv/rOv94v7VGS/M5OVWXpohF/PTXKb45OQt7F/t69vmGhcHUcp9ctOv/G2/C2DgoZuK7DVKFPYfHD7Tl9cMRovf9Gly/AwEWn0bwQab4IrYafgUlwpqDZHQMT5r3TvX2dtviUxFAumWGw39FVTsvYopTgudHxJ6uxHRbybavGuWNuceGuZk83Oa6ckiP1zDWmxgny16Bux7YauRpOqV+QOqA9PGbeJ88EplU6x99XbH0/clFOxdb7u+lHRNzfV+btiT8yJP+joBNKDVPPZGtM0pD//1cvvXx+6+ZbGUHxoiuX4DT1F7Y+yV4zglJESijLxB0lxcSn9/ydXy//XLzkuLulBxR+Yay/sVE9LKVVfXynb8/m6DBP1xL/2GRGl++fOSYvdla++8Y34WOUVJGvS04fQpH08/he/ZVdLCw6Py/zPnL0lj/8H9XjZ+QPZXp2DuQgRqrR5c07ErP0mxtPZq3oe4f1lGUu//Dn5drmFqKtJNIcKaZOIvH+LZdFtHNtMC9pEy0rO55nqujHT5hxbt+5eqyGteWS/NpGXiSGs6t+lmuSX5eaKz0VirFdsYtUtmrUnXvdlMBgMj8CuYxck5ZorlgTrlZ1u4w23j9wOHtHXt2ZUZYW8PF6057d/zvx+IPCdl2VMt4kqROOissRINXtVlf/UW6c1Vy/MpJFSZYkRqldlEQRBWLNNXWW6EzrqKmqn1FrHB6tXZRMEQVizjJHC6iVXrcgNKd0+wH/EYTVBqPbGCCNXZVkJgrBmr+oqm3hCR3HQcWp7Y6QxNU+txkH96WnNIxZmmuuunX6Z2tS3grs6mpS1smvw+FQtQaj2xoiifr5vIwgCL9nW12vIvkeF4KrjU1v2XnXPUlla7TPSpo4P7roq21FmpLBKdaRNemIjtnrhVf/58P91p6Y2j1qdbSUIwl7wex/ZGynax6sM111dOcgr8M3dRTaC0J79uLXfK3/l2+o8QUv+0eWT+oWJEGIH9njr2+MFFvImORkqdJqkShrsFZ1QThD6fz584aOzioRor8FJKqejoiLoiF/ceI9igJGWWZa/ZbB361m7binNxgeXf58chthDnFVEELhVm3955+f9vZpNS1Za65cdp9/4fUO8o3eVV00fszdvb4w0ZlfGpgFB7SJajku8t5tkwDQSbra4bSVydVj7QHqJWViIJ0IIsaSYyEBobK6ktBPFRixEihBCLE+GlIXcHqti74cxzXkYhmE+r58s0ZoqpmksaYgnCyHEkspEhiJHJ5AepFtPea7Op30gh1btNLFrS4wiR5M8Q0TGYm2F8YQp8hczEUIYR8DGrfaqE/95p/p/XWXFv/YZ2bXFRlGI1FGme11Bm0qhuBgfxsYwjBk09Ux+scb+OLP+8vTFQ6OXchcd3TTKn2m+vmr6H7Jv1rwaVPfUkR005NM/TmVp7PqcxLk+f78+au1dI0WTXBsq1ZvE4Ek4ZpURR/xePxz5/qHZ0cmzk1QCt6juHphdvvCdX3NI6yItkx30xubfRt76qLMnlxc64UjzEZF+vhX2XCQZmapMrX2Hh7GEQZ3HLf5joc++jReN9cuuo914psDHw/hAZ3ekV+19eAfMChw+NTy7qOf0GG83CrluFv3ZWAshcb2Q7uNZuaris0ZoeZiI6UpKFhbIJxQVB5VEExAQ6s9+NSsh/PsrSgtuL9ra+6FB0KaSqyo0ivlankMoTX4QIYQwJlY1ypJeAq8WwtLrhRZatVe+aVOHY5Ap8uNpHU1SKrQ8f2cXCxHqk0vWobgvB1T3StY4I5Y4kK9TVJbZeFeQyWZYDRYCIWTXVn6rsaQhLWK2FeOVM8nHWIAy526f1vulvyM2XdgT10GAIWS6l3z1Qcp7oWwMw6SjTqhOjJIOTKzDEcbgB3d/66tP2mYdvWOlaBLlUKHRJI/mPfwVaXcqLYx30hR+FGbHKoOFLWk57P348MykG6TeN4oy2cEjViTnGgmC0F77sc3N0tZDW9PYORxjOvyX9cxOt/G81oPD5PvPk5sdp5w0lf05GMyO1PCZb48i1sWbTsgJs9qe+I3ptJN3FfT29eushTo8bb1ZEcV5JKVTWwd6ahPVTlPymWOi8I3rbUU6PHWd6Zre7aM/bnloEDzyw/fnHhoE9dfWr0st1BWlrd+oeGjmIz2IEOIERkhzj1wodRb/+Z3eHmVaF//jCbnerL6T+M3i01rq2hFCTHEA9/6pDKXTMiNGd7r/09oThbrCE+s23O80KoLv9FWfGhN/0jPitx8Tpdi4/mSRrjB13bpGu4Lc4C6eN7ck3dUZFMlr1la84IEEkRNj5UsX7b6jNmtzkldO/zD14TBWJw70rCtq4+rzK17uPvPepENnNo6rVAlKRqbWXH1KJf9S0RyfPvbDTceu3leZzeW3kr7/ITOwX6g3RZOohgqdJrFbjJ4ceODjb48r9HrF8W8/Phg8ZXQL0he0NMmzXv9sS3q2ymwzlmQkLFuRGdw/jPR7grRMY8r709emK/QWQ/HVhC9fm3tv9IKRlWrG6v2pSY6bMH/7v3KtxaLOSV0dtzh/0NQu9npmp914ZuCoL4ZmzH1n1YlcrdX84Ka7mx1RY674V3/BpmL9C9fb/pihCWKXI4Zq6NfWMjv1ur9IPX2SWoDKBR31f+c5fUJAltKSZ54WqURI2WWyvr3I/df9DZnrRoeyEWKFDPviqyhJzF5VxdJ5xPRJnQUICTq++3eexREaah+sPOmcza81xxBCldmrvyFTeQlu/jGjTxAbIUbw0K9PltkpanfMIjX/zOvriRDCnJVpzvnftM4ShJCk87T/5ZgpV8xrrPg/DHZkZ2TJ2z4tUoiQoMvkGe1FjbTuT1jlO96O4CHECR21cGG3yp6xq86vfDVCjBCSdpmy8ZLaMYxx9YnprXqsuG2pq4qaH9NumxQ26jbUXJm/ueOLUR29MYQQkrQcNHfbbQNO2iRnQ4Vek8zZf8/q5cdAiOHfe/b2HDPFAMD1dxMXjenohSGEGN4RL322O8dEWVftMu3qyxsndhAihNj+nccuOig3U3WFXXVx47t9grkIISRoET3zt2savL7ZXWo8rr+1NS66OQ8hxPDp8saKtAdlNB4UNRKIaKLQj9Hu/xT3iUUitxhS9cJyb1XvllOPq/Bn5oyqn93qvi2nHFXi7jx+gOeGRntYhmHK+hdyQqp84ilr3Rt5IuDpPfgJjz9z9xk+u7npd+EiA25Co0X/+kZVtXVgC9P7uaK6n6fRTwkAAPDcgBEEAb0AAADwvAGb2QAAAED0BwAAACD6AwAAABD9AQAAAIj+AAAAAET/x0FtHYgpMUyJYdq6tiuhyO7pNGOdCVDD5G3YTqOxT8Cz3QAAAJp89JewUwlPQiWsvrm8eyBhpyrd8u8DKLYkbDAIdfLbrfqsfmQyetoNcLOvXgYWtSbbhhBCtuw1URijYb4I1YkDsQqqlE96kArTvT+n9/RjYhjTr+eMbVnmen+jE/rbCfPGdvZjYRjGCej62rLkIhtCCFlyd8zpE8jCMFZg3zk7cy3U7aydsp4VUUGakmb2+vc8shYcXjwm0peFYZh3l0nrL6iVtYYNOY0wqYKVH8DJSCbbcO355tJ/KxV9/73UgN/xjm0Y6jpIEf9urX7tw5sjExR6vXzXiOsfvLb6tqWeTdKeWfFrcd9Fh3PVZlNx2oKQHa+PqTA7vjbzdPQfOVptzh/902e8seGelbydZCnrWRHFkCVLSTt7fXue0KR/Oujt9KjvzjwwGkpPL+uU8ZfD7Fh12GCk+/w0xqTK3bbrUd8y/ydGiVB5QC/9X1mVaVjlfI6y87vG6VHKNh9b9ZV7t82YqhahcmFktb3bKn2N+ojKvdtIyqx777nKVqksVcSQ+p33Kzf3UlhmdlEipOz+rr6DuOH3EXq0eVb1HaNYiM8Rd3736+lRPm0+Pq8nCIKwqW8lPLQw/pVlqmzw7pldRAiJu78b10FcuRlZ+akllba/P7NrOCtqKVZqNEC1t6oXcOd9xx5hpGWS1t70dlWqUPRdNZmuOBR9e1WEJW/7Q2nl9ocb7Um6LVxUKa3cIbc+zU2cLLeWRoZOP62vtPVMD41cdstC4Ibbfz4Udi5NL7NTbslXt+Gl+M++Xi/se3BneSfZxBRNxUFN8gRZpxV3LGTttFCnrGdFNc+dLKXexdofu+ftBVsHBQ39q9BOY9iA3YVkwX3yWAvnQ7FaL018zf7RBLPDosBivLmM8+AXk+5NDkqwZBgRQgjp7MfEvFsaye5B1rlzrKUVvsY5hrRYQYFGvERsddj+qMqkvx6lsx8V8W5pJAmx1ri5DjHkoXj98b4CuUa8VGzN1DZ8z1BNQFjBby579cEv63RvvoYSNmcYEVIfnjz2v5wP09X6/MTXbn80YVOODSGi/FD8zON9t8s1t5aKjzoaTGjSPnprk9+318oKj7ya+WlcdQFhjYk/aQN014+KltzSFCTEnoibWyFcJCuTtPamCCvklQmiPb/+c+a3A4HvviJjIoQ/SJo9O6X/3wqN4u9+ybNnP5JW7lC9l1qmubFKtueztRmmp9hI0/0LJQG9Qx17EHuE9goouXDfpD//5Uvx11/847bWWHJ4qvnYDX3Va1oRg2hOP/Gy8/srzI7ni2UxjyyMMbKSc+RmRxPtlK5WVGPZirQiFe3s9cRw+/Dt4JFkZseaw+Z5X/enCL57MoWLX2GI+ViPSdxW2dY7FRYFLiN2GCtUzBw+nOWvwUsr7mMFzDlz2UEixsA5HrKLlkw9Qnp7wkXGzDnsQBFjUDw3UuC0TPpUqSj4giXTgIN3q64AABsKSURBVJDBvvMcY9YHbJmIERPn4aioUeA2jx02JFQcPnz4AH9NVqkFIclLezIPL36llZjv12PS9FbZx+4YEDJk7DwXPOuDITJRYEzcLEeDDde2pvh9MH9sa6+APu/NbnFtz3VDlRX/2ooVkp6JnDN3UJAocOCcmcEXEjINFGWS1t40w3/wy5N9d82KO9hq+lB/BkLIcH335Waz5g4KFgUPip/V7HJlHwqi4j94oZlA1Hb05Haqy/nmp9hG3KS2cEQejo82w0PMsahNuqu/7ubMWfdJbHOhh2e7cQsX9hM95mKB/tqaNyanxaz4MJJjVFu4Uh4DGc5+NPTjf5En16w2khqMcdopG6Ii22PU/ljYdSVGvkOR43haUPHVUmvYQPQnRbHXENNciWFKzEd/soRwGAQxJOBjLAYS8DGGnXDM3av6Go2E1k7payQv04WPfC0xpI0oNGDNKg82plYQ4wj4HiwGR8D3YNjNNoTILYw2TaFB1KzS4edosBMBIc0V/9peQNIySWtvouG/hqLPVWnl0/hMe0g4Fq0Jr/wu0Fg4Yg87qbDT5S+WxzQ7uuqApF9RjdcQSFOyaGevJ2B2dLnHMPTow6G3fTXLGv69WGnxtBcJeoud5qzia9TxMTGLwtfoUpl1VVRVDJlXXr0iN4HUwsgSB/I1eeXVPYiUAkJ6E39EKlwkK5O09qYa/qsr+lyTVj6d28GQKN+is7mOhRVT7rkiv27NRGTCzodTiDrdnAjVy+zomgPySVckfQwD5WMBZkfX4GARUvzIBcIR/3FksCKBJ+ZhwY/8YKpmECQJc1V8jd04Hah8jU7KpPleP5kY8tWe+IaVVrkaP77GdM3gTuGJ1MLI7/hqz4INK4/K1fLja9Y7GkwlIKT/qk9tLyBpmaS1Pxu4JK1ET+UPJjhho98QJ3y+9nSR0VCUvubz3dI3R4dKyISdjvkXDTdnPc2O9FO6WlGN/iRNyaedvb4zWTA7ukjOZl1z7OE7NnjmOm0ouxyxVMO+MERJNHtVle8F5Vb5r6rynZ/JagEqF0bqd9x34mskK9O59qvqcQoxpFVhntFZiZCyx3R9pEST+PTe+amgUqMojdmbW+W/KkoLo1WRMKOzECFxj+nxkZLYREoBIZlbkaDw0pF5AUmlhqS1N22TWuU/aUsrH9vs6EyZSY7x9h/vdvNGCGE+3aZtuWOkEnaSuTkbwuxI6musZ0VUr+KQpqSZvf49D2bHJk+pub+XJklFSwxpk5t6ynQp2iZzcjb5f3vK3qRsMKlb8VHP7OjvNTipHmO3jtqfbdzN7AiA2bFxnlY+CbNjg3KqigyyTjFkrMji7g5I7al5KwrfiI81bP0lLyK+HdUChRO3ImHOPbr9rmfnCut1g9T+bANmR8CtnmE13oqTW8ZKtXWgp+6EB3Pan8INYxgsRC2GxIl/VuhHf25Vt+GsS+K/0xpz90st6Dhc8PUg39fVbd5clzQmwNUnPurEgZ6jTni0n/bnmkiPp147AABPfAoOZkcAAIDnEJiDAQAAQPQHAAAAIPoDAAAAEP0BAAAAiP4AAAAARP9nkJqbQBA3VuuCMCXG0DZJr6ETP1FD7D3wlAWQNasz3Vg9PAjDGsq9BQAQ/Z8j9PYfvrdP/Edqx0VN0mvoxE9Uz20OSQP9k9k6sZZXku7FuvDD91kT/1HZ8SfsS7KXnvxhQk8ZD8Mwpm/nsfMSbusb4n1pcrshYbi5ZVb/ZnwMwzB+8wGzttwyUFbubmZHquz0pyn1E0NaFUmfDmrBxzCMHdhn5rZ7pjonSdXbQN8rCWbHZxAbkatn9G6LQX89PR7bK2krz9UH9W4recIXy5b7y7hXt3h9sD9HbzE++GftCMuO1WcbwlRDajfUXV8xNv5S7C/X1Waz+vovAy+/P3bFdfKw7n5mR/Ls9Kcp9RNDmvL/mjxld9i3F8pNhoKD72q/fmvlTcoOqbZ5ScXsgb5XEsyO9J2OZMZEcrMjWUp7uXXJcBUXlfPb6/7MrlbsB59oIzzLEVIOXmItt7tQO4kY8pHrsbrx8alvz0PiayR1K1IIF53uaVVtux4SBSBV7dWGUo0tsaqV6br+sMpmcxRnZMnb8V4nEUKiqCkzIkSub8jlKur9L3r3/bMYd7btnbSyGfU3O9awG97f/6JPv79KHLXjJX/18xl2QN1EzI6k2VW0N9SrpxhSfniEX89fFI5AYLv/c/9u39w003Y60q8dzI4uUNuYSGVhJHMrpn2k3+THu1YmOfKq/dM4yyMroc7+y2XWqn+lugJh33/M57S0aycVQz5yPbL2qjwJopFWfkh9jYjMrUh1kO48i0wBSFo7qReQtMzH0B/WmPiTKCRL98+JS4tNKNDcXCI+VnmxHk9VSA+P8AGyjCVf/Jx8u9xS54LPEzM7VtoNPSNf7674aWNKrtZq1eam/PSTvPvrHUm3S3JDsyNpdvq7RZkeT834qCIMYViVrVhM8ktyM0V27YnXfDAMw7gBXcbMT8o1u6KlBLOjC9Q2JlJZGMnciltTsA/mc1p7Mfq859HimvWRlZDPnP+Tx5BwTBDIWrhP8KKEdu2kYkh3Wbgn8zUiMrci1UGaGMgUgFS10y3TVf1hLb1M7TPSZyZclM2cMzBQFDwoPu5pXCxO248P7ppi3fZed28uN6jn+OXJhdRPJJ6M2bGK3VAYMn7jN4EbBoeKORxx6OB1vot/eiuEdJsuNzQ7kmanv1tUPcWQXh3HRt5dvmTPbZXFVHpl67zl/5Y/VJ/Vmg/ZCLOVwK3anMNftj0xNXpOispOu3YwO7pAbWMilYWRzK2oUNjjw5QYpmQG6c/k44+shGyspc9j1U4hhnSTVXASXyMicytSHaRbD6kCkKJ2uk9LXdQf1l7xr31Gdm2xURQidZT5dC4WO2jIp3+cytLY9TmJc33+fn3U2rtU8f8JmB2r2w1tOZsmfCKfdjhLZTar7h18L//TCf/NJq3dDc2OpNldiFKuqhmrV8QMemPzbyNvfdTZk8sLnXCk+YhIP1+Hgo3i9QSMJQzqPG7xHwt99m28aKB9mmB2dOlRak1jIpWFkcytGNKCta3YkyA8CcKTqP4qDoY9Vu2kYkg3gdTXiMjcilQHEUIIY2J1hSI2mQKQqvaKQuv0ArqmPyTzSpIoJMWBfJ1C1Si2SAY/uPtbX33SNuvoHSOTzbAaLARCyK6t/FZ7AtSyGxpuJN0ImzPnhTAJhyMJfzE+vtXN/TeNZFnd0OxImt2FNbf6VsQOHrEiOddIEIT22o9tbpa2Htqaxh7jGJPFIHCCfu1gdnQlotUyJlJZGGunFDAnxuJLF1nuqJE2x7ZyuiHV+dsXtSWOZL5GEjGkm0Dqa0RkbkWqgwghTmCENPfIhVJnMYpPpgCkqh3R8wK6pD8kfdWn9hnx24+JUmxcf7JIV5i6bt3TuFia49PHfrjp2NX7KrO5/FbS9z9kBvYLlQR38by5JemuzqBIXrP2Up3NoPN6JandkBvSzSdz1Zqj2RqrVZtzdO3qDJ9uzUiXzt3Q7Eia3YV7LtpqRtKKNCnvT1+brtBbDMVXE758be690QtGBjLIsmuS4ybM3/6vXGuxqHNSV8ctzh80tYuU9mmC2dGld35qGRMpzI5kbkW7yrryVbUYlSOpespGW4VBkJaskdrXSCaGpGX4anjIfI2kbkUK4WLF+eVsfq05hpwr68gUgOS2SBIvIEWZtPWHZF5JijOy5G2fFilESNBl8oz2Igp53hME193c8cWojt4YQghJWg6au+22ASes8h1vR/AQ4oSOWriwm6SKcfOJmR0RQt02KazajF/e7V3xrJQb3PvdXzJ0eFMxO1Jlp2m1fHw1I0Ko26b75Zc3TuwgRAix/TuPXXRQbqZ6yceuurjx3T4VfSxoET3zt2sa3AUtJZgdXYj+NONpQ0Texo/mDWCaJdxiSNXTfUjilWzSZwRmRwDMjjXX1KQ6RMOY+BD6Kenz2GW6u8Sx6eLEK/lMnB2YHQH3ofHMjiohuTGRdMmeZkr6NESZAAAATQcwOwIAADyPwL41AAAAEP0BAAAAiP4AAAAARH8AAAAAoj8AAAAA0f+JUXs/hsYqhFbJTUf3CGbHRux5TxBMAhD9n06klrBTlU/lRf4mpHsEs2M90R4bF9j7t4JH+3fhBb/19h95RNsw18uZMbFuEeCTN1A+NbMjaUonc5ea2Q3ZB5dP7hPCxTCMG+jIXs/aXXJqgtnxeQF0jw2KW5kdOX6tvQz5aps9f3N/7/6b8+02dYFe1EA7S1OoBEmkg6Sn3wAGyqdmdiRNyaeeu9TMfnrZxvvdvjqQozWbitIWh+95a8yGrPL61e6CUxPMjvR32qltTFRZYiTqhYu0YdxyxFO/s8NupZY4KpIMg8OUCJVjPuopP9nU9qplVtvDhySlK7JJ99A9gtmxUc2O9oLf+7WccUZb9FcsC7EGbivS/jMzrNO3ty2EvfzUkuEtuAjx20/5M9tM2TYXtgMiUwk+oL3ZEamBkiBrp5Oh0rhmR9KUrm/3hJds6+v94n51/Wqn79QEs6ML6zOkxkStfYeKm1omvbGKseczc4aJQuKot332niXsB7Ha7Fl2mtfhsvmivmqZVdcByFJS4ba6RzA7Nq7ZkSGUBRFFqgdn/rzi28Xn8pb0EmWBXiSTMjVpH721ye/ba2WFR17N/DRubwlO0Tb6UKkEa0sHSSE1UBJk7aQ/VKrx1MyONFJSP1axaXOOrV17r9ULrXnUZdIRQ9J3ajY1syNq5F3myDZe/vl+xXesua+Xdp+KIHTWqc3Vq7MrvlzNfWS6FC1B6KxTA5UvLDCnXLUrzU7LdJKydmOE6lVZBEEQ1mxTV5nuhI4gtNbxwepV2QRBENYsY6TQDbZ9Lt0+wH/EYXXFtCJyVZaVIAhr9qqusokndBQH6e8Jqj89rXnEwkxz3bXTL1Ob+lZwV0eTslZ2DR6fqq2YeEb9fN/mmKN5DakyHau+zzPpGWlTxwd3XZXtKDNS2NA7PJuuftE5ZvVvo/w6Lt79RRvvl39Z2zdg9BGN7tTU5lGrs60Vtwd9ZG+kaJ22jdaHImmwV3RCOUHo//nwhY/OKhKivQYnVZaAW7X5l3d+3t+r2bRkqs1CLflHl0/qFyZCiB3Y461vjxdYCNJ2OhkqTva5vrpykFfgm7uLbE7aSXkJqmSnX5GrO9o+vAUUv7jxntnlMmultOT9+VpAZcT0HfNHLsVNkmrfEO/oXeVV2xCzN29vjDRmV8amAUHtIlqOS7y32312eHa/JWsm5i9GCCGMg7Fxwo4oJI4C1nc7eaHnTO8MUHtyVS98Z6d8rkU/JXJn3SOYHRvX7Mj2a+1ZlLTupPilEdEvx3DT1u0tFMo8WTaVQnExPoyNYRgzaOqZ/GKNvd5tc2pMrCYdpLirIDFQGsna6fJQeWpmR9opSd8vkIxMJXCL6u6B2eUL3/nVcZdMWiYdMSR9pyaYHV2lbqschcTRuy934yFxttJTvo9zZ7nxDPX9Nf2U7qt7BLNjI5sdGUKZX2HyJfbgEa28Ikb2xK8kZ3NDpCyWNKRFzLaHi+x4ykhJvdtGQyXokA7W1eZHBkorWTudDZXaPDWzYz0ckFV6iC1pOez9+PDMpBuG+tVO36kJZkdXZ/oBXPxUBuEsIpFKHDW2uAnGXZdxo5Uw6Ak7F6OcdDhJ2YR0j2B2bGyzI9uvlQ+SDBzbno9EXcZEMRCSyqQsQeTEWPnSRbvvqM3anOSV0z9M1TptG53X/0lFhkYy6aCAdMCTGSi9ydrpZKjUHH5Py+zoqgOylppx1uufbUnPVpltxpKMhGUrMoP7h3Goy6QjhqTv1ASzo4u2PPyfeRpPVI6wyndpHq6kV/l/Eokjjmds0ceElCNUzg/VfnbAbqV6j4g0ZdPTPYLZsZHNjvaiLX18h+0pxQmCsN77sSMSjD2mIQjCrjq/8tUIMUJI2mXKxksVb5RRtI2e2ZFUJUglHaRroCRrp7Oh4iZmR4RQt03XEyhf5apxrXH93cRFYzp6YQghhnfES5/tzjE5q52OGNIlpyaYHZusKLGp6R7B7Ahmxyc+fgAwOzb4cj+mdM+bIdA9NiZgdgSAp0XjmR3dMFaC7hEAgOcGMDsCAAA8j8AWNQAAABD9AQAAAIj+AAAAAER/AAAAAKI/AAAAANEfAAAAgOgPAAAAQPQHAAAAIPoDAAAAEP0BAAAAiP4AAAAARH8AAAAAoj8AAAAA0R8AAACA6A8AAABA9AcAAAAg+gMAAAAQ/QEAAACI/gAAABD9AQAAAIj+AAAAAER/AAAAAKI/AAAAANEfAAAAgOgPAAAAQPQHAAAAIPoDAAAAEP0BAAAAiP4AAAAARH8AAAAAoj8AAAAA0R8AAACA6A8AAABA9AcAAAAg+gMAAAAQ/QEAAACI/gAAABD9AQAAAIj+AAAAAER/AAAAAKI/AAAA8KzAOnXtPvQCAADA8wamNxPQCwAAAM8bsPIDAAAA0R8AAACA6A8AAABA9AcAAAAg+gMAAAAQ/QEAAACI/gAAAABEfwAAAACiPwAAAADRHwAAAIDoDwAAAED0BwAAACD6AwAAABD9AQAAAIj+AAAAAER/AAAAAKI/AAAAANEfAAAAgOgPAADw/MJy9ktbafqRy4X4owNsgXdou3YdA3mN86VBmHPT028H9h7Skv+wAbgu52jag7aDu7fgYi4VZrqduWvJv2fPlOnsCJN4Rozq9dan7YP5MCQAAIDojxBCDL8uvbp7MxFChN1clnvj/MUMQWz3lnysSZ82ocnd8ubhM0qGb49WHfzw4jNZ1/84tEzNX/5jqACDUQEAAER/hJgcLp9XkcxD0DosK/d6id7eks80l+ZczMzL19oQSxAU3iYqnJuVdq64Zb+BzbiYTXn++IXioB7DIyVM3HDn1LmC8D7RMo5VKb+ckS1XWwm2UNaqXVSYlKXLPnamzMfLnFNk9enQs7e09Er1BBwMNxTe+/e6vMSI+D5BvhaCLJZbSm5dypSXGzEPvxZturfz0l5JP2ONGN7Tj4sQwvU30s6XtOoTLXt0d2AvKshSItQm+pNtUX4sZC+8+evs8/nK4jJzKE917eveR3M79XwlOOv4wVIDVxIZN3z6rGABZpX/7/ivP97MLcMR4gTEdp/yfa9WuksLB6QWduseK7hzIk1t8QqI/nz4+LFeHPgKAQDAvXFlCQe3lMkVKsT34TNxvTz93H17SNdXXho0orcM5VxJzyECAriaQrUVIbv+wQMrMpWV6XFEmJVyg6C5DweZis6fvaf3j3zppUEjewXb714+l28mEMItqhJ+u2Ev9Ormo/63VgK7Xn7mUiGndc9RL0X3C7IUGUijv7HQ4t9v6KCR/Vqw5Bn/5Fo8W/ixyhQlZgIhhOsK80yScN9qAZnVrGXPVgjdTv1qyPaNi8+eypCO/XPSos29mnlUFnn14o2QHjM29GvPUl/74djJPNx2+9y6L6/nCluPmj9weH9GUcrprTtVdoQQQrYLF2/Jot7+rk8kKkr7ZFfCNSsMLAAAmvrcHy88l7rz0Y2AsHlkZLgAGbIUKkGLoaESDwZC0pDOrQsO55RgnXxYimKVzZf3oBwLbOZVWlpmCeWUF+mEgX5cZJLLi1lBA1t68RgISWUdQ+XHc0pNnRDCBGEtvARcZCyuneBBualALWjRSyZkM5CkWet2uaXZJF9hooj2wVI2hiTBkeHyo/JSa7PgEPbF7FKLLJitVhRZvNv413gq4OE3avt473Vnk5Oyz/4uP/t7OmJIe34z+p03vR09EhA5/v2IUA8Ltufs9WO6/FI7q3vfr893UDL5fE3prTIJ45RJe99YEf1RSPdp87uGcFB7niI+7v653aVjOwVyYHABANCUoz/Dt1P3KG8WQojB5PA8WAyEELKbDVaMK+A67hwwjsCDYTXZhUH+WGaB1igptkhbBvroC/NVRm6+lh/cjocRGr0FN8mTD8oflS0wmAkmwtg8FoYQbiZJoNfqrYjDc1SEsYUeJDcrGJMrcszsGVwhB7OarQxRCxknNbfM5C/IKbD7d/KsEYsJk0mt4UbMHRk9D7MUl95Jubpz/pVzXxxq1e+tWDZCCCGxiM+qqJKFEIHjiDCWn1t1dM/O/HIr4nmzcISQvbI4qUTARAghjp9EgJCh0IzDyAIAoIlHf8Ty4IsENZIxODw2UWYw44jNQAgRFr0JZ4s4bFEzL/xKQYlGz28hFYh9WXcUhdkqrizCg4EwDo/NEAQNiQkTMyqWkYwGnMOz5iGEEIYQeQI2KihH5QZTRUWEzUgWVwm71WQjEAtDiLAYrYjL42AMj5AgXm5BYamgEPfp4Vmj/YRyb8KHnxd6DH75241tpf6+HcZ1yfn1Sl6WtqAMRwEVXykMxzeO454BL91x8Ne/in2njF7+Uag089D7b958tGwmVxQaIr1EhD67VIuQp8wDXqQFAMDNebwwhQkCg6X6nCu5ajOOW9SKK3d0Ipm/iMHylEmMOVmlHr5eHKbQX2ovzC5k+QXxGQhhPH+ZjznvSo7KhBN244Or6adT72jsVcokS6DlBDbzMeVeu6+x4HZtwb0barJZNa6+e19rQ4gwld7ONvu08OFhiMEPCONrbtwsQYEyr5rfcZh0cPcoETId3//Z8J1r4xKXv7g1IQsh3/Du4VRfh4TdZEcI2YxWQ07e8Q1ZRoTspsrGqG6snXR4x9IDP84rREjaZ4wPLPsAANDk5/7kXxqCZn172C9mXkq6bsPYwsDQzv1bChkIcTwDvbEHGl8vHoaYIj8vRqEmwFfIqIjuQb17Wi9lXNl/w0pgHC9Z2/4Rniyjskr4J0nAYUl7dTdfuHYhMQP38AqWSZgltb+LWEKJ9tbxZIvVzvAK7dRT5oEhhBg8WQvh1Wvm1l1FzNrt92n93q7hCUvOnTmdd/EOQmy+LLbriHl92ooQoSc9Y6b/G0PG/HMgcfv+xUe8O49qF3L6qvx6kcqGIYRQWOfBwfJjm8rMXgExX700sgMLBhYAAG4OpjcTz+q5WYqvHr4hjI4OlzTYQoxdfnHhgFR5xxd+3BPpxYThBAAARP9GhbCZdAZt7pXrJSE9Bobyawf/KaHfN2gDNud8DGMLAACI/k8bu+rOkVN5Nt9WA7q3kDbklBzm/gAAQPQHAAAAmgzwaiIAAABEfwAAAACiPwAAAADRHwAAAIDoDwAAAED0BwAAACD6AwAAABD9AQAAAIj+AAAAAER/AAAAoHH4P1Uc0MdGDHDoAAAAAElFTkSuQmCC]RServes static files from a directory using the default configuration as given in [.^NServes static files from a directory. Configuration options are passed in a NT that captures various choices about desired behavior. The relative path given in 1 is searched for a requested file, and the file is served with the appropriate mime type if it is found. Absolute paths and "..N" are prohibited to prevent files from being served from outside the sandbox._Serves a single file specified by a full or relative path. If the file does not exist, throws an exception (not that it does not8 pass to the next handler). The path restrictions on ]P don't apply to this function since the path is not being supplied by the user.`Same as _*, with control over the MIME mapping used.aPDetermine a given file's MIME type from its filename and the provided MIME map.Y%MIME type mapping for reporting typesStyle info to insert in headerDirectory to generate index for]Directory to serve from^Configuration optionsDirectory to serve from_ path to file` MIME type path to fileNOPQRSTUVWXYZ[\]^_`aNOPQRST*NoneKQVDi"bThe bŒ datatype enumerates the different kinds of HTTP requests you can generate using the testing interface. Most users will prefer to use the }, , €, , and ~ convenience functions.h(Represents a single file upload for the m.jthe file's namekthe file's content-typelthe file contentsm A single "multipart/form-dataQ" form parameter: either a list of regular form values or a set of file uploads.n(a form variable consisting of the given ² values.o&a file upload consisting of the given h values.pA request body of type "multipart/form-dataƒ" consists of a set of named form parameters, each of which can by either a list of regular form values or a set of file uploads.qTRequestBuilder is a monad transformer that allows you to conveniently build a snap " for testing.rRuns a q, producing the desired ".N.B. please} don't use the request you get here in a real Snap application; things will probably break. Don't say you weren't warned :-)Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r $ }| "/foo/bar" M.empty GET /foo/bar HTTP/1.1 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a sSets the type of the " being built.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r $ ~ "/foo/bar" M.empty >> st GetRequest GET /foo/bar HTTP/1.1 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a t˜Sets the request's query string to be the raw bytestring provided, without any escaping or other interpretation. Most users should instead choose the u+ function, which takes a parameter mapping.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r $ } "/foo/bar" M.empty >> tÀ "param0=baz&param1=qux" GET /foo/bar?param0=baz&param1=qux HTTP/1.1 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a params: param0: ["baz"], param1: ["qux"] uOEscapes the given parameter mapping and sets it as the request's query string.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r $ } "/foo/bar" M.empty >> uà (M.fromList [("param0", ["baz"]), ("param1", ["qux"])]) GET /foo/bar?param0=baz&param1=qux HTTP/1.1 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a params: param0: ["baz"], param1: ["qux"] vmSets the given header in the request being built, overwriting any header with the same name already present.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> :{ ghci| r5 $ do get "/foo/bar" M.empty ghci| v. "Accept" "text/html" ghci| v› "Accept" "text/plain" ghci| :} GET /foo/bar HTTP/1.1 accept: text/plain host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a w1Adds the given header to the request being built.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> :{ ghci| r $ do }, "/foo/bar" M.empty ghci| w. "Accept" "text/html" ghci| w¥ "Accept" "text/plain" ghci| :} GET /foo/bar HTTP/1.1 accept: text/html,text/plain host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a x2Adds the given cookies to the request being built.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import  Snap.Core ghci> let cookie = 9: "name" "value" Nothing Nothing Nothing False False ghci> r $ } "/foo/bar" M.empty >> xÇ [cookie] GET /foo/bar HTTP/1.1 cookie: name=value host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a cookies: Cookie {cookieName = "name", cookieValue = "value", ...}  Convert 9 into ² for output.ySets the request's  content-type to the given MIME type.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r $ ' "/foo/bar" "text/html" "some text" >> yŸ "text/plain" PUT /foo/bar HTTP/1.1 content-type: text/plain content-length: 9 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=9 zYControls whether the test request being generated appears to be an https request or not.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r $ ~ "/foo/bar" M.empty >> zx True DELETE /foo/bar HTTP/1.1 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a secure {$Sets the test request's http versionExample: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r $ ~ "/foo/bar" M.empty >> {r (1,0) DELETE /foo/bar HTTP/1.0 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a |>Sets the request's path. The path provided must begin with a "/ " and must notc contain a query string; if you want to provide a query string in your test request, you must use u or t . Note that 2 is never set by any q function.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r $ } "/foo/bar" M.empty >> |t "/bar/foo" GET /bar/foo HTTP/1.1 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a }=Builds an HTTP "GET" request with the given query parameters.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r $ }Õ "/foo/bar" (M.fromList [("param0", ["baz", "quux"])]) GET /foo/bar?param0=baz&param0=quux HTTP/1.1 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a params: param0: ["baz","quux"] ~@Builds an HTTP "DELETE" request with the given query parameters.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r $ ~ "/foo/bar" M.empty DELETE /foo/bar HTTP/1.1 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a wBuilds an HTTP "POST" request with the given form parameters, using the "application/x-www-form-urlencoded" MIME type.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r $ ÿ "/foo/bar" (M.fromList [("param0", ["baz", "quux"])]) POST /foo/bar HTTP/1.1 content-type: application/x-www-form-urlencoded content-length: 22 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=22 params: param0: ["baz","quux"] €iBuilds an HTTP "POST" request with the given form parameters, using the "form-data/multipart" MIME type.Example: %ghci> :set -XOverloadedStrings ghci> r $ €ÿ "/foo/bar" [("param0", FormData ["baz", "quux"])] POST /foo/bar HTTP/1.1 content-type: multipart/form-data; boundary=snap-boundary-572334111ec0c05ad4812481e8585dfa content-length: 406 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=406 Builds an HTTP "PUT" request.Example: %ghci> :set -XOverloadedStrings ghci> r $ ¶ "/foo/bar" "text/plain" "some text" PUT /foo/bar HTTP/1.1 content-type: text/plain content-length: 9 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=9 ‚PBuilds a "raw" HTTP "POST" request, with the given MIME type and body contents.Example: %ghci> :set -XOverloadedStrings ghci> r $ ‚· "/foo/bar" "text/plain" "some text" POST /foo/bar HTTP/1.1 content-type: text/plain content-length: 9 host: localhost sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=9 ƒGiven a web handler in the ¼ monad, and a q? defining a test request, runs the handler, producing an HTTP .ùThis function will produce almost exactly the same output as running the handler in a real server, except that chunked transfer encoding is not applied, and the "Transfer-Encoding" header is not set (this makes it easier to test response output).Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import  Snap.Core ghci> ƒ (} "foo/bar" M.empty) (%g "Hello, world!") HTTP/1.1 200 OK server: Snap/test date: Thu, 17 Jul 2014 21:03:23 GMT Hello, world! „&Given a web handler in some arbitrary Ê_ monad, a function specifying how to evaluate it within the context of the test monad, and a q? defining a test request, runs the handler, producing an HTTP .…Given a web handler in the ¼ monad, and a qV defining a test request, runs the handler and returns the monadic value it produces.Throws an exception if the ¼ handler early-terminates with + or ,-.Example: ,ghci> :set -XOverloadedStrings ghci> import  Control.Monad ghci> import qualified Data.Map as M ghci> import  Snap.Core ghci> … (} "foo/bar" M.empty) (%( "Hello, world!" >> return 42) 42 ghci> … (} "foo/bar" M.empty) ,-9 *** Exception: No handler for request: failure was pass †&Given a web handler in some arbitrary Ê_ monad, a function specifying how to evaluate it within the context of the test monad, and a qU defining a test request, runs the handler, returning the monadic value it produces.Throws an exception if the ¼ handler early-terminates with + or ,-.‡Converts the given  to a bytestring.Example:  ghci> import  Snap.Core ghci> ‡  "HTTP/1.1 200 OK\r\n\r\n" ˆConverts the given " to a bytestring.Since: 1.0.0.0Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> r <- r $ get "/foo/bar" M.empty ghci> ˆ6 r "GET /foo/bar HTTP/1.1\r\nhost: localhost\r\n\r\n" } request pathrequest's form parameters~ request pathrequest's form parameters request pathrequest's form parameters€ request pathmultipart form parameters request pathrequest body MIME content-typerequest body contents‚ request pathrequest body MIME content-typerequest body contentsƒa request builder a web handler„a function defining how the Ê monad should be runa request builder a web handler†a function defining how the Ê monad should be runa request builder a web handler'bcdefghijklmonpqrstuvwxyz{|}~€‚ƒ„…†‡ˆbcdefghijklmnoq NoneE‚-‚ƒ„…†‡bcdefghijklmonpqrstuvwxyz{|}~€‚ƒ„…†‡ˆ-qpmnohijklbcdefgrƒ„…†}€‚~wyvx{ut|szƒ„…†‡‚ˆ‡ Noneeİ‹A newtype over   with a   instance.aSpecify the options to use when building CORS headers for a response. Most of these options are ./M actions to allow you to conditionally determine the setting of each header.8Which origins are allowed to make cross-origin requests.WWhether or not to allow exposing the response when the omit credentials flag is unset.‘‡A list of headers that are exposed to clients. This allows clients to read the values of these headers, if the response includes them.’+A list of request methods that are allowed.“rAn action to determine which of the request headers are allowed. This action is supplied the parsed contents of Access-Control-Request-Headers.”$Used to specify the contents of the Access-Control-Allow-Origin header.•:Allow any origin to access this resource. Corresponds to Access-Control-Allow-Origin: *–"Do not allow cross-origin requests—/Allow cross-origin requests from these origins.˜WA set of origins. RFC 6454 specifies that origins are a scheme, host and port, so the ˜ wrapper around a   ensures that each  % constists of nothing more than this.š(Liberal default options. Specifies that:*All origins may make cross-origin requestsallow-credentials is true.3No extra headers beyond simple headers are exposed.GET, POST, PUT, DELETE and HEAD are all allowed. All request headers are allowed.+All options are determined unconditionally.›·Apply CORS headers to a specific request. This is useful if you only have a single action that needs CORS headers, and you don't want to pay for conditional checks on every request.You should note that ›& needs to be used before you add any Ò@ combinators. For example, the following won't do what you want: 2method POST $ applyCORS defaultOptions $ myHandler'This fails to work as CORS requires an OPTIONSR request in the preflighting stage, but this would get filtered out. Instead, use 2applyCORS defaultOptions $ method POST $ myHandler‰Š‹Œ‘’“”•–—˜™š›œ›‘’“𔕖—˜™œ™‹Œ‰Š‰Š‹Œ‘’“”•–—˜™ NonegNOPQRSTUVWXYZ[\]^_`aWUVNOPQRSTZ[\YXa]^_`NonegŞ5 !"&'%$#()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM<45./012LM36-"#$%&'()*+,#$%'&89:;<=>?@ABCDEFGHIJK!7   None1CV„u£Thrown when the 'Accept-Encoding'# request header has invalid format.¤Runs a Snap+ web handler with compression if available.(If the client has indicated support for gzip or deflate in its Accept-Encoding header, and the  Content-Type0 in the response is one of the following types: application/x-javascript application/json text/css  text/html text/javascript  text/plain text/xml application/x-font-truetype<Then the given handler's output stream will be compressed, Content-Encoding- will be set in the output headers, and the Content-Lengtho will be cleared if it was set. (We can't process the stream in O(1) space if the length is known beforehand.)<The wrapped handler will be run to completion, and then the Response that's contained within the Snap monad state will be passed to Ï to prevent further processing.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Testd as T ghci> let r = T.get "/" M.empty >> T.addHeader "Accept-Encoding" "gzip,deflate" ghci> let h = ã (0 "text/plain") >> %¤ "some text" ghci> T.runHandler r h HTTP/1.1 200 OK content-type: text/plain server: Snap/test date: Fri, 08 Aug 2014 15:40:45 GMT some text ghci> T.runHandler r (¤’ h) HTTP/1.1 200 OK content-type: text/plain vary: Accept-Encoding content-encoding: gzip server: Snap/test date: Fri, 08 Aug 2014 15:40:10 GMT ¥ The same as ¤2, with control over which MIME types to compress.¦WTurn off compression by setting "Content-Encoding: identity" in the response headers. ¤4 is a no-op when a content-encoding is already set.¤the web handler to run¥set of compressible MIME typesthe web handler to run£¤¥¦§¤¥¦£§£ Noneê2What kind of proxy is this? Affects which headers ­) pulls the original remote address from.'Currently only proxy servers that send X-Forwarded-For or  Forwarded-For are supported.«!no proxy, leave the request alone¬Use the  Forwarded-For or X-Forwarded-For header­Rewrite % if we're behind a proxy.Example: 6ghci> :set -XOverloadedStrings ghci> import qualified Data.Map as M ghci> import qualified  Snap.Testb as T ghci> let r = T.get "/foo" M.empty >> T.addHeader "X-Forwarded-For" "1.2.3.4" ghci> let h = 1 % >>= %€) ghci> T.runHandler r h HTTP/1.1 200 OK server: Snap/test date: Fri, 08 Aug 2014 14:32:29 GMT 127.0.0.1 ghci> T.runHandler r (­ ¬S h) HTTP/1.1 200 OK server: Snap/test date: Fri, 08 Aug 2014 14:33:02 GMT 1.2.3.4 ª«¬­ª«¬­ª«¬23456789:;<=>?@ABCDEFFGHIJKLMNOPQRRSTUVWXYZ[\]^_`abcdefghhijklmnopqrstuvwxyzq{|}~€‚ƒ„…†‡ˆ‰Š‹Œ0‘’“”•–—˜™š›œŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖרÙÚÛÜÜİİŞßàá..âãäåææçèéêëãìíîïğ+ñò$óôõö÷øùúûü1ışÿ%      !"#$%&'()*+,-./01234#5#6(7(8(9(:(;(<(=(>(?(@(A(B(C(D(E(F(G(H(I(J(K(L(M(M(N(O((P(Q(R(S(T(U(V(W(X(Y(Z([(\(](^(_(`(a(b(c(d(e(f(g(h(i)j)j)k)l)m)n)o)p)q)r)s)t)u)v)w)x)y)z){)|*}*~**€**‚*ƒ*ƒ*„*…*†*‡*ˆ*‰*Š*‹*Œ*****‚**0*‘*’*“*&*=*”*•*–*—*"*˜*™*š*›*œ     Ÿ Ÿ   ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á ÂÃÄÅÆÇÈÉÊÃËÌÃËÍÎÏĞÎÑÒÃÓÔÕÖ×ÎØÙÎØÚÎØÛÎØ5ÎØÜİŞßàáâÎãäÎãåæçèÎéêëìíëìîïğñÃòÅóôõóöõÎØ÷ÃøùİŞúûûü#ı#ş#ÿ#######Îàá àá ( ( ( (8(9(((((:(((((((;(=((@((((((((ş(ş(( (!("("(#($)%)&)')')(**‹)*+,-./01 © ´2'snap-core-1.0.3.2-6c0XIwxbJjXXfnyiXTcpuSnap.Internal.DebugSnap.Types.HeadersSnap.Internal.Http.Types Snap.TestSnap.Internal.ParsingSnap.Internal.Core Snap.CoreSnap.Util.FileUploadsSnap.Util.FileServeSnap.Util.CORSSnap.Util.GZipSnap.Util.ProxyForeign.C.ErrorErrnogetErrnohandleFileUploadsSnap.Internal.Test.Assertions emptyResponsesetResponseStatus setHeadersetResponseBodyData.MapfromListControl.Monad.Trans.ClassliftControl.Monad.Trans.ReaderReaderTControl.Monad.Trans.WriterWriterTSystem.IO.Streams.Combinators skipToEofSnap.Http.Server httpServe runHandlerSnap.Internal.RoutingmethodwriteBSgetSnap.Internal.InstancesSnap.Internal.Util.FileUploadsSnap.Internal.Util.FileServe!Snap.Internal.Test.RequestBuilder finishWith Control.MonadmzeroSnapHandlersetContentType getsRequestdebug debugErrnoHeadersemptynullmemberlookuplookupWithDefaultinsert unsafeInsertsetdeletefoldl' foldedFoldl'foldr foldedFoldrtoListunsafeFromCaseFoldedListunsafeToCaseFoldedList $fShowHeadersResponse rspHeaders rspCookiesrspContentLengthrspBody rspStatusrspStatusReasonrspTransformingRqBody ResponseBodyStreamSendFile StreamProcRequest rqHostName rqClientAddr rqClientPort rqServerAddr rqServerPortrqLocalHostname rqIsSecure rqHeadersrqBodyrqContentLengthrqMethod rqVersion rqCookies rqPathInfo rqContextPathrqURI rqQueryStringrqParams rqQueryParams rqPostParamsParamsCookie cookieName cookieValue cookieExpires cookieDomain cookiePath cookieSecurecookieHttpOnly HttpVersionMethodGETHEADPOSTPUTDELETETRACEOPTIONSCONNECTPATCH HasHeaders updateHeadersheadersc_format_log_timec_format_http_timec_parse_http_time set_c_locale addHeader getHeader listHeaders deleteHeadernormalizeMethod rspBodyMap rspBodyToEnumrqParam rqPostParam rqQueryParamrqModifyParams rqSetParamsetResponseCodemodifyResponseBody cookieToBS renderCookiesaddResponseCookiegetResponseCookiegetResponseCookiesdeleteResponseCookiemodifyResponseCookiesetContentLengthclearContentLength formatLogTimeformatHttpTime parseHttpTimestatusReasonMap rqRemoteAddr rqRemotePort$fHasHeadersHeaders $fOrdMethod $fEqMethod$fHasHeadersRequest $fShowRequest$fHasHeadersResponse$fShowResponse $fShowMethod $fReadMethod $fEqCookie $fShowCookiegetResponseBody assertSuccess assert404assertRedirectToassertRedirectassertBodyContainsDList fullyParse fullyParse'parseNumuntilEOLcrlf toTableListtoTableskipFieldChars isFieldCharpHeaderspWordpWord' pQuotedStringpQuotedString' isRFCTextmatchAllpAvPairspAvPair pParameter pParameter'trimpValueWithParameterspValueWithParameters'pContentTypeWithParameterspTokenisTokenpTokensparseToCompletion pUrlEscaped urlDecode urlEncodeurlEncodeBuilderurlEncodeCleanhexdfinishparseUrlEncodedbuildUrlEncodedprintUrlEncodedpCookies parseCookie unsafeFromHex unsafeFromNatNoHandlerException SnapState _snapRequest _snapResponse _snapLogError_snapModifyTimeoutunSnapZeroPassOnProcessingEarlyTermination EscapeSnapTerminateConnection EscapeHttpEscapeHttpHandler SnapResult SnapValue MonadSnapliftSnaprunRequestBodyreadRequestBodytransformRequestBodycatchFinishWithpassmethodsupdateContextPathpathWithdirpathpathArgifTopsgetsmodify getRequest getResponse getsResponse putResponse putRequest modifyRequestmodifyResponseredirect redirect'logError addToOutput writeBuilderwriteLBS writeText writeLazyTextsendFilesendFilePartial localRequest withRequest withResponseipHeaderFilteripHeaderFilter' bracketSnapterminateConnection escapeHttprunSnap fixupResponseevalSnap getParamFromgetParam getPostParam getQueryParam getParams getPostParamsgetQueryParams getCookie readCookie expireCookie setTimeout extendTimeout modifyTimeoutgetTimeoutModifier$fShowEscapeSnap$fExceptionEscapeSnap$fAlternativeSnap$fApplicativeSnap $fFunctorSnap$fMonadPlusSnap$fMonadBaseIOSnap $fMonadIOSnap$fMonadFailSnap $fMonadSnap$fMonadSnapSnap$fMonadBaseControlIOSnap$fExceptionNoHandlerException$fShowNoHandlerException$fEqNoHandlerExceptionroute routeLocal FormParamPartUploadPolicyFileUploadPolicy UploadPolicyPolicyViolationExceptionpolicyViolationExceptionReasonBadPartExceptionbadPartExceptionReasonFileUploadExceptionPartInfo partFieldName partFileNamepartContentTypepartDisposition partHeadersPartDispositionDispositionAttachmentDispositionFileDispositionFormDataDispositionOther PartProcessorPartFoldFormFile formFileName formFileValuehandleFormUploads foldMultiparthandleMultipartfileUploadExceptionReasondefaultUploadPolicydoProcessFormInputssetProcessFormInputsgetMaximumFormInputSizesetMaximumFormInputSizegetMaximumNumberOfFormInputssetMaximumNumberOfFormInputsgetMinimumUploadRatesetMinimumUploadRategetMinimumUploadSecondssetMinimumUploadSecondsgetUploadTimeoutsetUploadTimeoutdefaultFileUploadPolicysetMaximumFileSizesetMaximumNumberOfFilessetSkipFilesWithoutNamessetMaximumSkippedFileSizedisallowallowWithMaximumSizestoreAsLazyByteStringwithTemporaryStoreDirectoryConfig indexFilesindexGeneratordynamicHandlers mimeTypes preServeHookMimeMap HandlerMap getSafePathdefaultMimeTypesdefaultIndexGeneratorsimpleDirectoryConfigdefaultDirectoryConfigfancyDirectoryConfigserveDirectoryserveDirectoryWith serveFile serveFileAsfileType RequestType GetRequestRequestWithRawBodyMultipartPostRequestUrlEncodedPostRequest DeleteRequestFileData fdFileName fdContentType fdContentsMultipartParamFormDataFilesMultipartParamsRequestBuilder buildRequestsetRequestTypesetQueryStringRawsetQueryString addCookies setSecuresetHttpVersionsetRequestPathpostUrlEncoded postMultipartputpostRaw runHandlerM evalHandler evalHandlerMresponseToStringrequestToStringHashableMethod HashableURI CORSOptionscorsAllowOrigincorsAllowCredentialscorsExposeHeaderscorsAllowedMethodscorsAllowedHeaders OriginList EverywhereNowhereOrigins OriginSetoriginsdefaultOptions applyCORS mkOriginSet$fHashableHashableURI$fShowHashableURI$fShowHashableMethod$fHashableHashableMethod$fEqHashableURI$fEqHashableMethodBadAcceptEncodingExceptionwithCompressionwithCompression' noCompressioncompressibleMimeTypes%$fExceptionBadAcceptEncodingException $fShowBadAcceptEncodingException ProxyTypeNoProxyX_Forwarded_For behindProxy$fReadProxyType$fShowProxyType $fEqProxyType$fOrdProxyTypebytestring-0.10.8.2Data.ByteString.Internal ByteString/case-insensitive-1.2.0.10-1Cqb2PqMAYNmEZ0jMKGvkData.CaseInsensitive.InternalCIHunH Data.ByteString.Builder.InternalBuilder byteStringbaseForeign.C.TypesCTimeGHC.Real fromIntegralData.ByteString.BuildertoLazyByteStringcontainers-0.5.10.2Data.Map.InternalMapGHC.BaseMonad Alternative MonadPlus<|>)io-streams-1.5.0.1-6auM1z4KeQM5ZSLLooUu8lSystem.IO.Streams.Internal OutputStreamghc-prim GHC.TypesIOControl.Monad.IO.ClassMonadIOliftIO,monad-control-1.0.2.3-4Dn1Phj5k8rLcgnEMPHikLControl.Monad.Trans.ControlMonadBaseControl GHC.Exception SomeException+lifted-base-0.2.3.12-9BUfqcMCwBm5ZiNpsDDbGEControl.Exception.LiftedthrowIOcatchtransformers-0.5.2.0Control.Monad.Trans.State.LazyStateTData.ByteString.Lazy.Internal#text-1.2.2.2-EakMpasry3jA6OIwSZhq9MData.Text.InternalTextData.Text.Internal.LazyfailData.ByteString intercalate InputStreamStSnapunStSnapRouteCaptureDirroute'ActionNoRoute routeHeightrouteEarliestNC splitPathpRoute Data.EitherEitherTrueFalse foldPartscaptureVariableOrReadFileinternalFoldMultipartmaxNumberOfFilesmaxFileUploadSizeskipEmptyFileNamemaxEmptyFileNameSize uploadTimeoutminimumUploadRateminimumUploadSecondsmaximumNumberOfFormInputsprocessFormInputsmaximumFormInputSizeWrappedFileUploadExceptiontoPartDispositionMultipartState numFormVars numFormFilescapturedFields accumulatorFileExceptionWithReasonexceptionReason UploadStatenumUploadedFiles uploadedFilessnapIndexStylesdecodeFilePathRangeReqSuffixRangeReq)network-uri-2.6.1.0-RmiO7Es4EVIxdXQfHHaUt Network.URIURI'hashable-1.2.6.1-JDYnvpSucMf1h1i2CUUtVbData.Hashable.ClassHashable3unordered-containers-0.2.8.0-3iSQJVS3Sio885UUC852oj Data.HashSetHashSet