127 lines
3.8 KiB
C++
127 lines
3.8 KiB
C++
#include <lexbor/html/parser.h>
|
|
#include <lexbor/dom/interfaces/element.h>
|
|
#include <lexbor/dom/interfaces/node.h>
|
|
#include <fstream>
|
|
#include <map>
|
|
#include "config.h"
|
|
#include "clients/remote_client.h"
|
|
#include "clients/archiveorg.h"
|
|
#include "util.h"
|
|
|
|
using httplib::Client;
|
|
using httplib::Headers;
|
|
using httplib::Result;
|
|
|
|
struct InsensitiveCompare
|
|
{
|
|
bool operator()(const std::string &a, const std::string &b) const
|
|
{
|
|
return strcasecmp(a.c_str(), b.c_str()) < 0;
|
|
}
|
|
};
|
|
|
|
static std::set<std::string, InsensitiveCompare> ignore_cookie_keys = {"path", "expires", "max-age", "domain", "secure"};
|
|
|
|
std::string ArchiveOrgClient::GenerateRandomId(const int len)
|
|
{
|
|
static const char alphanum[] = "0123456789abcdef";
|
|
std::string tmp_s;
|
|
tmp_s.reserve(len);
|
|
|
|
for (int i = 0; i < len; ++i) {
|
|
tmp_s += alphanum[rand() % (sizeof(alphanum) - 1)];
|
|
}
|
|
|
|
return tmp_s;
|
|
}
|
|
|
|
int ArchiveOrgClient::Connect(const std::string &url, const std::string &username, const std::string &password)
|
|
{
|
|
this->host_url = url;
|
|
size_t scheme_pos = url.find("://");
|
|
size_t root_pos = url.find("/", scheme_pos + 3);
|
|
if (root_pos != std::string::npos)
|
|
{
|
|
this->host_url = url.substr(0, root_pos);
|
|
this->base_path = url.substr(root_pos);
|
|
}
|
|
client = new httplib::Client(this->host_url);
|
|
client->set_keep_alive(true);
|
|
client->set_follow_location(true);
|
|
client->set_connection_timeout(30);
|
|
client->set_read_timeout(30);
|
|
client->enable_server_certificate_verification(false);
|
|
|
|
this->cookies = {
|
|
{"donation-identifier", GenerateRandomId(32)},
|
|
{"test-cookie", "1"},
|
|
{"abtest-identifier", GenerateRandomId(32)}
|
|
};
|
|
|
|
if (username.length() > 0)
|
|
return Login(username, password);
|
|
|
|
this->connected = true;
|
|
return 1;
|
|
}
|
|
|
|
int ArchiveOrgClient::Login(const std::string &username, const std::string &password)
|
|
{
|
|
std::string url = std::string("/account/login");
|
|
Headers headers = {{ "User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0"}};
|
|
SetCookies(headers);
|
|
|
|
MultipartFormDataItems items = {
|
|
{"username", username, "", ""},
|
|
{"password", password, "", ""},
|
|
{"remember", "true", "", ""},
|
|
{"referer", "https://archive.org/", "", ""},
|
|
{"login", "true", "", ""},
|
|
{"submit_by_js", "true", "", ""}};
|
|
|
|
if (auto res = client->Post(url, headers, items))
|
|
{
|
|
if (HTTP_SUCCESS(res->status))
|
|
{
|
|
if (res->has_header("Set-Cookie"))
|
|
{
|
|
int cookies_count = res->get_header_value_count("Set-Cookie");
|
|
|
|
for (int i = 0; i < cookies_count; i++)
|
|
{
|
|
std::string cookie_str = res->get_header_value("Set-Cookie", i);
|
|
|
|
std::vector<std::string> cookies = Util::Split(cookie_str, ";");
|
|
for (std::vector<std::string>::iterator it = cookies.begin(); it != cookies.end();)
|
|
{
|
|
std::vector<std::string> cookie = Util::Split(*it, "=");
|
|
std::string key = Util::Trim(cookie[0], " ");
|
|
if (ignore_cookie_keys.find(key) == ignore_cookie_keys.end())
|
|
{
|
|
if (cookie.size() > 1)
|
|
this->cookies[key] = Util::Trim(cookie[1], " ");
|
|
else
|
|
this->cookies[key] = "";
|
|
}
|
|
++it;
|
|
}
|
|
}
|
|
this->connected = true;
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|