Mercurial > minori
view src/core/http.cc @ 327:b5d6c27c308f
anime: refactor Anime::SeriesSeason to Season class
ToLocalString has also been altered to take in both season
and year because lots of locales actually treat formatting
seasons differently! most notably is Russian which adds a
suffix at the end to notate seasons(??)
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Thu, 13 Jun 2024 01:49:18 -0400 |
parents | d928ec7b6a0d |
children |
line wrap: on
line source
#include "core/http.h" #include "core/session.h" #include <QByteArray> #include <curl/curl.h> #include <iostream> #include <string> #include <vector> namespace HTTP { std::string UrlEncode(const std::string& data) { /* why do I need to init curl just for this? wtf? */ CURL *curl = curl_easy_init(); if (!curl) return ""; /* no way! */ char* output = curl_easy_escape(curl, data.data(), data.size()); if (!output) { curl_easy_cleanup(curl); return ""; } std::string str(output); curl_free(output); curl_easy_cleanup(curl); return str; } std::string UrlDecode(const std::string& data) { CURL *curl = curl_easy_init(); if (!curl) return ""; int outlength; char* output = curl_easy_unescape(curl, data.data(), data.size(), &outlength); if (!output) { curl_easy_cleanup(curl); return ""; } std::string str(output, outlength); curl_free(output); curl_easy_cleanup(curl); return str; } std::string EncodeParamsList(std::string base, const std::map<std::string, std::string>& params) { std::size_t count = 0; for (const auto& param : params) { base += (!count ? "?" : "&"); base += UrlEncode(param.first); base += "="; base += UrlEncode(param.second); count++; } return base; } static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userdata) { reinterpret_cast<QByteArray*>(userdata)->append(reinterpret_cast<char*>(contents), size * nmemb); return size * nmemb; } QByteArray Request(const std::string& url, const std::vector<std::string>& headers, const std::string& data, Type type) { struct curl_slist* list = NULL; QByteArray userdata; CURL* curl = curl_easy_init(); if (curl) { for (const std::string& h : headers) list = curl_slist_append(list, h.c_str()); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); if (type == Type::Post) curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &userdata); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback); /* Use system certs... useful on Windows. */ curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); // threading CURLcode res = curl_easy_perform(curl); session.IncrementRequests(); curl_easy_cleanup(curl); if (res != CURLE_OK) session.SetStatusBar(std::string("curl_easy_perform(curl) failed!: ") + curl_easy_strerror(res)); } return userdata; } /* this function is static */ size_t RequestThread::WriteCallback(void* contents, size_t size, size_t nmemb, void* userdata) { RequestThread* thread = reinterpret_cast<RequestThread*>(userdata); const std::lock_guard<std::mutex> lock(thread->callback_data_mutex_); /* stop writing, then! */ if (thread->cancelled_) return CURL_WRITEFUNC_ERROR; /* else, continue on as normal */ thread->array_.append(reinterpret_cast<char*>(contents), size * nmemb); return size * nmemb; } RequestThread::RequestThread(Type type, QObject* parent) : QThread(parent) { SetType(type); } RequestThread::RequestThread(const std::string& url, const std::vector<std::string>& headers, const std::string& data, Type type, QObject* parent) : QThread(parent) { SetUrl(url); SetData(data); SetHeaders(headers); SetType(type); } RequestThread::~RequestThread() { /* block until the function can safely exit */ Stop(); wait(); } void RequestThread::SetUrl(const std::string& url) { url_ = url; } void RequestThread::SetHeaders(const std::vector<std::string>& headers) { headers_ = headers; } void RequestThread::SetData(const std::string& data) { data_ = data; } void RequestThread::SetType(Type type) { type_ = type; } void RequestThread::run() { struct curl_slist* list = NULL; CURL* curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url_.c_str()); if (type_ == Type::Post) curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data_.c_str()); for (const std::string& h : headers_) list = curl_slist_append(list, h.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); curl_easy_setopt(curl, CURLOPT_WRITEDATA, this); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &RequestThread::WriteCallback); /* Use system certs... useful on Windows. */ curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA); /* does something with threading, don't remember what though */ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); CURLcode res = curl_easy_perform(curl); session.IncrementRequests(); curl_easy_cleanup(curl); callback_data_mutex_.lock(); if (res != CURLE_OK && !(res == CURLE_WRITE_ERROR && cancelled_)) session.SetStatusBar(std::string("curl_easy_perform(curl) failed!: ") + curl_easy_strerror(res)); callback_data_mutex_.unlock(); } emit ReceivedData(array_); array_.clear(); } void RequestThread::Stop() { const std::lock_guard<std::mutex> lock(callback_data_mutex_); cancelled_ = true; } } // namespace HTTP