From a478e31bd5bf22af38b0d13a0b2117b7bc8597b5 Mon Sep 17 00:00:00 2001 From: yggverse Date: Mon, 16 Sep 2024 14:05:07 +0300 Subject: [PATCH] implement response parser features, add request struct --- src/app/browser/main/tab/page.cpp | 113 ++++++++++++++++++++++-------- src/app/browser/main/tab/page.hpp | 45 +++++++++++- 2 files changed, 125 insertions(+), 33 deletions(-) diff --git a/src/app/browser/main/tab/page.cpp b/src/app/browser/main/tab/page.cpp index bdeb009f..0208aa62 100644 --- a/src/app/browser/main/tab/page.cpp +++ b/src/app/browser/main/tab/page.cpp @@ -323,7 +323,7 @@ void Page::navigation_reload( if (Socket::Connection::is_active(socket__connection)) // @TODO { // Build gemini protocol request - const auto REQUEST = Socket::Client::Gemini::get_request_from_uri( + const auto REQUEST = Socket::Client::Gemini::Request::create_from_uri( uri ); @@ -370,20 +370,41 @@ void Page::navigation_reload( action__update->activate(); // Parse meta - auto meta = Glib::Regex::split_simple( - R"regex(^(\d+)?\s([\w]+\/[\w]+)?)regex", - buffer + Socket::Client::Gemini::Response::Status status; + + Socket::Client::Gemini::Response::Match::meta( + buffer, + status, + mime ); - // Route by status code - if (meta[1] == "20") + // Try detect mime by file extension on still undefined @TODO + if (mime == MIME::UNDEFINED) { - // Route by mime type or path extension - if (meta[2] == "text/gemini" || Glib::str_has_suffix(g_uri_get_path(uri), ".gmi")) + if (Glib::str_has_suffix(g_uri_get_path(uri), ".gmi")) { - // Update mime = MIME::TEXT_GEMINI; + } + + else + { + // Update + title = _("Oops"); + + description = _("MIME type not supported"); + + progress_fraction = 1; + + action__update->activate(); + } + } + + // Route by status code + switch (status) + { + case Socket::Client::Gemini::Response::Status::SUCCESS: + // Update title = _("Done"); // @TODO page title description = g_uri_get_host( @@ -406,36 +427,24 @@ void Page::navigation_reload( } action__update->activate(); - } - else - { + break; + + // @TODO other statuses.. + + default: + // Update title = _("Oops"); - description = _("MIME type not supported"); + description = _("Response code not supported"); progress_fraction = 1; action__update->activate(); - } - } - - else - { - // Update - title = _("Oops"); - - description = Glib::ustring::sprintf( - _("Response code %s not supported"), - meta[1] - ); - - progress_fraction = 1; - - action__update->activate(); } + // Finalize request Socket::Connection::close( socket__connection ); @@ -672,7 +681,7 @@ Glib::RefPtr Page::Socket::Client::Gemini::create() /* * Build request string for Gemini protocol from GUri pointer */ -Glib::ustring Page::Socket::Client::Gemini::get_request_from_uri( +Glib::ustring Page::Socket::Client::Gemini::Request::create_from_uri( GUri * uri ) { return Glib::ustring::sprintf( @@ -683,6 +692,50 @@ Glib::ustring Page::Socket::Client::Gemini::get_request_from_uri( ); } +/* + * Parse meta data from response buffer + */ +bool Page::Socket::Client::Gemini::Response::Match::meta( + const Glib::ustring & RESPONSE, + Status & status, + MIME & mime +) { + // Parse response string + const auto MATCH = Glib::Regex::split_simple( + R"regex(^(\d+)?\s([\w]+\/[\w]+)?)regex", + RESPONSE + ); + + // Detect status code @TODO + if (MATCH[1] == "20") + { + status = Status::SUCCESS; + } + + else + { + status = Status::UNDEFINED; + } + + // Detect MIME @TODO + if (MATCH[2] == "text/gemini") + { + mime = MIME::TEXT_GEMINI; + } + + else if (MATCH[2] == "text/plain") + { + mime = MIME::TEXT_PLAIN; + } + + else + { + mime = MIME::UNDEFINED; + } + + return true; // @TODO +} + /* * Check socket connection active according to page class implementation */ diff --git a/src/app/browser/main/tab/page.hpp b/src/app/browser/main/tab/page.hpp index 0b9755f1..154b5fa0 100644 --- a/src/app/browser/main/tab/page.hpp +++ b/src/app/browser/main/tab/page.hpp @@ -96,13 +96,52 @@ namespace app::browser::main::tab struct Gemini { + // Defaults static const int DEFAULT_PORT = 1965; + // Actions static Glib::RefPtr create(); - static Glib::ustring get_request_from_uri( - GUri * uri - ); + struct Request + { + static Glib::ustring create_from_uri( + GUri * uri + ); + }; + + struct Response + { + /* + * Status codes + * + * 10-19 Input expected + * 20-29 Success + * 30-39 Redirection + * 40-49 Temporary failure + * 50-59 Permanent failure + * 60-69 Client certificates + * + * https://geminiprotocol.net/docs/protocol-specification.gmi#status-codes + */ + enum class Status + { + SUCCESS, + REDIRECT, + TEMPORARY_FAILURE, + PERMANENT_FAILURE, + CERTIFICATE, + UNDEFINED + }; // @TODO explain code groups + + struct Match + { + static bool meta( + const Glib::ustring & RESPONSE, + Status & status, + MIME & mime + ); + }; + }; }; };