aboutsummaryrefslogtreecommitdiff
path: root/src/core/page_processor.cc
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-04-14 14:38:42 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-04-14 14:38:42 +0800
commit10c3746a6df45dd154955a9e91e662260f36363f (patch)
tree0c9c879439baf659d875ec1438154ca9ea71faf1 /src/core/page_processor.cc
parentd4f78be6f231b5289eb1c658d1f67006b7d884dd (diff)
downloadrwebbrowser-10c3746a6df45dd154955a9e91e662260f36363f.tar.gz
rwebbrowser-10c3746a6df45dd154955a9e91e662260f36363f.tar.xz
refactor: adjust code structure
Diffstat (limited to 'src/core/page_processor.cc')
-rw-r--r--src/core/page_processor.cc97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/core/page_processor.cc b/src/core/page_processor.cc
new file mode 100644
index 0000000..00728a9
--- /dev/null
+++ b/src/core/page_processor.cc
@@ -0,0 +1,97 @@
+/*
+ * Ricochet - A minimalist CLI web browser for fast, distraction-free navigation.
+ * Copyright (C) 2026 Richard Qin
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "ricochet/core/page_processor.hh"
+#include <fstream>
+#include <ranges>
+#include <vector>
+
+namespace ricochet::core {
+
+std::string extract_title( const parser::DomNode& root_node )
+{
+ std::vector<const parser::DomNode*> stack;
+ stack.push_back( &root_node );
+
+ while ( !stack.empty() ) {
+ const parser::DomNode* current = stack.back();
+ stack.pop_back();
+
+ std::string base_tag = current->tag_name;
+ const std::size_t space_pos = base_tag.find( ' ' );
+ if ( space_pos != std::string::npos ) {
+ base_tag = base_tag.substr( 0, space_pos );
+ }
+
+ for ( char& c : base_tag ) {
+ if ( c >= 'A' && c <= 'Z' ) {
+ c = static_cast<char>( c + 32 );
+ }
+ }
+
+ if ( base_tag == "title" ) {
+ std::string full_title;
+ for ( const auto& child : current->children ) {
+ if ( child.tag_name.empty() ) {
+ full_title += child.text_content;
+ }
+ }
+ if ( !full_title.empty() ) {
+ return full_title;
+ }
+ }
+
+ for ( const auto& child : std::ranges::reverse_view( current->children ) ) {
+ stack.push_back( &child );
+ }
+ }
+ return "";
+}
+
+PageData process_binary_download( const HttpRequest& req, const net::HttpResponse& resp )
+{
+ std::string fname = "download.dat";
+ const std::size_t slash = req.url.rfind( '/' );
+ if ( slash != std::string::npos && slash + 1 < req.url.length() ) {
+ fname = req.url.substr( slash + 1 );
+ const std::size_t q_pos = fname.find( '?' );
+ if ( q_pos != std::string::npos ) {
+ fname = fname.substr( 0, q_pos );
+ }
+ }
+ if ( fname.empty() ) {
+ fname = "download.dat";
+ }
+
+ std::ofstream out( fname, std::ios::binary );
+ out.write( resp.body.data(), static_cast<std::streamsize>( resp.body.size() ) );
+ out.close();
+
+ return { .lines = { "\033[1;32m[ Download Complete ]\033[0m",
+ "",
+ "Saved File : " + fname,
+ "File Type : " + resp.content_type,
+ "File Size : " + std::to_string( resp.body.size() ) + " bytes",
+ "",
+ "Press 'H' to return to the previous page." },
+ .links = {},
+ .inputs = {},
+ .title = "Download Manager" };
+}
+
+} // namespace ricochet::core