Rewrite pixiv URLs to Pixwhile

This commit is contained in:
blankie 2023-04-10 00:34:13 +07:00
parent 3f45dce9f8
commit 79bae2c013
Signed by: blankie
GPG Key ID: CC15FC822C7F61F5
5 changed files with 46 additions and 22 deletions

View File

@ -1,5 +1,6 @@
#include <regex> #include <regex>
#include <vector> #include <vector>
#include <ctype.h>
#include <climits> #include <climits>
#include "murl.h" #include "murl.h"
@ -14,7 +15,7 @@
// A lot looser than RFC 3986, but things will go very wrong very quickly if I comply // A lot looser than RFC 3986, but things will go very wrong very quickly if I comply
// Hostname does not allow for stuff like "//The", but it is not important here // Hostname does not allow for stuff like "//The", but it is not important here
#define HOSTCHAR "[\\w\\d\\-.]" #define HOSTCHAR "[\\w\\d\\-.]"
#define HOST "(\\[[\\da-f:.]+\\]|" HOSTCHAR "+(?:\\." HOSTCHAR "+)+)" #define HOST "(\\[[\\da-f:.]+\\]|localhost|" HOSTCHAR "+(?:\\." HOSTCHAR "+)+)"
#define PORT "(\\d*)" #define PORT "(\\d*)"
#define AUTHORITY "(?:" USERINFO "@)?" HOST "(?::" PORT ")?" #define AUTHORITY "(?:" USERINFO "@)?" HOST "(?::" PORT ")?"
@ -38,6 +39,7 @@
"(?:#" FRAGMENT ")?" "(?:#" FRAGMENT ")?"
static void handle_segment(std::vector<std::string>& segments, const std::string& str, size_t offset, size_t length); static void handle_segment(std::vector<std::string>& segments, const std::string& str, size_t offset, size_t length);
static std::string tolower(std::string str);
namespace blankie { namespace blankie {
namespace murl { namespace murl {
@ -87,6 +89,10 @@ std::string Url::to_string() const {
return str; return str;
} }
bool Url::is_host_equal(std::string other) const {
return tolower(this->hostname) == tolower(std::move(other));
}
std::string normalize_path(const std::string& str) { std::string normalize_path(const std::string& str) {
std::vector<std::string> segments; std::vector<std::string> segments;
std::string res; std::string res;
@ -143,3 +149,10 @@ static void handle_segment(std::vector<std::string>& segments, const std::string
segments.push_back(str.substr(offset, length)); segments.push_back(str.substr(offset, length));
} }
} }
static std::string tolower(std::string str) {
for (size_t i = 0; i < str.size(); i++) {
str[i] = static_cast<char>(tolower(str[i]));
}
return str;
}

View File

@ -32,6 +32,9 @@ struct Url {
return res; return res;
} }
// NOT SECURE!
bool is_host_equal(std::string other) const;
std::string to_string() const; std::string to_string() const;
}; };

View File

