From 5fb32fcfca41d2e1b6eaaacaa6b6b37fc9e6d0b1 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sat, 1 Aug 2020 22:50:07 +0300 Subject: Handling status codes by class --- src/gemini.h | 4 +- src/gmutil.c | 198 ++++++++++++++++++++++++++---------------------- src/ui/documentwidget.c | 42 +++++----- src/ui/window.c | 5 +- 4 files changed, 140 insertions(+), 109 deletions(-) diff --git a/src/gemini.h b/src/gemini.h index 863e27f7..564de65b 100644 --- a/src/gemini.h +++ b/src/gemini.h @@ -9,6 +9,7 @@ enum iGmStatusCode { invalidHeader_GmStatusCode, unsupportedMimeType_GmStatusCode, failedToOpenFile_GmStatusCode, + unknownStatusCode_GmStatusCode, none_GmStatusCode = 0, input_GmStatusCode = 10, sensitiveInput_GmStatusCode = 11, @@ -38,4 +39,5 @@ struct Impl_GmError { const char *info; }; -const iGmError * get_GmError (enum iGmStatusCode code); +iBool isDefined_GmError (enum iGmStatusCode code); +const iGmError * get_GmError (enum iGmStatusCode code); diff --git a/src/gmutil.c b/src/gmutil.c index 2008ea36..bf08e960 100644 --- a/src/gmutil.c +++ b/src/gmutil.c @@ -146,97 +146,117 @@ void urlEncodeSpaces_String(iString *d) { } } +static const struct { + enum iGmStatusCode code; + iGmError err; +} errors_[] = { + { unknownStatusCode_GmStatusCode, /* keep this as the first one (fallback return value) */ + { 0x1f4ab, /* dizzy */ + "Unknown Status Code", + "The server responded with a status code that is not specified in the Gemini " + "protocol as known to this client. Maybe the server is from the future? Or " + "just malfunctioning."} }, + { failedToOpenFile_GmStatusCode, + { 0x1f4c1, /* file folder */ + "Failed to Open File", + "The requested file does not exist or is inaccessible. " + "Please check the file path." } }, + { unsupportedMimeType_GmStatusCode, + { 0x1f47d, /* alien */ + "Unsupported MIME Type", + "The received content is in an unsupported format and cannot be viewed with " + "this application." } }, + { invalidHeader_GmStatusCode, + { 0x1f4a9, /* pile of poo */ + "Invalid Header", + "The received header did not conform to the Gemini specification. " + "Perhaps the server is malfunctioning or you tried to contact a " + "non-Gemini server." } }, + { invalidRedirect_GmStatusCode, + { 0, /* */ + "Invalid Redirect", + "The server responded with a redirect but did not provide a valid destination URL. " + "Perhaps the server is malfunctioning." } }, + { temporaryFailure_GmStatusCode, + { 0x1f50c, /* electric plug */ + "Temporary Failure", + "The request has failed, but may succeed if you try again in the future." } }, + { serverUnavailable_GmStatusCode, + { 0x1f525, /* fire */ + "Server Unavailable", + "The server is unavailable due to overload or maintenance. Check back later." } }, + { cgiError_GmStatusCode, + { 0x1f4a5, /* collision */ + "CGI Error", + "Failure during dynamic content generation on the server. This may be due " + "to buggy serverside software." } }, + { proxyError_GmStatusCode, + { 0x1f310, /* globe */ + "Proxy Error", + "A proxy request failed because the server was unable to successfully " + "complete a transaction with the remote host. Perhaps there are difficulties " + "with network connectivity." } }, + { slowDown_GmStatusCode, + { 0x1f40c, /* snail */ + "Slow Down", + "The server is rate limiting requests. Please wait..." } }, + { permanentFailure_GmStatusCode, + { 0x1f6ab, /* no entry */ + "Permanent Failure", + "Your request has failed and will fail in the future as well if repeated." } }, + { notFound_GmStatusCode, + { 0x1f50d, /* magnifying glass */ + "Not Found", + "The requested resource could not be found at this time." } }, + { gone_GmStatusCode, + { 0x1f47b, /* ghost */ + "Gone", + "The resource requested is no longer available and will not be available again." } }, + { proxyRequestRefused_GmStatusCode, + { 0x1f6c2, /* passport control */ + "Proxy Request Refused", + "The request was for a resource at a domain not served by the server and the " + "server does not accept proxy requests." } }, + { badRequest_GmStatusCode, + { 0x1f44e, /* thumbs down */ + "Bad Request", + "The server was unable to parse your request, presumably due to the " + "request being malformed. Likely a bug in Lagrange." } }, + { clientCertificateRequired_GmStatusCode, + { 0x1f511, /* key */ + "Certificate Required", + "Access to the requested resource requires identification via " + "a client certificate." } }, + { certificateNotAuthorized_GmStatusCode, + { 0x1f512, /* lock */ + "Certificate Not Authorized", + "The provided client certificate is valid but is not authorized for accessing " + "the requested resource. " } }, + { certificateNotValid_GmStatusCode, + { 0x1f6a8, /* revolving light */ + "Invalid Certificate", + "The provided client certificate is expired or invalid." } }, +}; + +iBool isDefined_GmError(enum iGmStatusCode code) { + iForIndices(i, errors_) { + if (errors_[i].code == code) { + return iTrue; + } + } + return iFalse; +} + const iGmError *get_GmError(enum iGmStatusCode code) { static const iGmError none = { 0, "", "" }; - static const struct { - enum iGmStatusCode code; - iGmError err; - } errors[] = { - { failedToOpenFile_GmStatusCode, - { 0x1f4c1, /* file folder */ - "Failed to Open File", - "The requested file does not exist or is inaccessible. " - "Please check the file path." } }, - { unsupportedMimeType_GmStatusCode, - { 0x1f47d, /* alien */ - "Unsupported MIME Type", - "The received content is in an unsupported format and cannot be viewed with " - "this application." } }, - { invalidHeader_GmStatusCode, - { 0x1f4a9, /* pile of poo */ - "Invalid Header", - "The received header did not conform to the Gemini specification. " - "Perhaps the server is malfunctioning or you tried to contact a " - "non-Gemini server." } }, - { invalidRedirect_GmStatusCode, - { 0, /* */ - "Invalid Redirect", - "The server responded with a redirect but did not provide a valid destination URL. " - "Perhaps the server is malfunctioning." } }, - { temporaryFailure_GmStatusCode, - { 0x1f50c, /* electric plug */ - "Temporary Failure", - "The request has failed, but may succeed if you try again in the future." } }, - { serverUnavailable_GmStatusCode, - { 0x1f525, /* fire */ - "Server Unavailable", - "The server is unavailable due to overload or maintenance. Check back later." } }, - { cgiError_GmStatusCode, - { 0x1f4a5, /* collision */ - "CGI Error", - "Failure during dynamic content generation on the server. This may be due " - "to buggy serverside software." } }, - { proxyError_GmStatusCode, - { 0x1f310, /* globe */ - "Proxy Error", - "A proxy request failed because the server was unable to successfully " - "complete a transaction with the remote host. Perhaps there are difficulties " - "with network connectivity." } }, - { slowDown_GmStatusCode, - { 0x1f40c, /* snail */ - "Slow Down", - "The server is rate limiting requests. Please wait..." } }, - { permanentFailure_GmStatusCode, - { 0x1f6ab, /* no entry */ - "Permanent Failure", - "Your request has failed and will fail in the future as well if repeated." } }, - { notFound_GmStatusCode, - { 0x1f50d, /* magnifying glass */ - "Not Found", - "The requested resource could not be found at this time." } }, - { gone_GmStatusCode, - { 0x1f47b, /* ghost */ - "Gone", - "The resource requested is no longer available and will not be available again." } }, - { proxyRequestRefused_GmStatusCode, - { 0x1f6c2, /* passport control */ - "Proxy Request Refused", - "The request was for a resource at a domain not served by the server and the " - "server does not accept proxy requests." } }, - { badRequest_GmStatusCode, - { 0x1f44e, /* thumbs down */ - "Bad Request", - "The server was unable to parse your request, presumably due to the " - "request being malformed. Likely a bug in Lagrange." } }, - { clientCertificateRequired_GmStatusCode, - { 0x1f511, /* key */ - "Certificate Required", - "Access to the requested resource requires identification via " - "a client certificate." } }, - { certificateNotAuthorized_GmStatusCode, - { 0x1f512, /* lock */ - "Certificate Not Authorized", - "The provided client certificate is valid but is not authorized for accessing " - "the requested resource. " } }, - { certificateNotValid_GmStatusCode, - { 0x1f6a8, /* revolving light */ - "Invalid Certificate", - "The provided client certificate is expired or invalid." } }, - }; - iForIndices(i, errors) { - if (errors[i].code == code) { - return &errors[i].err; + if (code == 0) { + return &none; + } + iForIndices(i, errors_) { + if (errors_[i].code == code) { + return &errors_[i].err; } } - return &none; + iAssert(errors_[0].code == unknownStatusCode_GmStatusCode); + return &errors_[0].err; /* unknown */ } diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 3b8c468b..c8755fd2 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -419,26 +419,19 @@ static void checkResponseCode_DocumentWidget_(iDocumentWidget *d) { enum iGmStatusCode statusCode = status_GmRequest(d->request); if (d->state == fetching_DocumentState) { d->state = receivedPartialResponse_DocumentState; - switch (statusCode) { - case none_GmStatusCode: - case success_GmStatusCode: - d->scrollY = 0; - reset_GmDocument(d->doc); /* new content incoming */ - updateSource_DocumentWidget_(d); - break; - case input_GmStatusCode: - case sensitiveInput_GmStatusCode: { + switch (statusCode / 10) { + case 1: /* input required */ { iUrl parts; init_Url(&parts, d->url); + printf("%s\n", cstr_String(meta_GmRequest(d->request))); iWidget *dlg = makeValueInput_Widget( as_Widget(d), NULL, format_CStr(cyan_ColorEscape "%s", - cstr_String(collect_String(newRange_String(parts.host)))), + cstr_String(collect_String(newRange_String(parts.host)))), isEmpty_String(meta_GmRequest(d->request)) - ? format_CStr( - "Please enter input for %s:", - cstr_String(collect_String(newRange_String(parts.path)))) + ? format_CStr("Please enter input for %s:", + cstr_String(collect_String(newRange_String(parts.path)))) : cstr_String(meta_GmRequest(d->request)), orange_ColorEscape "Send \u21d2", "document.input.submit"); @@ -446,19 +439,32 @@ static void checkResponseCode_DocumentWidget_(iDocumentWidget *d) { statusCode == sensitiveInput_GmStatusCode); break; } - case redirectTemporary_GmStatusCode: - case redirectPermanent_GmStatusCode: + case 2: /* success */ + d->scrollY = 0; + reset_GmDocument(d->doc); /* new content incoming */ + updateSource_DocumentWidget_(d); + break; + case 3: /* redirect */ if (isEmpty_String(meta_GmRequest(d->request))) { showErrorPage_DocumentWidget_(d, invalidRedirect_GmStatusCode); } else { - postCommandf_App("open redirect:1 url:%s", - cstr_String(meta_GmRequest(d->request))); + postCommandf_App( + "open redirect:1 url:%s", + cstr_String(absoluteUrl_String(d->url, meta_GmRequest(d->request)))); iReleasePtr(&d->request); } break; default: - showErrorPage_DocumentWidget_(d, statusCode); + if (isDefined_GmError(statusCode)) { + showErrorPage_DocumentWidget_(d, statusCode); + } + else if (statusCode / 10 == 4) { + showErrorPage_DocumentWidget_(d, temporaryFailure_GmStatusCode); + } + else if (statusCode / 10 == 5) { + showErrorPage_DocumentWidget_(d, permanentFailure_GmStatusCode); + } break; } } diff --git a/src/ui/window.c b/src/ui/window.c index 83c3d5a3..b438c301 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -9,6 +9,7 @@ #include "labelwidget.h" #include "inputwidget.h" #include "documentwidget.h" +#include "gmutil.h" #if defined (iPlatformMsys) # include "../win32.h" #endif @@ -81,7 +82,9 @@ static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) { if (equal_Command(cmd, "input.ended")) { iInputWidget *url = findChild_Widget(navBar, "url"); if (arg_Command(cmd) && pointer_Command(cmd) == url) { - postCommandf_App("open url:%s", cstr_String(text_InputWidget(url))); + postCommandf_App( + "open url:%s", + cstr_String(absoluteUrl_String(&iStringLiteral(""), text_InputWidget(url)))); return iTrue; } } -- cgit v1.2.3