#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 *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 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 (userdata); mem->append(data, realSize); return realSize; }