@ -9,8 +9,8 @@
static inline Element generate_user_link(const httplib::Request& req, const Config& config, const Illust& illust); static inline Element generate_user_link(const httplib::Request& req, const Config& config, const Illust& illust);
static inline Element generate_images(const httplib::Request& req, const Config& config, const Illust& illust); static inline Element generate_images(const httplib::Request& req, const Config& config, const Illust& illust);
static inline Element generate_preview_images(const httplib::Request& req, const Config& config, const Illust& illust); static inline Element generate_preview_images(const httplib::Request& req, const Config& config, const Illust& illust);
static inline std::vector<blankie::html::Node> parse_description_line(std::string str); static inline std::vector<blankie::html::Node> parse_description_line(const httplib::Request& req, const Config& config, std::string str);
static inline Element generate_description(const std::string& description); static inline Element generate_description(const httplib::Request& req, const Config& config, const std::string& description);
static inline Element generate_illust_tags(const Illust& illust); static inline Element generate_illust_tags(const Illust& illust);
static inline bool is_true(const std::string& str); static inline bool is_true(const std::string& str);
@ -45,7 +45,7 @@ void artworks_route(const httplib::Request& req, httplib::Response& res, const C
Element("br") Element("br")
}); });
if (illust.comment) { if (illust.comment) {
body.nodes.push_back(generate_description(*illust.comment)); body.nodes.push_back(generate_description(req, config, *illust.comment));
} }
body.nodes.push_back(generate_illust_tags(illust)); body.nodes.push_back(generate_illust_tags(illust));
body.nodes.push_back(Element("p", {time_to_string(illust.upload_time)})); body.nodes.push_back(Element("p", {time_to_string(illust.upload_time)}));
@ -112,8 +112,7 @@ static inline Element generate_preview_images(const httplib::Request& req, const
return div; return div;
} }
// TODO proxy urls static inline std::vector<blankie::html::Node> parse_description_line(const httplib::Request& req, const Config& config, std::string str) {
static inline std::vector<blankie::html::Node> parse_description_line(std::string str) {
std::vector<blankie::html::Node> nodes; std::vector<blankie::html::Node> nodes;
std::smatch sm; std::smatch sm;
@ -121,7 +120,13 @@ static inline std::vector<blankie::html::Node> parse_description_line(std::strin
if (sm.prefix().length()) { if (sm.prefix().length()) {
nodes.push_back(sm.prefix()); nodes.push_back(sm.prefix());
} }
nodes.push_back(Element("a", {{"href", sm.str(0)}}, {sm.str(0)}));
blankie::murl::Url url(sm.str(0));
std::string url_str = url.is_host_equal("pixiv.net") || url.is_host_equal("www.pixiv.net")
? proxy_url(get_origin(req, config), std::move(url))
: url.to_string();
nodes.push_back(Element("a", {{"href", url_str}}, {url_str}));
str = sm.suffix(); str = sm.suffix();
} }
if (!str.empty()) { if (!str.empty()) {
@ -131,7 +136,7 @@ static inline std::vector<blankie::html::Node> parse_description_line(std::strin
return nodes; return nodes;
} }
static inline Element generate_description(const std::string& description) { static inline Element generate_description(const httplib::Request& req, const Config& config, const std::string& description) {
Element p("p"); Element p("p");
size_t pos = 0; size_t pos = 0;
size_t last_pos = 0; size_t last_pos = 0;
@ -139,7 +144,7 @@ static inline Element generate_description(const std::string& description) {
if (!p.nodes.empty()) { if (!p.nodes.empty()) {
p.nodes.push_back(Element("br")); p.nodes.push_back(Element("br"));
} }
std::vector<blankie::html::Node> nodes = parse_description_line(std::move(str)); std::vector<blankie::html::Node> nodes = parse_description_line(req, config, std::move(str));
p.nodes.insert(p.nodes.end(), nodes.begin(), nodes.end()); p.nodes.insert(p.nodes.end(), nodes.begin(), nodes.end());
}; };

View File

@ -72,20 +72,22 @@ std::string get_origin(const httplib::Request& req, const Config& config) {
return origin; return origin;
} }
std::string proxy_url(blankie::murl::Url base, blankie::murl::Url url) {
if (!url.path.empty() && url.path[0] != '/') {
base.path += '/';
}
base.path += blankie::murl::normalize_path(std::move(url.path));
if (!base.query.empty() && !url.query.empty()) {
base.query += '&';
}
base.query += std::move(url.query);
base.fragment = std::move(url.fragment);
return base.to_string();
}
std::string proxy_image_url(const Config& config, blankie::murl::Url url) { std::string proxy_image_url(const Config& config, blankie::murl::Url url) {
if (url.hostname == "s.pximg.net") { if (url.is_host_equal("s.pximg.net")) {
return url.to_string(); return url.to_string();
} }
return proxy_url(config.image_proxy_url, std::move(url));
blankie::murl::Url new_url = config.image_proxy_url;
if (!url.path.empty() && url.path[0] != '/') {
new_url.path += '/';
}
new_url.path += blankie::murl::normalize_path(std::move(url.path));
if (!new_url.query.empty() && !url.query.empty()) {
new_url.query += '&';
new_url.query += std::move(url.query);
}
new_url.fragment = std::move(url.fragment);
return new_url.to_string();
} }

View File

@ -14,4 +14,5 @@ void serve_error(const httplib::Request& req, httplib::Response& res, const Conf
std::string title, std::optional<std::string> subtitle = std::nullopt, std::optional<std::string> info = std::nullopt); std::string title, std::optional<std::string> subtitle = std::nullopt, std::optional<std::string> info = std::nullopt);
void serve_redirect(const httplib::Request& req, httplib::Response& res, const Config& config, std::string url); void serve_redirect(const httplib::Request& req, httplib::Response& res, const Config& config, std::string url);
std::string get_origin(const httplib::Request& req, const Config& config); std::string get_origin(const httplib::Request& req, const Config& config);
std::string proxy_url(blankie::murl::Url base, blankie::murl::Url url);
std::string proxy_image_url(const Config& config, blankie::murl::Url url); std::string proxy_image_url(const Config& config, blankie::murl::Url url);