Search full subdirectory for custom databases (#4137)

* Fix #2324 by allowing for iteration & symlinks

* Ensure alphabetical sorting
This commit is contained in:
Zach H 2020-11-22 20:06:25 -05:00 committed by GitHub
parent ca5f1dd434
commit 45d838a0b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 140 additions and 198 deletions

View file

@ -10,6 +10,7 @@
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
#include <QDirIterator>
#include <QFile> #include <QFile>
#include <QMessageBox> #include <QMessageBox>
#include <QRegularExpression> #include <QRegularExpression>
@ -534,11 +535,21 @@ LoadStatus CardDatabase::loadCardDatabases()
loadCardDatabase(SettingsCache::instance().getTokenDatabasePath()); // load tokens database loadCardDatabase(SettingsCache::instance().getTokenDatabasePath()); // load tokens database
loadCardDatabase(SettingsCache::instance().getSpoilerCardDatabasePath()); // load spoilers database loadCardDatabase(SettingsCache::instance().getSpoilerCardDatabasePath()); // load spoilers database
// load custom card databases // find all custom card databases, recursively & following symlinks
QDir dir(SettingsCache::instance().getCustomCardDatabasePath()); // then load them alphabetically
for (const QString &fileName : QDirIterator customDatabaseIterator(SettingsCache::instance().getCustomCardDatabasePath(), QStringList() << "*.xml",
dir.entryList(QStringList("*.xml"), QDir::Files | QDir::Readable, QDir::Name | QDir::IgnoreCase)) { QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
loadCardDatabase(dir.absoluteFilePath(fileName)); QStringList databasePaths;
while (customDatabaseIterator.hasNext()) {
customDatabaseIterator.next();
databasePaths.push_back(customDatabaseIterator.filePath());
}
databasePaths.sort();
for (auto i = 0; i < databasePaths.size(); ++i) {
const auto &databasePath = databasePaths.at(i);
qDebug() << "Loading Custom Set" << i << "(" << databasePath << ")";
loadCardDatabase(databasePath);
} }
// AFTER all the cards have been loaded // AFTER all the cards have been loaded

View file

@ -27,41 +27,41 @@
#include "qxtglobal.h" #include "qxtglobal.h"
#include <QStringList>
#include <QHash>
#include <QByteArray> #include <QByteArray>
#include <QHash>
#include <QIODevice>
#include <QMetaType> #include <QMetaType>
#include <QSharedDataPointer> #include <QSharedDataPointer>
#include <QIODevice> #include <QStringList>
struct QxtMailAttachmentPrivate; struct QxtMailAttachmentPrivate;
class QXT_NETWORK_EXPORT QxtMailAttachment class QXT_NETWORK_EXPORT QxtMailAttachment
{ {
public: public:
QxtMailAttachment(); QxtMailAttachment();
QxtMailAttachment(const QxtMailAttachment& other); QxtMailAttachment(const QxtMailAttachment &other);
QxtMailAttachment(const QByteArray& content, const QString& contentType = QString("application/octet-stream")); QxtMailAttachment(const QByteArray &content, const QString &contentType = QString("application/octet-stream"));
QxtMailAttachment(QIODevice* content, const QString& contentType = QString("application/octet-stream")); QxtMailAttachment(QIODevice *content, const QString &contentType = QString("application/octet-stream"));
QxtMailAttachment& operator=(const QxtMailAttachment& other); QxtMailAttachment &operator=(const QxtMailAttachment &other);
~QxtMailAttachment(); ~QxtMailAttachment();
static QxtMailAttachment fromFile(const QString& filename); static QxtMailAttachment fromFile(const QString &filename);
QIODevice* content() const; QIODevice *content() const;
void setContent(const QByteArray& content); void setContent(const QByteArray &content);
void setContent(QIODevice* content); void setContent(QIODevice *content);
bool deleteContent() const; bool deleteContent() const;
void setDeleteContent(bool enable); void setDeleteContent(bool enable);
QString contentType() const; QString contentType() const;
void setContentType(const QString& contentType); void setContentType(const QString &contentType);
QHash<QString, QString> extraHeaders() const; QHash<QString, QString> extraHeaders() const;
QByteArray extraHeader(const QString&) const; QByteArray extraHeader(const QString &) const;
bool hasExtraHeader(const QString&) const; bool hasExtraHeader(const QString &) const;
void setExtraHeader(const QString& key, const QString& value); void setExtraHeader(const QString &key, const QString &value);
void setExtraHeaders(const QHash<QString, QString>&); void setExtraHeaders(const QHash<QString, QString> &);
void removeExtraHeader(const QString& key); void removeExtraHeader(const QString &key);
QByteArray mimeData(); QByteArray mimeData();

View file

@ -23,7 +23,6 @@
** **
****************************************************************************/ ****************************************************************************/
/*! /*!
* \class QxtMailMessage * \class QxtMailMessage
* \inmodule QxtNetwork * \inmodule QxtNetwork
@ -31,22 +30,26 @@
* TODO: {implicitshared} * TODO: {implicitshared}
*/ */
#include "qxtmailmessage.h" #include "qxtmailmessage.h"
#include "qxtmail_p.h" #include "qxtmail_p.h"
#include <QDir>
#include <QTextCodec> #include <QTextCodec>
#include <QUuid> #include <QUuid>
#include <QDir>
#include <QtDebug> #include <QtDebug>
struct QxtMailMessagePrivate : public QSharedData struct QxtMailMessagePrivate : public QSharedData
{ {
QxtMailMessagePrivate() {} QxtMailMessagePrivate()
QxtMailMessagePrivate(const QxtMailMessagePrivate& other) {
: QSharedData(other), rcptTo(other.rcptTo), rcptCc(other.rcptCc), rcptBcc(other.rcptBcc), }
subject(other.subject), body(other.body), sender(other.sender), QxtMailMessagePrivate(const QxtMailMessagePrivate &other)
extraHeaders(other.extraHeaders), attachments(other.attachments) {} : QSharedData(other), rcptTo(other.rcptTo), rcptCc(other.rcptCc), rcptBcc(other.rcptBcc),
subject(other.subject), body(other.body), sender(other.sender), extraHeaders(other.extraHeaders),
attachments(other.attachments)
{
}
QStringList rcptTo, rcptCc, rcptBcc; QStringList rcptTo, rcptCc, rcptBcc;
QString subject, body, sender; QString subject, body, sender;
QHash<QString, QString> extraHeaders; QHash<QString, QString> extraHeaders;
@ -59,12 +62,12 @@ QxtMailMessage::QxtMailMessage()
qxt_d = new QxtMailMessagePrivate; qxt_d = new QxtMailMessagePrivate;
} }
QxtMailMessage::QxtMailMessage(const QxtMailMessage& other) : qxt_d(other.qxt_d) QxtMailMessage::QxtMailMessage(const QxtMailMessage &other) : qxt_d(other.qxt_d)
{ {
// trivial copy constructor // trivial copy constructor
} }
QxtMailMessage::QxtMailMessage(const QString& sender, const QString& recipient) QxtMailMessage::QxtMailMessage(const QString &sender, const QString &recipient)
{ {
qxt_d = new QxtMailMessagePrivate; qxt_d = new QxtMailMessagePrivate;
setSender(sender); setSender(sender);
@ -76,7 +79,7 @@ QxtMailMessage::~QxtMailMessage()
// trivial destructor // trivial destructor
} }
QxtMailMessage& QxtMailMessage::operator=(const QxtMailMessage & other) QxtMailMessage &QxtMailMessage::operator=(const QxtMailMessage &other)
{ {
qxt_d = other.qxt_d; qxt_d = other.qxt_d;
return *this; return *this;
@ -87,7 +90,7 @@ QString QxtMailMessage::sender() const
return qxt_d->sender; return qxt_d->sender;
} }
void QxtMailMessage::setSender(const QString& a) void QxtMailMessage::setSender(const QString &a)
{ {
qxt_d->sender = a; qxt_d->sender = a;
} }
@ -97,7 +100,7 @@ QString QxtMailMessage::subject() const
return qxt_d->subject; return qxt_d->subject;
} }
void QxtMailMessage::setSubject(const QString& a) void QxtMailMessage::setSubject(const QString &a)
{ {
qxt_d->subject = a; qxt_d->subject = a;
} }
@ -107,7 +110,7 @@ QString QxtMailMessage::body() const
return qxt_d->body; return qxt_d->body;
} }
void QxtMailMessage::setBody(const QString& a) void QxtMailMessage::setBody(const QString &a)
{ {
qxt_d->body = a; qxt_d->body = a;
} }
@ -121,7 +124,7 @@ QStringList QxtMailMessage::recipients(QxtMailMessage::RecipientType type) const
return qxt_d->rcptTo; return qxt_d->rcptTo;
} }
void QxtMailMessage::addRecipient(const QString& a, QxtMailMessage::RecipientType type) void QxtMailMessage::addRecipient(const QString &a, QxtMailMessage::RecipientType type)
{ {
if (type == Bcc) if (type == Bcc)
qxt_d->rcptBcc.append(a); qxt_d->rcptBcc.append(a);
@ -131,7 +134,7 @@ void QxtMailMessage::addRecipient(const QString& a, QxtMailMessage::RecipientTyp
qxt_d->rcptTo.append(a); qxt_d->rcptTo.append(a);
} }
void QxtMailMessage::removeRecipient(const QString& a) void QxtMailMessage::removeRecipient(const QString &a)
{ {
qxt_d->rcptTo.removeAll(a); qxt_d->rcptTo.removeAll(a);
qxt_d->rcptCc.removeAll(a); qxt_d->rcptCc.removeAll(a);
@ -143,32 +146,31 @@ QHash<QString, QString> QxtMailMessage::extraHeaders() const
return qxt_d->extraHeaders; return qxt_d->extraHeaders;
} }
QByteArray QxtMailMessage::extraHeader(const QString& key) const QByteArray QxtMailMessage::extraHeader(const QString &key) const
{ {
return qxt_d->extraHeaders[key.toLower()].toLatin1(); return qxt_d->extraHeaders[key.toLower()].toLatin1();
} }
bool QxtMailMessage::hasExtraHeader(const QString& key) const bool QxtMailMessage::hasExtraHeader(const QString &key) const
{ {
return qxt_d->extraHeaders.contains(key.toLower()); return qxt_d->extraHeaders.contains(key.toLower());
} }
void QxtMailMessage::setExtraHeader(const QString& key, const QString& value) void QxtMailMessage::setExtraHeader(const QString &key, const QString &value)
{ {
qxt_d->extraHeaders[key.toLower()] = value; qxt_d->extraHeaders[key.toLower()] = value;
} }
void QxtMailMessage::setExtraHeaders(const QHash<QString, QString>& a) void QxtMailMessage::setExtraHeaders(const QHash<QString, QString> &a)
{ {
QHash<QString, QString>& headers = qxt_d->extraHeaders; QHash<QString, QString> &headers = qxt_d->extraHeaders;
headers.clear(); headers.clear();
foreach(const QString& key, a.keys()) foreach (const QString &key, a.keys()) {
{
headers[key.toLower()] = a[key]; headers[key.toLower()] = a[key];
} }
} }
void QxtMailMessage::removeExtraHeader(const QString& key) void QxtMailMessage::removeExtraHeader(const QString &key)
{ {
qxt_d->extraHeaders.remove(key.toLower()); qxt_d->extraHeaders.remove(key.toLower());
} }
@ -178,46 +180,40 @@ QHash<QString, QxtMailAttachment> QxtMailMessage::attachments() const
return qxt_d->attachments; return qxt_d->attachments;
} }
QxtMailAttachment QxtMailMessage::attachment(const QString& filename) const QxtMailAttachment QxtMailMessage::attachment(const QString &filename) const
{ {
return qxt_d->attachments[filename]; return qxt_d->attachments[filename];
} }
void QxtMailMessage::addAttachment(const QString& filename, const QxtMailAttachment& attach) void QxtMailMessage::addAttachment(const QString &filename, const QxtMailAttachment &attach)
{ {
if (qxt_d->attachments.contains(filename)) if (qxt_d->attachments.contains(filename)) {
{
qWarning() << "QxtMailMessage::addAttachment: " << filename << " already in use"; qWarning() << "QxtMailMessage::addAttachment: " << filename << " already in use";
int i = 1; int i = 1;
while (qxt_d->attachments.contains(filename + "." + QString::number(i))) while (qxt_d->attachments.contains(filename + "." + QString::number(i))) {
{
i++; i++;
} }
qxt_d->attachments[filename+"."+QString::number(i)] = attach; qxt_d->attachments[filename + "." + QString::number(i)] = attach;
} } else {
else
{
qxt_d->attachments[filename] = attach; qxt_d->attachments[filename] = attach;
} }
} }
void QxtMailMessage::removeAttachment(const QString& filename) void QxtMailMessage::removeAttachment(const QString &filename)
{ {
qxt_d->attachments.remove(filename); qxt_d->attachments.remove(filename);
} }
QByteArray qxt_fold_mime_header(const QString& key, const QString& value, QTextCodec* latin1, const QByteArray& prefix) QByteArray qxt_fold_mime_header(const QString &key, const QString &value, QTextCodec *latin1, const QByteArray &prefix)
{ {
QByteArray rv = ""; QByteArray rv = "";
QByteArray line = key.toLatin1() + ": "; QByteArray line = key.toLatin1() + ": ";
if (!prefix.isEmpty()) line += prefix; if (!prefix.isEmpty())
if (!value.contains("=?") && latin1->canEncode(value)) line += prefix;
{ if (!value.contains("=?") && latin1->canEncode(value)) {
bool firstWord = true; bool firstWord = true;
foreach(const QByteArray& word, value.toLatin1().split(' ')) foreach (const QByteArray &word, value.toLatin1().split(' ')) {
{ if (line.size() > 78) {
if (line.size() > 78)
{
rv = rv + line + "\r\n"; rv = rv + line + "\r\n";
line.clear(); line.clear();
} }
@ -227,9 +223,7 @@ QByteArray qxt_fold_mime_header(const QString& key, const QString& value, QTextC
line += " " + word; line += " " + word;
firstWord = false; firstWord = false;
} }
} } else {
else
{
// The text cannot be losslessly encoded as Latin-1. Therefore, we // The text cannot be losslessly encoded as Latin-1. Therefore, we
// must use quoted-printable or base64 encoding. This is a quick // must use quoted-printable or base64 encoding. This is a quick
// heuristic based on the first 100 characters to see which // heuristic based on the first 100 characters to see which
@ -237,43 +231,33 @@ QByteArray qxt_fold_mime_header(const QString& key, const QString& value, QTextC
QByteArray utf8 = value.toUtf8(); QByteArray utf8 = value.toUtf8();
int ct = utf8.length(); int ct = utf8.length();
int nonAscii = 0; int nonAscii = 0;
for (int i = 0; i < ct && i < 100; i++) for (int i = 0; i < ct && i < 100; i++) {
{ if (QXT_MUST_QP(utf8[i]))
if (QXT_MUST_QP(utf8[i])) nonAscii++; nonAscii++;
} }
if (nonAscii > 20) if (nonAscii > 20) {
{
// more than 20%-ish non-ASCII characters: use base64 // more than 20%-ish non-ASCII characters: use base64
QByteArray base64 = utf8.toBase64(); QByteArray base64 = utf8.toBase64();
ct = base64.length(); ct = base64.length();
line += "=?utf-8?b?"; line += "=?utf-8?b?";
for (int i = 0; i < ct; i += 4) for (int i = 0; i < ct; i += 4) {
{ if (line.length() > 72) {
if (line.length() > 72)
{
rv += line + "?\r\n"; rv += line + "?\r\n";
line = " =?utf-8?b?"; line = " =?utf-8?b?";
} }
line = line + base64.mid(i, 4); line = line + base64.mid(i, 4);
} }
} } else {
else
{
// otherwise use Q-encoding // otherwise use Q-encoding
line += "=?utf-8?q?"; line += "=?utf-8?q?";
for (int i = 0; i < ct; i++) for (int i = 0; i < ct; i++) {
{ if (line.length() > 73) {
if (line.length() > 73)
{
rv += line + "?\r\n"; rv += line + "?\r\n";
line = " =?utf-8?q?"; line = " =?utf-8?q?";
} }
if (QXT_MUST_QP(utf8[i]) || utf8[i] == ' ') if (QXT_MUST_QP(utf8[i]) || utf8[i] == ' ') {
{
line += "=" + utf8.mid(i, 1).toHex().toUpper(); line += "=" + utf8.mid(i, 1).toHex().toUpper();
} } else {
else
{
line += utf8[i]; line += utf8[i];
} }
} }
@ -290,81 +274,67 @@ QByteArray QxtMailMessage::rfc2822() const
// Use base64 if requested // Use base64 if requested
bool useBase64 = (extraHeader("Content-Transfer-Encoding").toLower() == "base64"); bool useBase64 = (extraHeader("Content-Transfer-Encoding").toLower() == "base64");
// Check to see if plain text is ASCII-clean; assume it isn't if QP or base64 was requested // Check to see if plain text is ASCII-clean; assume it isn't if QP or base64 was requested
QTextCodec* latin1 = QTextCodec::codecForName("latin1"); QTextCodec *latin1 = QTextCodec::codecForName("latin1");
bool bodyIsAscii = latin1->canEncode(body()) && !useQuotedPrintable && !useBase64; bool bodyIsAscii = latin1->canEncode(body()) && !useQuotedPrintable && !useBase64;
QHash<QString, QxtMailAttachment> attach = attachments(); QHash<QString, QxtMailAttachment> attach = attachments();
QByteArray rv; QByteArray rv;
if (!sender().isEmpty() && !hasExtraHeader("From")) if (!sender().isEmpty() && !hasExtraHeader("From")) {
{
rv += qxt_fold_mime_header("From", sender(), latin1); rv += qxt_fold_mime_header("From", sender(), latin1);
} }
if (!qxt_d->rcptTo.isEmpty()) if (!qxt_d->rcptTo.isEmpty()) {
{
rv += qxt_fold_mime_header("To", qxt_d->rcptTo.join(", "), latin1); rv += qxt_fold_mime_header("To", qxt_d->rcptTo.join(", "), latin1);
} }
if (!qxt_d->rcptCc.isEmpty()) if (!qxt_d->rcptCc.isEmpty()) {
{
rv += qxt_fold_mime_header("Cc", qxt_d->rcptCc.join(", "), latin1); rv += qxt_fold_mime_header("Cc", qxt_d->rcptCc.join(", "), latin1);
} }
if (!subject().isEmpty()) if (!subject().isEmpty()) {
{
rv += qxt_fold_mime_header("Subject", subject(), latin1); rv += qxt_fold_mime_header("Subject", subject(), latin1);
} }
if (!bodyIsAscii) if (!bodyIsAscii) {
{
if (!hasExtraHeader("MIME-Version") && !attach.count()) if (!hasExtraHeader("MIME-Version") && !attach.count())
rv += "MIME-Version: 1.0\r\n"; rv += "MIME-Version: 1.0\r\n";
// If no transfer encoding has been requested, guess. // If no transfer encoding has been requested, guess.
// Heuristic: If >20% of the first 100 characters aren't // Heuristic: If >20% of the first 100 characters aren't
// 7-bit clean, use base64, otherwise use Q-P. // 7-bit clean, use base64, otherwise use Q-P.
if(!bodyIsAscii && !useQuotedPrintable && !useBase64) if (!bodyIsAscii && !useQuotedPrintable && !useBase64) {
{
QString b = body(); QString b = body();
int nonAscii = 0; int nonAscii = 0;
int ct = b.length(); int ct = b.length();
for (int i = 0; i < ct && i < 100; i++) for (int i = 0; i < ct && i < 100; i++) {
{ if (QXT_MUST_QP(b[i]))
if (QXT_MUST_QP(b[i])) nonAscii++; nonAscii++;
} }
useQuotedPrintable = !(nonAscii > 20); useQuotedPrintable = !(nonAscii > 20);
useBase64 = !useQuotedPrintable; useBase64 = !useQuotedPrintable;
} }
} }
if (attach.count()) if (attach.count()) {
{
if (qxt_d->boundary.isEmpty()) if (qxt_d->boundary.isEmpty())
qxt_d->boundary = QUuid::createUuid().toString().toLatin1().replace("{", "").replace("}", ""); qxt_d->boundary = QUuid::createUuid().toString().toLatin1().replace("{", "").replace("}", "");
if (!hasExtraHeader("MIME-Version")) if (!hasExtraHeader("MIME-Version"))
rv += "MIME-Version: 1.0\r\n"; rv += "MIME-Version: 1.0\r\n";
if (!hasExtraHeader("Content-Type")) if (!hasExtraHeader("Content-Type"))
rv += "Content-Type: multipart/mixed; boundary=" + qxt_d->boundary + "\r\n"; rv += "Content-Type: multipart/mixed; boundary=" + qxt_d->boundary + "\r\n";
} } else if (!bodyIsAscii && !hasExtraHeader("Content-Transfer-Encoding")) {
else if (!bodyIsAscii && !hasExtraHeader("Content-Transfer-Encoding")) if (!useQuotedPrintable) {
{
if (!useQuotedPrintable)
{
// base64 // base64
rv += "Content-Transfer-Encoding: base64\r\n"; rv += "Content-Transfer-Encoding: base64\r\n";
} } else {
else
{
// quoted-printable // quoted-printable
rv += "Content-Transfer-Encoding: quoted-printable\r\n"; rv += "Content-Transfer-Encoding: quoted-printable\r\n";
} }
} }
foreach(const QString& r, qxt_d->extraHeaders.keys()) foreach (const QString &r, qxt_d->extraHeaders.keys()) {
{ if ((r.toLower() == "content-type" || r.toLower() == "content-transfer-encoding") && attach.count()) {
if ((r.toLower() == "content-type" || r.toLower() == "content-transfer-encoding") && attach.count())
{
// Since we're in multipart mode, we'll be outputting this later // Since we're in multipart mode, we'll be outputting this later
continue; continue;
} }
@ -373,8 +343,7 @@ QByteArray QxtMailMessage::rfc2822() const
rv += "\r\n"; rv += "\r\n";
if (attach.count()) if (attach.count()) {
{
// we're going to have attachments, so output the lead-in for the message body // we're going to have attachments, so output the lead-in for the message body
rv += "This is a message with multiple parts in MIME format.\r\n"; rv += "This is a message with multiple parts in MIME format.\r\n";
rv += "--" + qxt_d->boundary + "\r\nContent-Type: "; rv += "--" + qxt_d->boundary + "\r\nContent-Type: ";
@ -382,19 +351,13 @@ QByteArray QxtMailMessage::rfc2822() const
rv += extraHeader("Content-Type") + "\r\n"; rv += extraHeader("Content-Type") + "\r\n";
else else
rv += "text/plain; charset=UTF-8\r\n"; rv += "text/plain; charset=UTF-8\r\n";
if (hasExtraHeader("Content-Transfer-Encoding")) if (hasExtraHeader("Content-Transfer-Encoding")) {
{
rv += "Content-Transfer-Encoding: " + extraHeader("Content-Transfer-Encoding") + "\r\n"; rv += "Content-Transfer-Encoding: " + extraHeader("Content-Transfer-Encoding") + "\r\n";
} } else if (!bodyIsAscii) {
else if (!bodyIsAscii) if (!useQuotedPrintable) {
{
if (!useQuotedPrintable)
{
// base64 // base64
rv += "Content-Transfer-Encoding: base64\r\n"; rv += "Content-Transfer-Encoding: base64\r\n";
} } else {
else
{
// quoted-printable // quoted-printable
rv += "Content-Transfer-Encoding: quoted-printable\r\n"; rv += "Content-Transfer-Encoding: quoted-printable\r\n";
} }
@ -402,132 +365,100 @@ QByteArray QxtMailMessage::rfc2822() const
rv += "\r\n"; rv += "\r\n";
} }
if (bodyIsAscii) if (bodyIsAscii) {
{
QByteArray b = latin1->fromUnicode(body()); QByteArray b = latin1->fromUnicode(body());
int len = b.length(); int len = b.length();
QByteArray line = ""; QByteArray line = "";
QByteArray word = ""; QByteArray word = "";
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++) {
{ if (b[i] == '\n' || b[i] == '\r') {
if (b[i] == '\n' || b[i] == '\r') if (line.isEmpty()) {
{
if (line.isEmpty())
{
line = word; line = word;
word = ""; word = "";
} } else if (line.length() + word.length() + 1 <= 78) {
else if (line.length() + word.length() + 1 <= 78)
{
line = line + ' ' + word; line = line + ' ' + word;
word = ""; word = "";
} }
if(line[0] == '.') if (line[0] == '.')
rv += "."; rv += ".";
rv += line + "\r\n"; rv += line + "\r\n";
if ((b[i+1] == '\n' || b[i+1] == '\r') && b[i] != b[i+1]) if ((b[i + 1] == '\n' || b[i + 1] == '\r') && b[i] != b[i + 1]) {
{
// If we're looking at a CRLF pair, skip the second half // If we're looking at a CRLF pair, skip the second half
i++; i++;
} }
line = word; line = word;
} } else if (b[i] == ' ') {
else if (b[i] == ' ') if (line.length() + word.length() + 1 > 78) {
{ if (line[0] == '.')
if (line.length() + word.length() + 1 > 78)
{
if(line[0] == '.')
rv += "."; rv += ".";
rv += line + "\r\n"; rv += line + "\r\n";
line = word; line = word;
} } else if (line.isEmpty()) {
else if (line.isEmpty())
{
line = word; line = word;
} } else {
else
{
line = line + ' ' + word; line = line + ' ' + word;
} }
word = ""; word = "";
} } else {
else
{
word += b[i]; word += b[i];
} }
} }
if (line.length() + word.length() + 1 > 78) if (line.length() + word.length() + 1 > 78) {
{ if (line[0] == '.')
if(line[0] == '.')
rv += "."; rv += ".";
rv += line + "\r\n"; rv += line + "\r\n";
line = word; line = word;
} } else if (!word.isEmpty()) {
else if (!word.isEmpty())
{
line += ' ' + word; line += ' ' + word;
} }
if(!line.isEmpty()) { if (!line.isEmpty()) {
if(line[0] == '.') if (line[0] == '.')
rv += "."; rv += ".";
rv += line + "\r\n"; rv += line + "\r\n";
} }
} } else if (useQuotedPrintable) {
else if (useQuotedPrintable)
{
QByteArray b = body().toUtf8(); QByteArray b = body().toUtf8();
int ct = b.length(); int ct = b.length();
QByteArray line; QByteArray line;
for (int i = 0; i < ct; i++) for (int i = 0; i < ct; i++) {
{ if (b[i] == '\n' || b[i] == '\r') {
if(b[i] == '\n' || b[i] == '\r') if (line[0] == '.')
{
if(line[0] == '.')
rv += "."; rv += ".";
rv += line + "\r\n"; rv += line + "\r\n";
line = ""; line = "";
if ((b[i+1] == '\n' || b[i+1] == '\r') && b[i] != b[i+1]) if ((b[i + 1] == '\n' || b[i + 1] == '\r') && b[i] != b[i + 1]) {
{
// If we're looking at a CRLF pair, skip the second half // If we're looking at a CRLF pair, skip the second half
i++; i++;
} }
} } else if (line.length() > 74) {
else if (line.length() > 74)
{
rv += line + "=\r\n"; rv += line + "=\r\n";
line = ""; line = "";
} }
if (QXT_MUST_QP(b[i])) if (QXT_MUST_QP(b[i])) {
{
line += "=" + b.mid(i, 1).toHex().toUpper(); line += "=" + b.mid(i, 1).toHex().toUpper();
} } else {
else
{
line += b[i]; line += b[i];
} }
} }
if(!line.isEmpty()) { if (!line.isEmpty()) {
if(line[0] == '.') if (line[0] == '.')
rv += "."; rv += ".";
rv += line + "\r\n"; rv += line + "\r\n";
} }
} } else /* base64 */
else /* base64 */
{ {
QByteArray b = body().toUtf8().toBase64(); QByteArray b = body().toUtf8().toBase64();
int ct = b.length(); int ct = b.length();
for (int i = 0; i < ct; i += 78) for (int i = 0; i < ct; i += 78) {
{
rv += b.mid(i, 78) + "\r\n"; rv += b.mid(i, 78) + "\r\n";
} }
} }
if (attach.count()) if (attach.count()) {
{ foreach (const QString &filename, attach.keys()) {
foreach(const QString& filename, attach.keys())
{
rv += "--" + qxt_d->boundary + "\r\n"; rv += "--" + qxt_d->boundary + "\r\n";
rv += qxt_fold_mime_header("Content-Disposition", QDir(filename).dirName(), latin1, "attachment; filename="); rv +=
qxt_fold_mime_header("Content-Disposition", QDir(filename).dirName(), latin1, "attachment; filename=");
rv += attach[filename].mimeData(); rv += attach[filename].mimeData();
} }
rv += "--" + qxt_d->boundary + "--\r\n"; rv += "--" + qxt_d->boundary + "--\r\n";