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_CXX_STANDARD 23)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG -fsanitize=address,undefined") 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") set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fsanitize=address,undefined")
@ -28,7 +30,7 @@ add_executable(emailQt main.cpp
KeychainClass.cpp KeychainClass.cpp
KeychainClass.hpp) KeychainClass.hpp)
target_link_libraries(emailQt PRIVATE Qt6::Core target_link_libraries(emailQt PRIVATE Qt6::Core
Qt6::Gui Qt6::Gui
Qt6::Widgets Qt6::Widgets
CURL::libcurl CURL::libcurl

View File

@ -15,7 +15,7 @@ void CurlHandler::configure(const ParametersProvider::settings &sett) {
url += "/INBOX?ALL"; url += "/INBOX?ALL";
setts = sett; setts = sett;
setupCurl(initialCurl, initialChunk, url); setupCurl(initialCurl.get(), initialChunk, url);
} }
std::vector<std::string> *CurlHandler::fetch() { std::vector<std::string> *CurlHandler::fetch() {
@ -47,18 +47,21 @@ std::vector<std::string> *CurlHandler::fetch() {
decodedMessages.resize(messagesId.size()); decodedMessages.resize(messagesId.size());
count = 0; 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++); v.emplace_back(&CurlHandler::query, this, std::ref(*i), count++);
return &decodedMessages; return &decodedMessages;
} }
void CurlHandler::query(std::string &c, size_t count) { 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; CURLcode localCode;
c.erase(std::remove(c.begin(), c.end(), '\r'), c.end()); c.erase(std::remove(c.begin(), c.end(), '\r'), c.end());
c.erase(std::remove(c.begin(), c.end(), '\n'), 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()); localCode = curl_easy_perform(localCurl.get());
if (localCode != CURLE_OK) { if (localCode != CURLE_OK) {
@ -68,26 +71,26 @@ void CurlHandler::query(std::string &c, size_t count) {
emit threadFinished(count, std::stoi(c)); emit threadFinished(count, std::stoi(c));
} }
void CurlHandler::setupCurl(std::shared_ptr<CURL> ptr, std::string &m, std::string const &ur) const { void CurlHandler::setupCurl(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, CURLOPT_USERNAME, setts.userS.c_str());
curl_easy_setopt(ptr.get(), CURLOPT_PASSWORD, setts.passS.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, CURLOPT_PORT, setts.port);
curl_easy_setopt(ptr.get(), CURLOPT_TIMEOUT, curlTimeoutSeconds); curl_easy_setopt(ptr, CURLOPT_TIMEOUT, curlTimeoutSeconds);
// The callback function will receive the string ref as its userdata // The callback function will receive the string ref as its userdata
// and therefore save the data there. // and therefore save the data there.
curl_easy_setopt(ptr.get(), CURLOPT_USE_SSL, (long) CURLUSESSL_ALL); curl_easy_setopt(ptr, CURLOPT_USE_SSL, (long) CURLUSESSL_ALL);
curl_easy_setopt(ptr.get(), CURLOPT_WRITEDATA, (void *) &m); curl_easy_setopt(ptr, CURLOPT_WRITEDATA, (void *) &m);
curl_easy_setopt(ptr.get(), CURLOPT_WRITEFUNCTION, cb); curl_easy_setopt(ptr, CURLOPT_WRITEFUNCTION, cb);
// Necessary on some servers // 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 #ifdef DEBUG
curl_easy_setopt(ptr.get(), CURLOPT_VERBOSE, 1L); curl_easy_setopt(ptr, CURLOPT_VERBOSE, 1L);
#else #else
curl_easy_setopt(ptr.get(), CURLOPT_VERBOSE, 0L); curl_easy_setopt(ptr.get(), CURLOPT_VERBOSE, 0L);
#endif #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 cb(char *data, size_t size, size_t numberOfMembers, void *userdata) {
size_t realSize = size * numberOfMembers; size_t realSize = size * numberOfMembers;
auto *mem = (std::string *) userdata; auto *mem = static_cast<std::string *> (userdata);
mem->append(data, realSize); mem->append(data, realSize);
return realSize; return realSize;
} }

View File

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

View File

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

View File

@ -16,13 +16,15 @@ public:
void setString(const std::string &str); void setString(const std::string &str);
[[nodiscard]] const std::string &title() const; [[nodiscard]] const std::string &title() const;
[[nodiscard]] const std::string &message() 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); void parseEmailBody(std::stringstream &ss, std::string &line);
private: private:
std::string titleS; std::string titleS;
std::string messageS; std::string messageS;
std::string rawMessageS;
size_t uid; size_t uid;
}; };

View File

@ -1,18 +1,34 @@
#include "EmailDetails.hpp" #include "EmailDetails.hpp"
EmailDetails::EmailDetails(QWidget *parent) EmailDetails::EmailDetails(QWidget *parent)
: QWidget(parent) { : QWidget(parent), em{} {
t = new QTextEdit; t = new QTextEdit;
dbg = new QCheckBox("View raw message");
auto *lay = new QVBoxLayout; auto *lay = new QVBoxLayout;
lay->addWidget(dbg);
lay->addWidget(t); lay->addWidget(t);
setLayout(lay); setLayout(lay);
connect(dbg, &QCheckBox::checkStateChanged, this, &EmailDetails::checkStateChanged);
resize(800, 600); resize(800, 600);
} }
void EmailDetails::setMail(const Email &m) { void EmailDetails::setMail(const Email &m) {
setWindowTitle(QString::fromStdString(m.title())); setWindowTitle(QString::fromStdString(m.title()));
t->setPlainText(QString::fromStdString(m.message())); 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 #pragma once
#include <QCheckBox>
#include <QTextEdit> #include <QTextEdit>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QWidget> #include <QWidget>
@ -14,6 +15,12 @@ public:
void setMail(const Email &m); void setMail(const Email &m);
public slots:
void checkStateChanged(Qt::CheckState state);
private: private:
Email *em;
QTextEdit *t; QTextEdit *t;
QCheckBox *dbg;
}; };

View File

@ -52,7 +52,7 @@ ParametersProvider::ParametersProvider(QWidget *parent)
portField->setText("993"); 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) if (key == Keychain::passKey)
passField->setText(value); passField->setText(value);
} }

View File

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