emailQt/CurlHandler.cpp

105 lines
3.3 KiB
C++
Executable File

#include "CurlHandler.hpp"
CurlHandler::CurlHandler()
: initialRes{}, initialCurl(curl_easy_init(), curl_easy_cleanup) {
}
CurlHandler::~CurlHandler() {
for (auto &t: v)
t.join();
}
void CurlHandler::configure(const ParametersProvider::settings &sett) {
url.append("imaps://");
url += sett.imapS;
url += "/INBOX?ALL";
setts = sett;
setupCurl(initialCurl.get(), initialChunk, url);
}
std::vector<std::string> *CurlHandler::fetch() {
initialRes = curl_easy_perform(initialCurl.get());
if (initialRes != CURLE_OK) {
return &decodedMessages;
}
// We prepare to query the server.
url.erase(url.end() - 4, url.end());
url += "/;MAILINDEX=";
std::string temp;
std::stringstream s(initialChunk);
size_t count = 0;
while (getline(s, temp, ' ')) {
// SELECT and *
if (count < 2) {
count++;
continue;
}
messagesId.emplace_back(temp);
}
// We will query the server number by number.
// The messagesId vector contains all Email GUIDs.
v.reserve(messagesId.size());
decodedMessages.resize(messagesId.size());
count = 0;
// 10 messages max
// By default, even if the thread's function parameter specifies a reference,
// a copy is made. To specify that you want a reference, use std::ref.
for (auto i{messagesId.rbegin()}; i != messagesId.rbegin() + 10 && i != messagesId.rend(); ++i)
v.emplace_back(&CurlHandler::query, this, std::ref(*i), count++);
return &decodedMessages;
}
void CurlHandler::query(std::string &c, size_t count) {
std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> localCurl(curl_easy_init(), curl_easy_cleanup);
CURLcode localCode;
c.erase(std::remove(c.begin(), c.end(), '\r'), c.end());
c.erase(std::remove(c.begin(), c.end(), '\n'), c.end());
setupCurl(localCurl.get(), decodedMessages[count], url + c);
localCode = curl_easy_perform(localCurl.get());
if (localCode != CURLE_OK) {
// ...
}
emit threadFinished(count, std::stoi(c));
}
void CurlHandler::setupCurl(CURL *ptr, std::string &m, std::string const &ur) const {
curl_easy_setopt(ptr, CURLOPT_USERNAME, setts.userS.c_str());
curl_easy_setopt(ptr, CURLOPT_PASSWORD, setts.passS.c_str());
curl_easy_setopt(ptr, CURLOPT_PORT, setts.port);
curl_easy_setopt(ptr, CURLOPT_TIMEOUT, curlTimeoutSeconds);
// The callback function will receive the string ref as its userdata
// and therefore save the data there.
curl_easy_setopt(ptr, CURLOPT_USE_SSL, (long) CURLUSESSL_ALL);
curl_easy_setopt(ptr, CURLOPT_WRITEDATA, (void *) &m);
curl_easy_setopt(ptr, CURLOPT_WRITEFUNCTION, cb);
// Necessary on some servers
curl_easy_setopt(ptr, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(ptr, CURLOPT_URL, ur.c_str());
#ifdef DEBUG
curl_easy_setopt(ptr, CURLOPT_VERBOSE, 1L);
#else
curl_easy_setopt(ptr.get(), CURLOPT_VERBOSE, 0L);
#endif
}
size_t cb(char *data, size_t size, size_t numberOfMembers, void *userdata) {
size_t realSize = size * numberOfMembers;
auto *mem = static_cast<std::string *> (userdata);
mem->append(data, realSize);
return realSize;
}