/*
* Copyright (C) 2014-2017 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "src/files.h"
#include "src/common.h"
#include "src/settings.h"
#include "src/io/filesystem.h"
#include "ios/src/url_opener.h"
#include "src/models/accountmodel.h"
#include "src/sqlite/file_db_container.h"
#include "src/sqlite/message_db_container.h"
#include "src/net/xml_layer.h"
#include "src/sqlite/dbs.h"
#ifndef Q_OS_WIN
#include "src/crypto/crypto.h"
#endif
/* TODO -- These MUST be removed. */
QStack> stackFileList;
QStack stackMessageDetail;
/*!
* @brief Creates email header and message body.
*
* @param[in,out] message String to append data to.
* @param[in] body Email body.
* @param[in] subj Subject text.
* @param[in] boundary Boundary to be used,
*/
static
void createEmailMessage(QString &message, const QString &body,
const QString &subj, const QString &boundary)
{
message.clear();
const QString newLine("\n"); /* "\r\n" ? */
/* Rudimentary header. */
message += "Subject: " + subj + newLine;
message += "MIME-Version: 1.0" + newLine;
message += "Content-Type: multipart/mixed;" + newLine +
" boundary=\"" + boundary + "\"" + newLine;
/* Body. */
message += newLine;
message += "--" + boundary + newLine;
message += "Content-Type: text/plain; charset=UTF-8" + newLine;
message += "Content-Transfer-Encoding: 8bit" + newLine;
message += newLine;
message += "-- " + newLine; /* Must contain the space. */
message += body + newLine;
}
/*!
* @brief Adds attachment into email.
*
* @param[in,out] message String to append data to.
* @param[in] attachName Attachment name.
* @param[in] base64 Base64-encoded attachment.
* @param[in] boundary Boundary to be used.
*/
static
void addAttachmentToEmailMessage(QString &message, const QString &attachName,
const QByteArray &base64, const QString &boundary)
{
const QString newLine("\n"); /* "\r\n" ? */
QMimeDatabase mimeDb;
QMimeType mimeType(
mimeDb.mimeTypeForData(QByteArray::fromBase64(base64)));
message += newLine;
message += "--" + boundary + newLine;
message += "Content-Type: " + mimeType.name() + "; charset=UTF-8;"
+ newLine + " name=\"" + attachName + "\"" + newLine;
message += "Content-Transfer-Encoding: base64" + newLine;
message += "Content-Disposition: attachment;" + newLine +
" filename=\"" + attachName + "\"" + newLine;
for (int i = 0; i < base64.size(); ++i) {
if ((i % 60) == 0) {
message += newLine;
}
message += base64.at(i);
}
message += newLine;
}
/*!
* @brief Adds last line into email.
*
* @param[in,out] message String to append data to.
* @param[in] boundary Boundary to be used.
*/
static
void finishEmailMessage(QString &message, const QString &boundary)
{
const QString newLine("\n"); /* "\r\n" ? */
message += newLine + "--" + boundary + "--" + newLine;
}
Files::Files(QObject *parent) : QObject(parent)
{
}
void Files::clearFileModel(void)
{
globFilesModel.clearAll();
}
/*!
* @brief Set attachment model content.
*
* @param[in,out] model Model to be set.
* @param[in] fileList Attachment list to be added into the model.
*/
static
void setZfoFilesToModel(FileListModel &model,
const QList &fileList)
{
model.clearAll();
foreach (const Files::File &file, fileList) {
model.appendFileEntry(FileListModel::Entry(-1, file.dmFileDescr,
file._dmFileSize, file._icon, file.dmEncodedContent));
}
}
void Files::deleteExpiredFilesFromDbs(int days)
{
qDebug("%s()", __func__);
QStringList msgIDList;
QStringList userNameList = AccountListModel::globAccounts.keys();
foreach (const QString &userName, userNameList) {
FileDb *fDb = NULL;
fDb = globFileDbsPtr->accessFileDb(globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (fDb == NULL) {
qDebug() << "ERROR: File database cannot open!" << userName;
return;
}
msgIDList = fDb->cleanFilesInDb(days);
if (msgIDList.isEmpty()) {
continue;
}
MessageDb *msgDb = NULL;
msgDb = globMessageDbsPtr->accessMessageDb(globSet.dbsLocation,
userName, AccountListModel::globAccounts[userName].storeToDisk());
if (msgDb == NULL) {
qDebug() << "ERROR: Message database cannot open!";
return;
}
msgDb->beginTransaction();
foreach (const QString &msgId, msgIDList) {
msgDb->setAttachmentDownloaded(msgId.toLongLong(),
false);
}
msgDb->commitTransaction();
}
}
void Files::openAttachmentFromDb(const QString &userName,
qint64 msgId, int fileId)
{
qDebug("%s()", __func__);
if (userName.isEmpty() || msgId <= 0 || fileId < 0) {
return;
}
FileDb *fDb = NULL;
fDb = globFileDbsPtr->accessFileDb(globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (fDb == NULL) {
qDebug() << "ERROR: File database cannot open!";
return;
}
FileDb::FileData file = fDb->getFileContentFromDb(fileId);
QString fileName = file.filename;
Q_ASSERT(!fileName.isEmpty());
if (fileName.isEmpty()) {
qDebug() << "ERROR: File name is empty!";
return;
}
openAttachment(fileName, file.content.toUtf8());
}
void Files::openAttachment(const QString &fileName, const QByteArray &base64Data)
{
Q_ASSERT(!fileName.isEmpty());
Q_ASSERT(!base64Data.isEmpty());
if (fileName.isEmpty() || base64Data.isEmpty()) {
qCritical() << "File name or its content is empty!";
return;
}
if (isZfoFile(fileName)) {
/* Don't open zfo files from here. */
Q_ASSERT(0);
qCritical() << "This should open ZFO files by itself.";
return;
}
QByteArray rawData(QByteArray::fromBase64(base64Data));
QString filePath(writeFileToTmpDir(fileName, TEMP_DIR_NAME, rawData));
if (!filePath.isEmpty()) {
qInfo() << "Creating temporary file" << filePath;
#if defined Q_OS_IOS
UrlOpener urlOpener;
urlOpener.openFile(filePath);
/*
* TODO - we may check exceptions form objective-C (openFile)
* and return as bool.
*/
#else /* !defined Q_OS_IOS */
if (!QDesktopServices::openUrl(QUrl::fromLocalFile(filePath))) {
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
msgBox.setWindowTitle(tr("Open attachment error"));
msgBox.setText(tr("There is no application to open this file format."));
msgBox.setInformativeText(tr("File: '%1'").arg(filePath));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.exec();
}
#endif /* defined Q_OS_IOS */
} else {
qCritical() << "Cannot create temporary file for" << fileName;
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
msgBox.setWindowTitle(tr("Open attachment error"));
msgBox.setText(tr("Cannot save selected file to disk for opening."));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.exec();
}
}
void Files::sendAttachmentsWithEmailFromDb(const QString &userName,
qint64 msgId)
{
qDebug("%s()", __func__);
if (userName.isEmpty() || msgId <= 0) {
return;
}
QString body;
QString subject;
QStringList fileList;
QString emailMessage;
const QString boundary("-----123456789asdfghj_" +
QDateTime::currentDateTimeUtc().toString(
"dd.MM.yyyy-HH:mm:ss.zzz"));
MessageDb *msgDb = NULL;
msgDb = globMessageDbsPtr->accessMessageDb(globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (msgDb == NULL) {
qDebug() << "ERROR: Message database cannot open!";
return;
}
if (!msgDb->getMessageDataForEmail(msgId, body, subject)) {
qDebug() << "ERROR: Message data mssing!";
return;
}
FileDb *fDb = NULL;
fDb = globFileDbsPtr->accessFileDb(globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (fDb == NULL) {
qDebug() << "ERROR: File database cannot open!";
return;
}
QList filelist;
filelist = fDb->getFilesFromDb(msgId);
if (filelist.isEmpty()) {
qDebug() << "ERROR: File list is empty!";
return;
}
createEmailMessage(emailMessage, body, subject, boundary);
deleteFilesFromDir(EMAIL_DIR_NAME);
QString fileName;
foreach (const FileDb::FileData &file, filelist) {
fileName = file.filename;
if (fileName.isEmpty()) {
qDebug() << "ERROR: File name is empty!";
return;
}
QByteArray data = QByteArray::fromBase64(file.content.toUtf8());
fileName = writeFileToEmailDir(fileName, msgId, data);
fileList.append(fileName);
addAttachmentToEmailMessage(emailMessage, file.filename,
file.content.toUtf8(), boundary);
qDebug() << fileName;
}
finishEmailMessage(emailMessage, boundary);
sendEmail(emailMessage, fileList, subject, body, msgId);
}
void Files::saveAttachmentsToDisk(const QString &userName, qint64 msgId)
{
qDebug("%s()", __func__);
QList filelist;
if (!userName.isEmpty()) {
FileDb *fDb = NULL;
fDb = globFileDbsPtr->accessFileDb(globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (fDb == NULL) {
qDebug() << "ERROR: File database cannot open!";
return;
}
filelist = fDb->getFilesFromDb(msgId);
if (filelist.isEmpty()) {
qDebug() << "ERROR: File list is empty!";
return;
}
}
QString path = getBasePathBasedOnPlatform();
#if defined Q_OS_IOS
/* There is only one location where files or data can store
* permanently and share with Desktop.
* See: https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html
*/
path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
#else
/* Another platform can select destination for attachment saving. */
path = QFileDialog::getExistingDirectory(0,
tr("Select directory"), path,
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
#endif
QString destPath;
if (userName.isEmpty()) {
for (int i = 0; i < globFilesModelZfo.rowCount(); ++i) {
QModelIndex index = globFilesModelZfo.index(i);
QByteArray data = QByteArray::fromBase64(
globFilesModelZfo.data(
index, FileListModel::ROLE_FILE_DATA).toByteArray());
destPath = writeFileToDir(path,
globFilesModelZfo.data(
index, FileListModel::ROLE_FILE_NAME).toString(),
msgId,
data);
}
} else {
foreach (const FileDb::FileData &file, filelist) {
QByteArray data = QByteArray::fromBase64(file.content.toUtf8());
destPath = writeFileToDir(path, file.filename, msgId, data);
}
}
QFileInfo fi(destPath);
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Attachment saving"));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
if (!destPath.isEmpty()) {
msgBox.setIcon(QMessageBox::Information);
msgBox.setText(tr("Attachments have been saved."));
msgBox.setInformativeText(tr("Path: '%1'").arg(fi.absolutePath()));
} else {
msgBox.setIcon(QMessageBox::Critical);
msgBox.setText(tr("Attachments have not been saved!"));
msgBox.setInformativeText(tr("Path: '%1'").arg(fi.absolutePath()));
}
msgBox.exec();
}
void Files::deleteFileDb(const QString &userName)
{
qDebug("%s()", __func__);
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Delete files: %1").arg(userName));
msgBox.setIcon(QMessageBox::Question);
msgBox.setText(tr("Do you want to clean up the file database "
"of account '%1'?").arg(userName));
msgBox.setInformativeText(tr("Note: All attachment files of messages "
"will be removed from the database."));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No);
if (msgBox.exec() == QMessageBox::No) {
return;
}
FileDb *fDb = NULL;
fDb = globFileDbsPtr->accessFileDb(globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (fDb == NULL) {
qDebug() << "ERROR: File database open error!";
return;
}
if (!globFileDbsPtr->deleteDb(fDb)) {
qDebug() << "ERROR: File database could not delete!";
return;
}
MessageDb *msgDb = NULL;
msgDb = globMessageDbsPtr->accessMessageDb(globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (msgDb == NULL) {
qDebug() << "ERROR: Message database cannot open!";
return;
}
if (!msgDb->setAttachmentsDownloaded(false)) {
qDebug() << "ERROR: Message data mssing!";
return;
}
}
void Files::vacuumFileDbs(void)
{
qDebug("%s()", __func__);
emit statusBarTextChanged(tr("Vacuum databases"), true);
QStringList userNameList = AccountListModel::globAccounts.keys();
foreach (const QString &userName, userNameList) {
FileDb *fDb = NULL;
fDb = globFileDbsPtr->accessFileDb(globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (fDb == NULL) {
qDebug() << "ERROR: File database cannot open!" << userName;
return;
}
fDb->vacuumFileDb();
}
emit statusBarTextChanged(tr("Operation Vacuum has finished"), false);
}
bool Files::deleteAttachmentsFromDb(const QString &userName, qint64 msgId)
{
qDebug("%s()", __func__);
FileDb *fDb = NULL;
fDb = globFileDbsPtr->accessFileDb(globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (fDb == NULL) {
qDebug() << "ERROR: File database cannot open!" << userName;
return false;
}
if (fDb->deleteFilesFromDb(msgId)) {
MessageDb *msgDb = NULL;
msgDb = globMessageDbsPtr->accessMessageDb(globSet.dbsLocation,
userName, AccountListModel::globAccounts[userName].storeToDisk());
if (msgDb == NULL) {
qDebug() << "ERROR: Message database cannot open!";
return false;
}
return msgDb->setAttachmentDownloaded(msgId, false);
}
return false;
}
bool Files::fileReadable(const QString &filePath)
{
if (filePath.isEmpty()) {
Q_ASSERT(0);
qCritical() << "Target ZFO path is empty!";
return false;
}
{
QFileInfo fileInfo(filePath);
if (!fileInfo.isFile() || !fileInfo.isReadable()) {
qCritical() << "Cannot open ZFO file from" << filePath;
return false;
}
}
return true;
}
bool Files::isZfoFile(const QString &fileName)
{
return QFileInfo(fileName).suffix().toLower() == QStringLiteral("zfo");
}
QByteArray Files::rawFileContent(const QString &filePath)
{
if (!fileReadable(filePath)) {
return QByteArray();
}
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly)) {
Q_ASSERT(0);
qCritical() << "Cannot open file" << filePath;
return QByteArray();
}
QByteArray rawData(file.readAll());
file.close();
return rawData;
}
QByteArray Files::base64ToRaw(const QByteArray &base64Data)
{
return QByteArray::fromBase64(base64Data);
}
QString Files::msgIdString(const QByteArray &rawZfoData)
{
QString msgId;
bool ret = parseXmlData(&msgId, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR,
Q_NULLPTR, getXmlFromCms(rawZfoData));
return ret ? msgId : QString();
}
QString Files::msgAnnotation(const QByteArray &rawZfoData)
{
QString annotation;
bool ret = parseXmlData(Q_NULLPTR, &annotation, Q_NULLPTR, Q_NULLPTR,
Q_NULLPTR, getXmlFromCms(rawZfoData));
return ret ? annotation : QString();
}
QString Files::msgDescriptionHtml(const QByteArray &rawZfoData)
{
QString htmlDescr;
bool ret = parseXmlData(Q_NULLPTR, Q_NULLPTR, &htmlDescr, Q_NULLPTR,
Q_NULLPTR, getXmlFromCms(rawZfoData));
return ret ? htmlDescr : QString();
}
QString Files::msgEmailBody(const QByteArray &rawZfoData)
{
QString emailBody;
bool ret = parseXmlData(Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR,
&emailBody, getXmlFromCms(rawZfoData));
return ret ? emailBody : QString();
}
bool Files::setAttachmentModel(FileListModel &attachModel,
const QByteArray &rawZfoData)
{
return parseXmlData(Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, &attachModel,
Q_NULLPTR, getXmlFromCms(rawZfoData));
}
bool Files::setAttachmentModel(FileListModel &attachModel,
const QString &userName, qint64 msgId)
{
qDebug("%s()", __func__);
FileDb *fDb = Q_NULLPTR;
fDb = globFileDbsPtr->accessFileDb(globSet.dbsLocation, userName,
AccountListModel::globAccounts[userName].storeToDisk());
if (fDb == Q_NULLPTR) {
qCritical() << "Cannot open file database!";
return false;
}
attachModel.clearAll();
fDb->getFileListFromDb(attachModel, msgId);
return true;
}
void Files::sendAttachmentEmailZfo(const QVariant &attachModelVariant,
const QString &msgIdStr, QString subject, QString body)
{
qDebug("%s()", __func__);
/* Obtain pointer to attachment model. */
const FileListModel *attachModel = Q_NULLPTR;
{
if (!attachModelVariant.canConvert()) {
return;
}
QObject *obj = qvariant_cast(attachModelVariant);
attachModel = qobject_cast(obj);
}
if (attachModel == Q_NULLPTR) {
Q_ASSERT(0);
return;
}
/* Obtain message identifier. */
bool ok = false;
qint64 msgId = msgIdStr.toLongLong(&ok);
if (!ok || (msgId < 0)) {
return;
}
QStringList fileList;
QString emailMessage;
QString boundary("-----123456789asdfghj_" +
QDateTime::currentDateTimeUtc().toString(
"dd.MM.yyyy-HH:mm:ss.zzz"));
createEmailMessage(emailMessage, body, subject, boundary);
deleteFilesFromDir(EMAIL_DIR_NAME);
QString filePath;
QByteArray data;
for (int row = 0; row < attachModel->rowCount(); ++row) {
QModelIndex idx(attachModel->index(row));
/*
* On Android the attachment must be saved and the explicitly
* add into the email message.
*/
QByteArray base64Data(attachModel->data(idx,
FileListModel::ROLE_FILE_DATA).toByteArray());
QByteArray rawData(QByteArray::fromBase64(base64Data));
QString attachName(attachModel->data(idx,
FileListModel::ROLE_FILE_NAME).toString());
QString filePath(
writeFileToEmailDir(attachName, msgId, rawData));
fileList.append(filePath);
addAttachmentToEmailMessage(emailMessage, attachName,
base64Data, boundary);
}
finishEmailMessage(emailMessage, boundary);
sendEmail(emailMessage, fileList, subject, body, msgId);
}
void Files::deleteTmpFileFromStorage(const QString &filePath)
{
#if defined Q_OS_IOS
QFile file(filePath);
file.remove();
#else
Q_UNUSED(filePath);
#endif /* defined Q_OS_IOS */
}
void Files::sendEmail(const QString &emailMessage, const QStringList &fileList,
const QString &subject, const QString &body, qint64 msgId)
{
Q_UNUSED(subject);
Q_UNUSED(body);
Q_UNUSED(emailMessage);
Q_UNUSED(msgId);
if (!fileList.isEmpty()) {
#if defined Q_OS_IOS
UrlOpener urlOpener;
urlOpener.createEmail(body, subject, fileList);
#elif defined Q_OS_ANDROID
QDesktopServices::openUrl(QUrl("mailto:?subject=" +
subject + "&body=" + body));
#elif defined Q_OS_WINRT
QDesktopServices::openUrl(QUrl("mailto:?subject=" +
subject + "&body=" + body));
#else
QString tmpEmailFile = writeFileToEmailDir(QString::number(msgId)
+ "_mail.eml", msgId, emailMessage.toUtf8());
QDesktopServices::openUrl(QUrl::fromLocalFile(tmpEmailFile));
#endif
/* TODO -- Handle openUrl() return value. */
} else {
qDebug() << "Tmp file save error";
}
}
QByteArray Files::getXmlFromCms(const QByteArray &rawData)
{
qDebug("%s()", __func__);
if (rawData.isEmpty()) {
Q_ASSERT(0);
qCritical() << "File content is empty!";
return QByteArray();
}
/* Decode CMS and obtain message XML data - uses OpenSSL. */
void *xmlContent = NULL;
size_t xmlContentLen = 0;
if (extract_cms_data(rawData.data(), rawData.length(), &xmlContent,
&xmlContentLen) != 0) {
return QByteArray();
}
if (xmlContentLen == 0) {
free(xmlContent); xmlContent = NULL;
return QByteArray();
}
QByteArray soap((char *)xmlContent, xmlContentLen);
free(xmlContent); xmlContent = NULL;
return soap;
}
QByteArray Files::decodeZfoFile(const QByteArray &base64ZfoData)
{
qDebug("%s()", __func__);
if (base64ZfoData.isEmpty()) {
Q_ASSERT(0);
qCritical() << "File content is empty.";
return QByteArray();
}
/* decode signature from base64 and obtain something CMS message */
return getXmlFromCms(QByteArray::fromBase64(base64ZfoData));
}
bool Files::parseXmlData(QString *idStr, QString *annotation,
QString *msgDescrHtml, FileListModel *attachModel, QString *emailBody,
QByteArray xmlData)
{
qDebug("%s()", __func__);
bool success = false;
if (xmlData.isEmpty()) {
Q_ASSERT(0);
qCritical() << "XML content is empty!";
return success;
}
xmlData.prepend(""
""
"");
xmlData.append("");
//qDebug() << xmlData;
QXmlStreamReader xml;
xml.addData(xmlData);
XmlLayer xmlLayer;
Messages::Message msg;
QList fileList;
while(!xml.atEnd() && !xml.hasError()) {
QXmlStreamReader::TokenType token = xml.readNext();
if (xml.error() != QXmlStreamReader::NoError) {
return success;
}
if (token == QXmlStreamReader::StartDocument) {
continue;
}
if (token == QXmlStreamReader::StartElement) {
if (xml.name() == "dmDm") {
success = xmlLayer.completeMessageParse(xml,
msg, fileList);
}
}
}
if (!success) {
return success;
}
QString html = divStart;
html += "" + QObject::tr("General") + "
";
html += strongInfoLine(QObject::tr("Subject"), msg.dmAnnotation);
QString size = QString::number(msg.dmAttachmentSize);
html += strongInfoLine(QObject::tr("Attachment size"),
(size == "0") ? "<1 KB" : "~" + size + " KB");
html += strongInfoLine(QObject::tr("Personal delivery"),
(msg.dmPersonalDelivery) ? QObject::tr("Yes") : QObject::tr("No"));
html += strongInfoLine(QObject::tr("Delivery by fiction"),
(msg.dmAllowSubstDelivery) ? QObject::tr("Yes") : QObject::tr("No"));
html += "" + QObject::tr("Sender") + "
";
html += strongInfoLine(QObject::tr("Databox ID"), msg.dbIDSender);
html += strongInfoLine(QObject::tr("Name"), msg.dmSender);
html += strongInfoLine(QObject::tr("Address"),msg.dmSenderAddress);
html += "" + QObject::tr("Recipient") + "
";
html += strongInfoLine(QObject::tr("Databox ID"), msg.dbIDRecipient);
html += strongInfoLine(QObject::tr("Name"), msg.dmRecipient);
html += strongInfoLine(QObject::tr("Address"),msg.dmRecipientAddress);
if (!msg.dmToHands.isEmpty()) {
html += strongInfoLine(QObject::tr("To hands"),
msg.dmToHands);
}
QString tmpHtml;
if (!msg.dmSenderIdent.isEmpty()) {
tmpHtml += strongInfoLine(QObject::tr("Our file mark"),
msg.dmSenderIdent);
}
if (!msg.dmSenderRefNumber.isEmpty()) {
tmpHtml += strongInfoLine(QObject::tr("Our reference number"),
msg.dmSenderRefNumber);
}
if (!msg.dmRecipientIdent.isEmpty()) {
tmpHtml += strongInfoLine(QObject::tr("Your file mark"),
msg.dmRecipientIdent);
}
if (!msg.dmRecipientRefNumber.isEmpty()) {
tmpHtml += strongInfoLine(QObject::tr("Your reference number"),
msg.dmRecipientRefNumber);
}
if (!msg.dmLegalTitleLaw.isEmpty()) {
tmpHtml += strongInfoLine(QObject::tr("Law"),
msg.dmLegalTitleLaw);
}
if (!msg.dmLegalTitleYear.isEmpty()) {
tmpHtml += strongInfoLine(QObject::tr("Year"),
msg.dmLegalTitleYear);
}
if (!msg.dmLegalTitleSect.isEmpty()) {
tmpHtml += strongInfoLine(QObject::tr("Section"),
msg.dmLegalTitleSect);
}
if (!msg.dmLegalTitlePar.isEmpty()) {
tmpHtml += strongInfoLine(QObject::tr("Paragraph"),
msg.dmLegalTitlePar);
}
if (!msg.dmLegalTitlePoint.isEmpty()) {
tmpHtml += strongInfoLine(QObject::tr("Letter"),
msg.dmLegalTitlePoint);
}
if (!tmpHtml.isEmpty()) {
html += "" + QObject::tr("Additional info") + "
";
html += tmpHtml;
}
html += "" + QObject::tr("Message state") + "
";
html += strongInfoLine(QObject::tr("Delivery time"),
dateTimeStrFromDbFormat(
dateTimeStrToUTCDbFormat(msg.dmDeliveryTime),
DATETIME_QML_FORMAT));
html += strongInfoLine(QObject::tr("Accetance time"),
dateTimeStrFromDbFormat(
dateTimeStrToUTCDbFormat(msg.dmAcceptanceTime),
DATETIME_QML_FORMAT));
html += strongInfoLine(QObject::tr("Status"),
QString::number(msg.dmMessageStatus));
html += divEnd;
// Create body for email
QString body = QObject::tr("ID") + ": ";
body += QString::number(msg.dmID) + "\n";
body += QObject::tr("FROM") + ": ";
body += msg.dmSender + "\n";
body += QObject::tr("TO") + ": ";
body += msg.dmRecipient + "\n";
body += QObject::tr("DELIVERED") + ": ";
body += dateTimeStrFromDbFormat(dateTimeStrToUTCDbFormat(msg.dmAcceptanceTime), DATETIME_QML_FORMAT) + "\n\n---\n";
body += QObject::tr("This email has been generated with Datovka "
"application based on a data message (%1) delivered "
"to databox.").arg(msg.dmID);
body += "\n";
if (idStr != Q_NULLPTR) {
*idStr = QString::number(msg.dmID);
}
if (annotation != Q_NULLPTR) {
*annotation = msg.dmAnnotation;
}
if (msgDescrHtml != Q_NULLPTR) {
*msgDescrHtml = html;
}
if (attachModel != Q_NULLPTR) {
setZfoFilesToModel(*attachModel, fileList);
}
if (emailBody != Q_NULLPTR) {
*emailBody = body;
}
// remember file list and message detail
stackFileList.push(fileList);
stackMessageDetail.push(html);
return success;
}