diff options
author | Adrian Cochrane <alcinnz@lavabit.com> | 2022-08-06 19:25:10 +1200 |
---|---|---|
committer | Adrian Cochrane <alcinnz@lavabit.com> | 2022-08-06 19:25:10 +1200 |
commit | a70796e500daf85c3910125b712af8e84ec0edfc (patch) | |
tree | fd7606433990121ffa9d00cd1f8f37a21e202a11 | |
parent | 5c4812d56d065967a78916152634edb78696237a (diff) | |
download | hurl-a70796e500daf85c3910125b712af8e84ec0edfc.tar.gz hurl-a70796e500daf85c3910125b712af8e84ec0edfc.tar.bz2 hurl-a70796e500daf85c3910125b712af8e84ec0edfc.zip |
Allow overriding localizations logic, including throwing as error.
Release HURL 2.2!
-rw-r--r-- | ChangeLog.md | 7 | ||||
-rw-r--r-- | hurl.cabal | 2 | ||||
-rw-r--r-- | src/Network/URI/Fetch.hs | 43 | ||||
-rw-r--r-- | src/Network/URI/Locale.hs | 94 | ||||
-rw-r--r-- | src/Network/URI/Messages.hs | 163 |
5 files changed, 162 insertions, 147 deletions
diff --git a/ChangeLog.md b/ChangeLog.md index 408704d..3f41653 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,12 @@ # Revision history for hurl +## 2.2.0.0 -- 2022-08-06 +* Fix webform submission, refine API, & support multiple encodings. +* Switch from OpenSSL to `tls`/Cryptonite for a cryptographic backend for better error reporting & to fix Gemini implementation +* Support clientside certificates in Gemini & HTTPS +* Support HSTS with bypass +* Allow overriding HURL's error-reporting localization + ## 2.1.0.1 -- 2021-03-09 * Fixes a build failure. @@ -10,7 +10,7 @@ name: hurl -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change -version: 2.1.0.1 +version: 2.2.0.0 -- A short (one-line) description of the package. synopsis: Haskell URL resolver diff --git a/src/Network/URI/Fetch.hs b/src/Network/URI/Fetch.hs index 9e9e43e..298779e 100644 --- a/src/Network/URI/Fetch.hs +++ b/src/Network/URI/Fetch.hs @@ -108,6 +108,8 @@ data Session = Session { #endif -- | The languages (RFC2616-encoded) to which responses should be localized. locale :: [String], + -- | Callback function for localizing error messages, or throwing exceptions + trans' :: Errors -> String, -- | Additional files to serve from about: URIs. aboutPages :: [(FilePath, ByteString)], -- | Log of timestamped/profiled URL requests @@ -201,6 +203,7 @@ newSession' appname = do rewriter = rewriters, #endif locale = ietfLocale, + trans' = trans ietfLocale, aboutPages = [], requestLog = Nothing, redirectCount = 5, @@ -324,8 +327,8 @@ encodeQuery query = intercalate "&" $ M.mapMaybe encodePart query -- | As per `fetchURL`, but also returns the redirected URI. fetchURL' :: Session -> [String] -> URI -> IO (URI, String, Either Text ByteString) -fetchURL' Session {redirectCount = 0, locale = locale'} _ uri = - return (uri, mimeERR, Left $ Txt.pack $ trans locale' ExcessiveRedirects) +fetchURL' sess@Session {redirectCount = 0 } _ uri = + return (uri, mimeERR, Left $ Txt.pack $ trans' sess ExcessiveRedirects) #ifdef WITH_PLUGIN_REWRITES fetchURL' session mimes uri @@ -333,14 +336,13 @@ fetchURL' session mimes uri #endif #ifdef WITH_PLUGIN_EXEC -fetchURL' session@Session { appName = appname, locale = l } mimes - uri@(URI "ext:" Nothing path query _) = do +fetchURL' session@Session { appName = appname } mimes uri@(URI "ext:" Nothing path query _) = do dir <- getXdgDirectory XdgData "nz.geek.adrian.hurl" sysdirs <- getXdgDirectoryList XdgDataDirs let dirs = concat [[dir' </> appname, dir'] | dir' <- dir : sysdirs] programs <- findExecutablesInDirectories dirs ("bin" </> path) case programs of - [] -> return (uri, mimeERR, Left $ Txt.pack $ trans l $ ReadFailed "404") + [] -> return (uri, mimeERR, Left $ Txt.pack $ trans' session $ ReadFailed "404") program:_ -> do let args = case query of { '?':rest -> split (== '&') rest; @@ -384,7 +386,7 @@ fetchURL' session accept uri | uriScheme uri `elem` ["http:", "https:"] = #endif #ifdef WITH_GEMINI_URI -fetchURL' sess@Session {connCtxt = ctxt, locale = l} mimes uri@URI { +fetchURL' sess@Session { connCtxt = ctxt } mimes uri@URI { uriScheme = "gemini:", uriAuthority = Just (URIAuth _ host port) } = do let params = TLS.defaultParamsClient host "gmni" @@ -418,12 +420,12 @@ fetchURL' sess@Session {connCtxt = ctxt, locale = l} mimes uri@URI { redirectCount = redirectCount sess - 1 } mimes $ relativeTo redirect' uri (x, y, err) -> return (uri, mimeERR, Left $ Txt.pack $ - trans l $ GeminiError x y $ Txt.unpack $ + trans' sess $ GeminiError x y $ Txt.unpack $ Txt.replace "<" "<" $ Txt.replace "&" "&" err) where parseHeader :: String -> (Char, Char, Text) parseHeader (major:minor:meta) = (major, minor, Txt.strip $ Txt.pack meta) - parseHeader header = ('4', '1', Txt.pack $ trans l $ MalformedResponse header) + parseHeader header = ('4', '1', Txt.pack $ trans' sess $ MalformedResponse header) handleIOErr :: IOError -> IO Strict.ByteString handleIOErr _ = return "" connectionGetChunks conn = do @@ -432,12 +434,12 @@ fetchURL' sess@Session {connCtxt = ctxt, locale = l} mimes uri@URI { #endif #ifdef WITH_FILE_URI -fetchURL' Session {locale = l} (defaultMIME:_) uri@URI {uriScheme = "file:"} = do +fetchURL' sess (defaultMIME:_) uri@URI {uriScheme = "file:"} = do response <- B.readFile $ uriPath uri return (uri, defaultMIME, Right response) `catch` \e -> do return (uri, mimeERR, - Left $ Txt.pack $ trans l $ ReadFailed $ displayException (e :: IOException)) + Left $ Txt.pack $ trans' sess $ ReadFailed $ displayException (e :: IOException)) #endif #ifdef WITH_DATA_URI @@ -453,21 +455,21 @@ fetchURL' _ (defaultMIME:_) uri@URI {uriScheme = "data:"} = #endif #ifdef WITH_XDG -fetchURL' Session {locale = l, apps = a} _ uri@(URI {uriScheme = s}) = do +fetchURL' sess@Session { apps = a } _ uri@(URI {uriScheme = s}) = do app <- dispatchURIByMIME a uri ("x-scheme-handler/" ++ init s) - return (uri, htmlERR, Left $ Txt.pack $ trans l $ app) + return (uri, htmlERR, Left $ Txt.pack $ trans' sess $ app) #else -fetchURL' Session {locale = l} _ URI {uriScheme = scheme} = - return (uri, mimeERR, Left $ Txt.pack $ trans l $ UnsupportedScheme scheme) +fetchURL' sess _ URI {uriScheme = scheme} = + return (uri, mimeERR, Left $ Txt.pack $ trans' sess $ UnsupportedScheme scheme) #endif dispatchByMIME :: Session -> String -> URI -> IO (Maybe String) #if WITH_XDG -dispatchByMIME Session {locale = l, apps = a} mime uri = do +dispatchByMIME sess@Session { apps = a } mime uri = do err <- dispatchURIByMIME a uri mime return $ case err of UnsupportedMIME _ -> Nothing - _ -> Just $ trans l err + _ -> Just $ trans' sess err #else dispatchByMIME _ _ _ = return Nothing #endif @@ -497,7 +499,8 @@ dispatchByApp _ _ _ _ = return False #endif #ifdef WITH_HTTP_URI -fetchHTTPCached session shouldCache accept@(defaultMIME:_) rawUri cbReq cbResp = do +fetchHTTPCached session @ Session { trans' = t} shouldCache + accept@(defaultMIME:_) rawUri cbReq cbResp = do now <- getCurrentTime hsts <- readMVar $ hstsDomains session uri <- case (uriScheme rawUri, uriAuthority rawUri) of { @@ -556,7 +559,7 @@ fetchHTTPCached session shouldCache accept@(defaultMIME:_) rawUri cbReq cbResp = return $ Left $ relativeTo uri' uri (Status code msg, "", _) -> return $ Right (Txt.pack mimeERR, B.fromStrict $ C8.pack $ - trans (locale session) $ HTTPStatus code $ C8.unpack msg) + trans' session $ HTTPStatus code $ C8.unpack msg) (_, body, (mimetype:_)) -> do cacheHTTP uri response forkIO cleanCacheHTTP -- Try to keep diskspace down... @@ -572,9 +575,9 @@ fetchHTTPCached session shouldCache accept@(defaultMIME:_) rawUri cbReq cbResp = Right (mime, body) -> let mime' = L.map (Txt.unpack . Txt.strip) $ Txt.splitOn ";" mime in return $ resolveCharset' uri mime' body - `catch` \e -> do return (rawUri, mimeERR, Left $ Txt.pack $ transHttp (locale session) e) + `catch` \e -> do return (rawUri, mimeERR, Left $ Txt.pack $ transHttp t e) fetchHTTPCached session _ [] uri _ _ = - return (uri, mimeERR, Left $ Txt.pack $ trans (locale session) $ UnsupportedMIME "") + return (uri, mimeERR, Left $ Txt.pack $ trans' session $ UnsupportedMIME "") #endif #if WITH_HTTP_URI || WITH_GEMINI_URI diff --git a/src/Network/URI/Locale.hs b/src/Network/URI/Locale.hs index d537d1e..9a4061a 100644 --- a/src/Network/URI/Locale.hs +++ b/src/Network/URI/Locale.hs @@ -70,64 +70,64 @@ split _ [] = [[]] ---- Decoupling Layer -------- #ifdef WITH_HTTP_URI -transHttp locales (InvalidUrlException url msg) = trans locales $ InvalidUrl url msg -transHttp locales (HttpExceptionRequest _ (TooManyRedirects _)) = trans locales $ ExcessiveRedirects -transHttp locales (HttpExceptionRequest _ ResponseTimeout) = trans locales $ TimeoutResponse -transHttp locales (HttpExceptionRequest _ ConnectionTimeout) = trans locales $ TimeoutConnection -transHttp locales (HttpExceptionRequest _ (ConnectionFailure err)) = - trans locales $ FailedConnect $ displayException err -transHttp locales (HttpExceptionRequest _ (StatusCodeException _ code)) = - trans locales $ HTTPStatus (fromMaybe 500 $ readMaybe $ C8.unpack code) "" -transHttp locales (HttpExceptionRequest _ OverlongHeaders) = - trans locales $ HTTPStatus 431 "Overlong Headers" -transHttp locales (HttpExceptionRequest _ (InvalidStatusLine why)) = - trans locales $ MalformedResponse $ C8.unpack why -transHttp locales (HttpExceptionRequest _ (InvalidHeader why)) = - trans locales $ MalformedResponse $ C8.unpack why -transHttp locales (HttpExceptionRequest _ (InvalidRequestHeader why)) = - trans locales $ InvalidRequest $ C8.unpack why -transHttp locales (HttpExceptionRequest _ (ProxyConnectException a b (Status code msg))) = - trans locales $ ProxyError (C8.unpack a) b code $ C8.unpack msg +transHttp trans' (InvalidUrlException url msg) = trans' $ InvalidUrl url msg +transHttp trans' (HttpExceptionRequest _ (TooManyRedirects _)) = trans' $ ExcessiveRedirects +transHttp trans' (HttpExceptionRequest _ ResponseTimeout) = trans' $ TimeoutResponse +transHttp trans' (HttpExceptionRequest _ ConnectionTimeout) = trans' $ TimeoutConnection +transHttp trans' (HttpExceptionRequest _ (ConnectionFailure err)) = + trans' $ FailedConnect $ displayException err +transHttp trans' (HttpExceptionRequest _ (StatusCodeException _ code)) = + trans' $ HTTPStatus (fromMaybe 500 $ readMaybe $ C8.unpack code) "" +transHttp trans' (HttpExceptionRequest _ OverlongHeaders) = + trans' $ HTTPStatus 431 "Overlong Headers" +transHttp trans' (HttpExceptionRequest _ (InvalidStatusLine why)) = + trans' $ MalformedResponse $ C8.unpack why +transHttp trans' (HttpExceptionRequest _ (InvalidHeader why)) = + trans' $ MalformedResponse $ C8.unpack why +transHttp trans' (HttpExceptionRequest _ (InvalidRequestHeader why)) = + trans' $ InvalidRequest $ C8.unpack why +transHttp trans' (HttpExceptionRequest _ (ProxyConnectException a b (Status code msg))) = + trans' $ ProxyError (C8.unpack a) b code $ C8.unpack msg -- NOTE: Minor details are unlocalized for now... Can always come back to this! -transHttp locales (HttpExceptionRequest _ NoResponseDataReceived) = - trans locales $ MalformedResponse "Empty" -transHttp locales (HttpExceptionRequest _ TlsNotSupported) = - trans locales $ HandshakeMisc "Unsupported" -transHttp locales (HttpExceptionRequest _ (WrongRequestBodyStreamSize a b)) = - trans locales $ OtherException $ unlines ["Wrong request bodysize", show a, show b] -transHttp locales (HttpExceptionRequest _ (ResponseBodyTooShort a b)) = - trans locales $ MalformedResponse ("Too short " ++ show a ++ '<' : show b) -transHttp locales (HttpExceptionRequest _ InvalidChunkHeaders) = - trans locales $ MalformedResponse "Chunk headers" -transHttp locales (HttpExceptionRequest _ IncompleteHeaders) = - trans locales $ MalformedResponse "Incomplete headers" -transHttp locales (HttpExceptionRequest _ (InvalidDestinationHost why)) = - trans locales $ FailedConnect $ C8.unpack why -transHttp locales (HttpExceptionRequest _ (HttpZlibException _)) = - trans locales $ MalformedResponse "ZLib compression" -transHttp locales (HttpExceptionRequest _ ConnectionClosed) = - trans locales $ FailedConnect "already-closed" -transHttp locales (HttpExceptionRequest _ (InvalidProxySettings why)) = - trans locales $ FailedConnect ("proxy (" ++ Txt.unpack why ++ ")") -transHttp locales (HttpExceptionRequest _ (InvalidProxyEnvironmentVariable key value)) = - trans locales $ FailedConnect ("proxy (" ++ Txt.unpack key ++ '=' : Txt.unpack value ++ ")") -transHttp locales (HttpExceptionRequest _ (InternalException e)) = - trans locales $ case fromException e of +transHttp trans' (HttpExceptionRequest _ NoResponseDataReceived) = + trans' $ MalformedResponse "Empty" +transHttp trans' (HttpExceptionRequest _ TlsNotSupported) = + trans' $ HandshakeMisc "Unsupported" +transHttp trans' (HttpExceptionRequest _ (WrongRequestBodyStreamSize a b)) = + trans' $ OtherException $ unlines ["Wrong request bodysize", show a, show b] +transHttp trans' (HttpExceptionRequest _ (ResponseBodyTooShort a b)) = + trans' $ MalformedResponse ("Too short " ++ show a ++ '<' : show b) +transHttp trans' (HttpExceptionRequest _ InvalidChunkHeaders) = + trans' $ MalformedResponse "Chunk headers" +transHttp trans' (HttpExceptionRequest _ IncompleteHeaders) = + trans' $ MalformedResponse "Incomplete headers" +transHttp trans' (HttpExceptionRequest _ (InvalidDestinationHost why)) = + trans' $ FailedConnect $ C8.unpack why +transHttp trans' (HttpExceptionRequest _ (HttpZlibException _)) = + trans' $ MalformedResponse "ZLib compression" +transHttp trans' (HttpExceptionRequest _ ConnectionClosed) = + trans' $ FailedConnect "already-closed" +transHttp trans' (HttpExceptionRequest _ (InvalidProxySettings why)) = + trans' $ FailedConnect ("proxy (" ++ Txt.unpack why ++ ")") +transHttp trans' (HttpExceptionRequest _ (InvalidProxyEnvironmentVariable key value)) = + trans' $ FailedConnect ("proxy (" ++ Txt.unpack key ++ '=' : Txt.unpack value ++ ")") +transHttp trans' (HttpExceptionRequest _ (InternalException e)) = + trans' $ case fromException e of Just (Terminated _ why _) -> InsecureTerminated why Just (HandshakeFailed (Error_Misc msg)) -> HandshakeMisc msg Just (HandshakeFailed (Error_Protocol (_, _, CloseNotify))) -> HandshakeClosed Just (HandshakeFailed (Error_Protocol (_, _, HandshakeFailure))) -> HandshakeError Just (HandshakeFailed (Error_Protocol (_, _, BadCertificate))) -> InsecureCertificate "" Just (HandshakeFailed (Error_Protocol (_, _, UnsupportedCertificate))) -> - InsecureCertificate $ trans locales InsecureCertificateUnsupported + InsecureCertificate $ trans' InsecureCertificateUnsupported Just (HandshakeFailed (Error_Protocol (_, _, CertificateExpired))) -> - InsecureCertificate $ trans locales InsecureCertificateExpired + InsecureCertificate $ trans' InsecureCertificateExpired Just (HandshakeFailed (Error_Protocol (_, _, CertificateRevoked))) -> - InsecureCertificate $ trans locales InsecureCertificateRevoked + InsecureCertificate $ trans' InsecureCertificateRevoked Just (HandshakeFailed (Error_Protocol (_, _, CertificateUnknown))) -> - InsecureCertificate $ trans locales InsecureCertificateUnknown + InsecureCertificate $ trans' InsecureCertificateUnknown Just (HandshakeFailed (Error_Protocol (_, _, UnknownCa))) -> - InsecureCertificate $ trans locales InsecureCertificateUnknownCA + InsecureCertificate $ trans' InsecureCertificateUnknownCA Just (HandshakeFailed (Error_Protocol (why, _, _))) -> HandshakeMisc why Just (HandshakeFailed (Error_Certificate why)) -> InsecureCertificate why Just (HandshakeFailed (Error_HandshakePolicy why)) -> HandshakePolicy why diff --git a/src/Network/URI/Messages.hs b/src/Network/URI/Messages.hs index 423f7ac..ccb36a6 100644 --- a/src/Network/URI/Messages.hs +++ b/src/Network/URI/Messages.hs @@ -13,58 +13,60 @@ module Network.URI.Messages (trans, Errors(..)) where import Data.List (stripPrefix) import Data.Maybe (fromMaybe) +import Control.Exception (Exception) trans _ (RawXML markup) = markup --- BEGIN LOCALIZATION -trans ("en":_) (UnsupportedScheme scheme) = "Unsupported protocol " ++ scheme -trans ("en":_) (UnsupportedMIME mime) = "Unsupported filetype " ++ mime -trans ("en":_) (RequiresInstall mime appsMarkup) = - "<h1>Please install a compatible app to open <code>" ++ linkType ++ "</code> links</h1>\n" ++ appsMarkup +("en":_) `trans` UnsupportedScheme scheme = "Unsupported protocol " ++ scheme +("en":_) `trans` UnsupportedMIME mime = "Unsupported filetype " ++ mime +("en":_) `trans` RequiresInstall mime appsMarkup = + "<h1>Please install a compatible app to open <code>" ++ linkType ++ + "</code> links</h1>\n" ++ appsMarkup where linkType = fromMaybe mime $ stripPrefix "x-scheme-handler/" mime -trans ("en":_) (OpenedWith app) = "Opened in " ++ app -trans ("en":_) (ReadFailed msg) = "Failed to read file: " ++ msg -trans ("en":_) (MalformedResponse why) = "Invalid response! " ++ why -trans ("en":_) ExcessiveRedirects = "Too many redirects!" -trans ("en":_) (GeminiError '1' '1' label) = +("en":_) `trans` OpenedWith app = "Opened in " ++ app +("en":_) `trans` ReadFailed msg = "Failed to read file: " ++ msg +("en":_) `trans` MalformedResponse why = "Invalid response! " ++ why +("en":_) `trans` ExcessiveRedirects = "Too many redirects!" +("en":_) `trans` GeminiError '1' '1' label = "<form><label>" ++ label ++ "<input type=password></form>" -trans ("en":_) (GeminiError '1' _ label) = "<form><label>" ++ label ++ "<input></form>" -trans ("en":_) (GeminiError '4' '1' _) = "Site unavailable!" -trans ("en":_) (GeminiError '4' '2' _) = "Program error!" -trans ("en":_) (GeminiError '4' '3' _) = "Proxy error!" -trans ("en":_) (GeminiError '4' '4' timeout) = +("en":_) `trans` GeminiError '1' _ label = "<form><label>" ++ label ++ "<input></form>" +("en":_) `trans` GeminiError '4' '1' _ = "Site unavailable!" +("en":_) `trans` GeminiError '4' '2' _ = "Program error!" +("en":_) `trans` GeminiError '4' '3' _ = "Proxy error!" +("en":_) `trans` GeminiError '4' '4' timeout = "Site busy! Please reload after at least " ++ timeout ++ " seconds" -trans ("en":_) (GeminiError '5' '1' _) = "Page not found! Try the <a href='/'>homepage</a>." -trans ("en":_) (GeminiError '5' '2' _) = "Page deleted! Try the <a href='/'>homepage</a>." -trans ("en":_) (GeminiError '5' '3' _) = "Contacted wrong server!" -trans ("en":_) (GeminiError '5' '9' _) = "Malformed request, my bad!" -trans ("en":_) (GeminiError '6' '1' _) = "<form><label>Authentication required" ++ +("en":_) `trans` GeminiError '5' '1' _ = "Page not found! Try the <a href='/'>homepage</a>." +("en":_) `trans` GeminiError '5' '2' _ = "Page deleted! Try the <a href='/'>homepage</a>." +("en":_) `trans` GeminiError '5' '3' _ = "Contacted wrong server!" +("en":_) `trans` GeminiError '5' '9' _ = "Malformed request, my bad!" +("en":_) `trans` GeminiError '6' '1' _ = "<form><label>Authentication required" ++ "<-argo-authenticate error='Unauthorized account!'></-argo-authenticate></form>" -trans ("en":_) (GeminiError '6' '2' _) = "<form><label>Authentication required" ++ +("en":_) `trans` GeminiError '6' '2' _ = "<form><label>Authentication required" ++ "<-argo-authenticate error='Invalid account!'></-argo-authenticate></form>" -trans ("en":_) (GeminiError '6' _ _) = "<form><label>Authentication required" ++ +("en":_) `trans` GeminiError '6' _ _ = "<form><label>Authentication required" ++ "<-argo-authenticate></-argo-authenticate></form>" -trans ("en":_) (GeminiError _ _ error) = error -trans ("en":_) (HTTPStatus 400 _) = "I sent a bad request, according to this site." -trans ("en":_) (HTTPStatus 401 _) = "Authentication required!" -- FIXME: Support HTTP Basic Auth. -trans ("en":_) (HTTPStatus 402 _) = "Payment required!" -trans ("en":_) (HTTPStatus 403 _) = "Access denied!" -trans ("en":_) (HTTPStatus 404 _) = "Page not found! Try the <a href='/'>homepage</a>." -trans ("en":_) (HTTPStatus 405 _) = "Bad webform for this destination webaddress! " ++ +("en":_) `trans` GeminiError _ _ error = error +("en":_) `trans` HTTPStatus 400 _ = "I sent a bad request, according to this site." +("en":_) `trans` HTTPStatus 401 _ = "Authentication required!" -- FIXME: Support HTTP Basic Auth. +("en":_) `trans` HTTPStatus 402 _ = "Payment required!" +("en":_) `trans` HTTPStatus 403 _ = "Access denied!" +("en":_) `trans` HTTPStatus 404 _ = "Page not found! Try the <a href='/'>homepage</a>." +("en":_) `trans` HTTPStatus 405 _ = "Bad webform for this destination webaddress! " ++ "<em>Method not allowed</em>." -trans ("en":_) (HTTPStatus 406 _) = "No representation available for given criteria!" -trans ("en":_) (HTTPStatus 407 _) = "Authentication into proxyserver required!" -trans ("en":_) (HTTPStatus 408 _) = "The site took too long to connect! <em>(HTTP 408)</em>" -trans ("en":_) (HTTPStatus 409 _) = "Request is based on outdated state!" -trans ("en":_) (HTTPStatus 410 _) = "Page deleted! Try the <a href='/'>homepage</a>." -trans ("en":_) (HTTPStatus 411 _) = "I sent a bad request, according to this site." ++ +("en":_) `trans` HTTPStatus 406 _ = "No representation available for given criteria!" +("en":_) `trans` HTTPStatus 407 _ = "Authentication into proxyserver required!" +("en":_) `trans` HTTPStatus 408 _ = "The site took too long to connect! <em>(HTTP 408)</em>" +("en":_) `trans` HTTPStatus 409 _ = "Request is based on outdated state!" +("en":_) `trans` HTTPStatus 410 _ = "Page deleted! Try the <a href='/'>homepage</a>." +("en":_) `trans` HTTPStatus 411 _ = "I sent a bad request, according to this site." ++ "<em>(Missing <code>Content-Length</code> header)</em>" -trans ("en":_) (HTTPStatus 412 _) = "Webpage doesn't meet our preconditions." -trans ("en":_) (HTTPStatus 413 _) = "Payload too large, please upload a smaller file!" -trans ("en":_) (HTTPStatus 414 _) = "Web address is too long for the site!" -trans ("en":_) (HTTPStatus 415 _) = "No representation available for supported filetypes!" -trans ("en":_) (HTTPStatus 416 _) = "Invalid byte-range of requested resource!" -trans ("en":_) (HTTPStatus 417 _) = "Site cannot satisfy our stated expectations!" -trans ("en":_) (HTTPStatus 418 _) = unlines [ +("en":_) `trans` HTTPStatus 412 _ = "Webpage doesn't meet our preconditions." +("en":_) `trans` HTTPStatus 413 _ = "Payload too large, please upload a smaller file!" +("en":_) `trans` HTTPStatus 414 _ = "Web address is too long for the site!" +("en":_) `trans` HTTPStatus 415 _ = "No representation available for supported filetypes!" +("en":_) `trans` HTTPStatus 416 _ = "Invalid byte-range of requested resource!" +("en":_) `trans` HTTPStatus 417 _ = "Site cannot satisfy our stated expectations!" +("en":_) `trans` HTTPStatus 418 _ = unlines [ "<p>I'm a little teapot<br/>", "Short and stout<br/>", "Here is my handle<br/>", @@ -74,50 +76,51 @@ trans ("en":_) (HTTPStatus 418 _) = unlines [ "<q>Tip me over<br/>", "And pour me out!</q></p>" ] -trans ("en":_) (HTTPStatus 421 _) = "Contacted wrong server!" -trans ("en":_) (HTTPStatus 422 _) = "Invalid <strong>WebDAV</strong> request!" -trans ("en":_) (HTTPStatus 423 _) = "<strong>WebDAV</strong> resource is locked!" -trans ("en":_) (HTTPStatus 424 _) = "Failed due to previous failure!" -trans ("en":_) (HTTPStatus 425 _) = "Site requires stronger security on our request!" -trans ("en":_) (HTTPStatus 426 _) = "Site requires newer networking-protocols!" -trans ("en":_) (HTTPStatus 428 _) = "Site requires additional protection to avoid loosing changes!" -trans ("en":_) (HTTPStatus 429 _) = "We sent this site too many requests for it to cope with!" -trans ("en":_) (HTTPStatus 431 _) = "I sent more auxiliary data than this site can cope with!" -trans ("en":_) (HTTPStatus 451 _) = "Requested page cannot legally be provided!" +("en":_) `trans` HTTPStatus 421 _ = "Contacted wrong server!" +("en":_) `trans` HTTPStatus 422 _ = "Invalid <strong>WebDAV</strong> request!" +("en":_) `trans` HTTPStatus 423 _ = "<strong>WebDAV</strong> resource is locked!" +("en":_) `trans` HTTPStatus 424 _ = "Failed due to previous failure!" +("en":_) `trans` HTTPStatus 425 _ = "Site requires stronger security on our request!" +("en":_) `trans` HTTPStatus 426 _ = "Site requires newer networking-protocols!" +("en":_) `trans` HTTPStatus 428 _ = "Site requires additional protection to avoid loosing changes!" +("en":_) `trans` HTTPStatus 429 _ = "We sent this site too many requests for it to cope with!" +("en":_) `trans` HTTPStatus 431 _ = "I sent more auxiliary data than this site can cope with!" +("en":_) `trans` HTTPStatus 451 _ = "Requested page cannot legally be provided!" -trans ("en":_) (HTTPStatus 500 _) = "The site experienced an error generating this webpage. <em>The webmasters have probably already been automatically notified.</em>" -trans ("en":_) (HTTPStatus 501 _) = "Bad webform for this destination webaddress! " ++ - "<em>Method not implemented</em>." -trans ("en":_) (HTTPStatus 502 _) = "Proxyserver got a malformed response!" -trans ("en":_) (HTTPStatus 503 _) = "The site is not available right now!" -trans ("en":_) (HTTPStatus 504 _) = "The site took too long to respond! <em>(Behind proxy)</em>" -trans ("en":_) (HTTPStatus 505 _) = "The site does not speak the language as me! " ++ +("en":_) `trans` HTTPStatus 500 _ = "The site experienced an error generating this webpage. " ++ + "<em>The webmasters have probably already been automatically notified.</em>" +("en":_) `trans` HTTPStatus 501 _ = + "Bad webform for this destination webaddress! <em>Method not implemented</em>." +("en":_) `trans` HTTPStatus 502 _ = "Proxyserver got a malformed response!" +("en":_) `trans` HTTPStatus 503 _ = "The site is not available right now!" +("en":_) `trans` HTTPStatus 504 _ = "The site took too long to respond! <em>(Behind proxy)</em>" +("en":_) `trans` HTTPStatus 505 _ = "The site does not speak the language as me! " ++ "<em>(Unsupported HTTP version)</em>" -trans ("en":_) (HTTPStatus 506 _) = "The site is misconfigured!" -trans ("en":_) (HTTPStatus 507 _) = "Insufficient <strong>WebDAV</strong> storage!" -trans ("en":_) (HTTPStatus 508 _) = "<strong>WebDAV</strong> loop detected!" -trans ("en":_) (HTTPStatus 510 _) = "Further request extensions required!" -trans ("en":_) (HTTPStatus 511 _) = "Authentication into network required!" -trans ("en":_) (HTTPStatus _ error) = error -- Fallback -trans ("en":_) (OtherException error) = "Internal Exception <pre><code>" ++ error ++ "</code></pre>" -trans ("en":_) (InvalidUrl url message) = +("en":_) `trans` HTTPStatus 506 _ = "The site is misconfigured!" +("en":_) `trans` HTTPStatus 507 _ = "Insufficient <strong>WebDAV</strong> storage!" +("en":_) `trans` HTTPStatus 508 _ = "<strong>WebDAV</strong> loop detected!" +("en":_) `trans` HTTPStatus 510 _ = "Further request extensions required!" +("en":_) `trans` HTTPStatus 511 _ = "Authentication into network required!" +("en":_) `trans` HTTPStatus _ error = error -- Fallback +("en":_) `trans` OtherException error = "Internal Exception <pre><code>" ++ error ++ "</code></pre>" +("en":_) `trans` InvalidUrl url message = "Invalid web address <code>" ++ url ++ "</code>: <em>" ++ message ++ "</em>" -trans ("en":_) (ProxyError msg code code' msg') = unlines [ +("en":_) `trans` ProxyError msg code code' msg' = unlines [ "<h1>Proxy failed to forward request!<h1>", "<p>" ++ show code ++ " " ++ msg ++ "</p>", "<p>" ++ show code' ++ " " ++ msg' ++ "</p>" ] -trans ("en":_) (InvalidRequest why) = +("en":_) `trans` InvalidRequest why = "Attempted to send invalid auxiliary data: <em>" ++ why ++ "</em>" -trans ("en":_) InsecureUnestablished = +("en":_) `trans` InsecureUnestablished = "Attempted to send or recieve data before establishing secure connection!" -trans ("en":_) (InsecureCertificate why) = unlines [ +("en":_) `trans` InsecureCertificate why = unlines [ "<h1>The site failed to prove it is who it says it is!</h1>", "<p>" ++ why ++ "</p>", "<p><a href=action:history/back>Leave Insecure Site</a> | ", "<a href=action:novalidate>Accept Imposter Risk & Continue</a></p>" ] -trans ("en":_) (InsecureTerminated why) = "Secure session disconnected! <em>" ++ why ++ "</em>" +("en":_) `trans` InsecureTerminated why = "Secure session disconnected! <em>" ++ why ++ "</em>" trans ("en":_) InsecureCertificateUnknownCA = "The authority vouching for it is unknown to me!" trans ("en":_) InsecureCertificateUnknown = "The cryptographic certificate it has sent us to prove its identity instead " ++ @@ -128,25 +131,25 @@ trans ("en":_) InsecureCertificateExpired = "The cryptographic certificate it has sent us to prove its identity has expired!" trans ("en":_) InsecureCertificateUnsupported = "It has sent us a cryptographic certificate to prove its identity I failed to make sense of." -trans ("en":_) (HandshakePacketUnparsed why) = "Invalid security packet: <em>" ++ why ++ "</em>" -trans ("en":_) (HandshakePacketUnexpected a b) = unlines [ +("en":_) `trans` HandshakePacketUnparsed why = "Invalid security packet: <em>" ++ why ++ "</em>" +("en":_) `trans` HandshakePacketUnexpected a b = unlines [ "<p>Invalid security packet: <em>" ++ a ++ "</em></p>", "<p>" ++ b ++ "</p>" ] -trans ("en":_) (HandshakePacketInvalid why) = "Invalid security packet: <em>" ++ why ++ "</em>" +("en":_) `trans` HandshakePacketInvalid why = "Invalid security packet: <em>" ++ why ++ "</em>" trans ("en":_) HandshakeEOF = "Secure session disconnected!" -trans ("en":_) (HandshakePolicy why) = "Invalid handshake policy: <em>" ++ why ++ "</em>" -trans ("en":_) (HandshakeMisc why) = +("en":_) `trans` HandshakePolicy why = "Invalid handshake policy: <em>" ++ why ++ "</em>" +("en":_) `trans` HandshakeMisc why = "Failed to establish secure connection! <em>" ++ why ++ "</em>" trans ("en":_) HandshakeError = "Failed to negotiate security parameters!" trans ("en":_) HandshakeClosed = "Secure session disconnected!" -trans ("en":_) (FailedConnect why) = "Failed to open connection to the site: <em>" ++ why ++ "</em>" +("en":_) `trans` FailedConnect why = "Failed to open connection to the site: <em>" ++ why ++ "</em>" trans ("en":_) TimeoutConnection = "The site took too long to connect!" trans ("en":_) TimeoutResponse = "The site took too long to respond!" --- END LOCALIZATION trans (_:locales) err = trans locales err -trans [] err = trans ["en"] err +trans [] err = show err data Errors = UnsupportedScheme String | UnsupportedMIME String | RequiresInstall String String | OpenedWith String | ReadFailed String | RawXML String | MalformedResponse String @@ -159,4 +162,6 @@ data Errors = UnsupportedScheme String | UnsupportedMIME String | RequiresInstal | HandshakePacketUnparsed String | HandshakePacketUnexpected String String | HandshakePacketInvalid String | HandshakeEOF | HandshakePolicy String | HandshakeMisc String | HandshakeError | HandshakeClosed - | FailedConnect String | TimeoutConnection | TimeoutResponse + | FailedConnect String | TimeoutConnection | TimeoutResponse deriving (Show) + +instance Exception Errors |