Bunch of fixes

This commit is contained in:
Timothée Leclaire-Fournier 2024-12-19 18:51:41 -05:00
parent 73e44801c0
commit d47678f3c0
9 changed files with 66 additions and 26 deletions

View File

@ -7,6 +7,8 @@ set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG -fsanitize=address,undefined")
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fsanitize=address,undefined")
@ -28,7 +30,7 @@ add_executable(emailQt main.cpp
KeychainClass.cpp
KeychainClass.hpp)
target_link_libraries(emailQt PRIVATE Qt6::Core
target_link_libraries(emailQt PRIVATE Qt6::Core
Qt6::Gui
Qt6::Widgets
CURL::libcurl

View File

@ -15,7 +15,7 @@ void CurlHandler::configure(const ParametersProvider::settings &sett) {
url += "/INBOX?ALL";
setts = sett;
setupCurl(initialCurl, initialChunk, url);
setupCurl(initialCurl.get(), initialChunk, url);
}
std::vector<std::string> *CurlHandler::fetch() {
@ -47,18 +47,21 @@ std::vector<std::string> *CurlHandler::fetch() {
decodedMessages.resize(messagesId.size());
count = 0;
for (auto i{messagesId.rbegin()}; i != messagesId.rbegin() + 10 && i != messagesId.rend(); i++)
// 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::shared_ptr<CURL> localCurl(curl_easy_init(), curl_easy_cleanup);
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, decodedMessages[count], url + c);
setupCurl(localCurl.get(), decodedMessages[count], url + c);
localCode = curl_easy_perform(localCurl.get());
if (localCode != CURLE_OK) {
@ -68,26 +71,26 @@ void CurlHandler::query(std::string &c, size_t count) {
emit threadFinished(count, std::stoi(c));
}
void CurlHandler::setupCurl(std::shared_ptr<CURL> ptr, std::string &m, std::string const &ur) const {
curl_easy_setopt(ptr.get(), CURLOPT_USERNAME, setts.userS.c_str());
curl_easy_setopt(ptr.get(), CURLOPT_PASSWORD, setts.passS.c_str());
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.get(), CURLOPT_PORT, setts.port);
curl_easy_setopt(ptr.get(), CURLOPT_TIMEOUT, curlTimeoutSeconds);
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.get(), CURLOPT_USE_SSL, (long) CURLUSESSL_ALL);
curl_easy_setopt(ptr.get(), CURLOPT_WRITEDATA, (void *) &m);
curl_easy_setopt(ptr.get(), CURLOPT_WRITEFUNCTION, cb);
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.get(), CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(ptr, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(ptr.get(), CURLOPT_URL, ur.c_str());
curl_easy_setopt(ptr, CURLOPT_URL, ur.c_str());
#ifdef DEBUG
curl_easy_setopt(ptr.get(), CURLOPT_VERBOSE, 1L);
curl_easy_setopt(ptr, CURLOPT_VERBOSE, 1L);
#else
curl_easy_setopt(ptr.get(), CURLOPT_VERBOSE, 0L);
#endif
@ -95,7 +98,7 @@ void CurlHandler::setupCurl(std::shared_ptr<CURL> ptr, std::string &m, std::stri
size_t cb(char *data, size_t size, size_t numberOfMembers, void *userdata) {
size_t realSize = size * numberOfMembers;
auto *mem = (std::string *) userdata;
auto *mem = static_cast<std::string *> (userdata);
mem->append(data, realSize);
return realSize;
}

View File

@ -30,14 +30,14 @@ public:
std::vector<std::string> *fetch();
void query(std::string &c, size_t count);
void setupCurl(std::shared_ptr<CURL> ptr, std::string &m, const std::string &ur) const;
void setupCurl(CURL *ptr, std::string &m, const std::string &ur) const;
signals:
void threadFinished(size_t threadId, int uid);
private:
std::string url;
std::shared_ptr<CURL> initialCurl;
std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> initialCurl;
CURLcode initialRes;
std::string initialChunk;

View File

@ -6,15 +6,21 @@ Email::Email(const std::string &str, size_t uid)
}
Email::Email(Email const &e)
: QListWidgetItem(e), uid{e.uid}, titleS(e.titleS), messageS(e.messageS) {
setString(titleS);
: QListWidgetItem(nullptr, QListWidgetItem::UserType),
uid{e.uid},
titleS(e.titleS),
messageS(e.messageS),
rawMessageS(e.rawMessageS) {
setText(QString::fromStdString(titleS));
}
void Email::setString(const std::string &str) {
std::stringstream ss(str);
std::string line;
rawMessageS.clear();
while (std::getline(ss, line)) {
rawMessageS.append(line);
if (line.starts_with("Subject:"))
titleS = line.substr(9);
else if (line.starts_with("Content-Type:"))
@ -32,6 +38,10 @@ const std::string &Email::message() const {
return messageS;
}
const std::string &Email::raw() const {
return rawMessageS;
}
bool Email::operator<(QListWidgetItem const &other) const {
auto a{dynamic_cast<const Email &>(other)};
return this->uid < a.uid;

View File

@ -16,13 +16,15 @@ public:
void setString(const std::string &str);
[[nodiscard]] const std::string &title() const;
[[nodiscard]] const std::string &message() const;
[[nodiscard]] const std::string &raw() const;
bool operator<(const QListWidgetItem &other) const;
bool operator<(const QListWidgetItem &other) const override;
void parseEmailBody(std::stringstream &ss, std::string &line);
private:
std::string titleS;
std::string messageS;
std::string rawMessageS;
size_t uid;
};

View File

@ -1,18 +1,34 @@
#include "EmailDetails.hpp"
EmailDetails::EmailDetails(QWidget *parent)
: QWidget(parent) {
: QWidget(parent), em{} {
t = new QTextEdit;
dbg = new QCheckBox("View raw message");
auto *lay = new QVBoxLayout;
lay->addWidget(dbg);
lay->addWidget(t);
setLayout(lay);
connect(dbg, &QCheckBox::checkStateChanged, this, &EmailDetails::checkStateChanged);
resize(800, 600);
}
void EmailDetails::setMail(const Email &m) {
setWindowTitle(QString::fromStdString(m.title()));
t->setPlainText(QString::fromStdString(m.message()));
delete em;
em = new Email(m);
}
void EmailDetails::checkStateChanged(Qt::CheckState state) {
if(em) {
if (state == Qt::Checked) {
t->setPlainText(QString::fromStdString(em->raw()));
} else {
t->setPlainText(QString::fromStdString(em->message()));
}
}
}

View File

@ -1,5 +1,6 @@
#pragma once
#include <QCheckBox>
#include <QTextEdit>
#include <QVBoxLayout>
#include <QWidget>
@ -14,6 +15,12 @@ public:
void setMail(const Email &m);
public slots:
void checkStateChanged(Qt::CheckState state);
private:
Email *em;
QTextEdit *t;
QCheckBox *dbg;
};

View File

@ -52,7 +52,7 @@ ParametersProvider::ParametersProvider(QWidget *parent)
portField->setText("993");
}
void ParametersProvider::keyRead(const QString &key, const QString &value) {
void ParametersProvider::keyRead(const QString &key, const QString &value) const {
if (key == Keychain::passKey)
passField->setText(value);
}

View File

@ -18,7 +18,7 @@ class ParametersProvider : public QDialog {
public:
struct settings {
std::string userS, passS, imapS;
int port;
int port = 0;
};
explicit ParametersProvider(QWidget *parent = nullptr);
@ -32,7 +32,7 @@ signals:
public slots:
// Keychain to save password
void keyRead(const QString &key, const QString &value);
void keyRead(const QString &key, const QString &value) const;
// When clicking OK
void start();