diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-04-13 02:55:36 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-04-13 02:55:36 +0800 |
| commit | c29cdb831b7586bb8421ca48e9e78a3a2183aca7 (patch) | |
| tree | 6e7dd7e14f53541ee885a20047c7d2290aaa8b7e /src | |
| parent | 24c36f5250e4c2b4232186ba3d17f949d70f5de2 (diff) | |
| download | rwebbrowser-c29cdb831b7586bb8421ca48e9e78a3a2183aca7.tar.gz rwebbrowser-c29cdb831b7586bb8421ca48e9e78a3a2183aca7.tar.xz | |
feat: implement persistent cookie storage and migrate configuration files to ~/.ricochet directory
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/browser.cc | 14 | ||||
| -rw-r--r-- | src/net/http_client.cc | 47 |
2 files changed, 59 insertions, 2 deletions
diff --git a/src/core/browser.cc b/src/core/browser.cc index e9f1fce..03c34bc 100644 --- a/src/core/browser.cc +++ b/src/core/browser.cc @@ -23,10 +23,12 @@ #include "ricochet/render/renderer.hh" #include "ricochet/tui/terminal.hh" #include <cstddef> +#include <cstdlib> #include <exception> #include <fstream> #include <iostream> #include <ranges> +#include <sys/stat.h> namespace ricochet::core { @@ -47,6 +49,14 @@ struct HttpRequest namespace { +std::string get_config_path( const std::string& filename ) +{ + const char* home = std::getenv( "HOME" ); // NOLINT(concurrency-mt-unsafe) + const std::string dir = ( home != nullptr ) ? std::string( home ) + "/.ricochet" : ".ricochet"; + static_cast<void>( mkdir( dir.c_str(), 0755 ) ); + return dir + "/" + filename; +} + std::string extract_title( const parser::DomNode& root_node ) { std::vector<const parser::DomNode*> stack; @@ -93,7 +103,7 @@ void save_bookmark( const std::string& title, // NOLINT(bugprone-easily-swappabl if ( url == "ricochet://bookmarks" ) { return; } - std::ofstream file( "bookmarks.txt", std::ios::app ); + std::ofstream file( get_config_path( "bookmarks.txt" ), std::ios::app ); if ( !file.is_open() ) { return; } @@ -112,7 +122,7 @@ void save_bookmark( const std::string& title, // NOLINT(bugprone-easily-swappabl std::string generate_bookmarks_html() { - std::ifstream file( "bookmarks.txt" ); + std::ifstream file( get_config_path( "bookmarks.txt" ) ); std::string html = "<html><head><title>My Bookmarks</title></head><body><h1>Saved Bookmarks</h1><ul>"; if ( !file.is_open() ) { html += "<li>No bookmarks found. Press 'b' on any page to add one!</li>"; diff --git a/src/net/http_client.cc b/src/net/http_client.cc index bbc5d17..5a56ac3 100644 --- a/src/net/http_client.cc +++ b/src/net/http_client.cc @@ -23,9 +23,12 @@ #include "ricochet/net/sys/socket.hh" #include <cstddef> +#include <cstdlib> #include <format> +#include <fstream> #include <string> #include <string_view> +#include <sys/stat.h> #include <unordered_map> namespace ricochet::net { @@ -163,15 +166,55 @@ std::string extract_redirect_url( const std::string& raw_response, bool is_https return ""; } +std::string get_config_path( const std::string& filename ) +{ + const char* home = std::getenv( "HOME" ); // NOLINT(concurrency-mt-unsafe) + const std::string dir = ( home != nullptr ) ? std::string( home ) + "/.ricochet" : ".ricochet"; + static_cast<void>( mkdir( dir.c_str(), 0755 ) ); + return dir + "/" + filename; +} + +void load_cookies_from_file( std::unordered_map<std::string, std::string>& jar ) +{ + std::ifstream file( get_config_path( "cookies.txt" ) ); + if ( !file.is_open() ) { + return; + } + std::string line; + while ( std::getline( file, line ) ) { + const std::size_t tab_pos = line.find( '\t' ); + if ( tab_pos != std::string::npos ) { + jar[line.substr( 0, tab_pos )] = line.substr( tab_pos + 1 ); + } + } +} + std::unordered_map<std::string, std::string>& get_cookie_jar() { static std::unordered_map<std::string, std::string> jar; + static bool initialized = false; + if ( !initialized ) { + load_cookies_from_file( jar ); + initialized = true; + } return jar; } +void save_cookies_to_file( const std::unordered_map<std::string, std::string>& jar ) +{ + std::ofstream file( get_config_path( "cookies.txt" ), std::ios::trunc ); + if ( !file.is_open() ) { + return; + } + for ( const auto& [k, v] : jar ) { + file << k << '\t' << v << '\n'; + } +} + void update_cookies( const std::string& raw_response ) { std::size_t pos = 0; + bool updated = false; while ( ( pos = raw_response.find( "Set-Cookie: ", pos ) ) != std::string::npos ) { pos += 12; const std::size_t end_pos = raw_response.find( '\r', pos ); @@ -189,8 +232,12 @@ void update_cookies( const std::string& raw_response ) const std::string key = cookie_pair.substr( 0, eq_pos ); const std::string val = cookie_pair.substr( eq_pos + 1 ); get_cookie_jar()[key] = val; + updated = true; } } + if ( updated ) { + save_cookies_to_file( get_cookie_jar() ); + } } std::string build_cookie_header() |
