7 #include "templateparserjob.h"
8 #include "customtemplates_kfg.h"
9 #include "globalsettings_templateparser.h"
10 #include "templateparserextracthtmlinfo.h"
11 #include "templateparserjob_p.h"
12 #include "templatesconfiguration.h"
13 #include "templatesconfiguration_kfg.h"
14 #include "templatesutil.h"
15 #include "templatesutil_p.h"
17 #include <MessageCore/ImageCollector>
18 #include <MessageCore/StringUtil>
20 #include <MimeTreeParser/MessagePart>
21 #include <MimeTreeParser/ObjectTreeParser>
22 #include <MimeTreeParser/SimpleObjectTreeSource>
24 #include <KIdentityManagement/Identity>
25 #include <KIdentityManagement/IdentityManager>
27 #include "templateparser_debug.h"
28 #include <KLocalizedString>
29 #include <KMessageBox>
37 #include <QRegularExpression>
42 Q_DECL_CONSTEXPR
inline int pipeTimeout()
49 for (
const QString &name : charsets) {
60 qCWarning(TEMPLATEPARSER_LOG) <<
"Could not get text codec for charset" <<
name;
65 if (name ==
QLatin1String(
"us-ascii") && !KMime::isUsAscii(text)) {
68 qCDebug(TEMPLATEPARSER_LOG) <<
"Chosen charset" <<
name << codec->
name();
73 qCDebug(TEMPLATEPARSER_LOG) <<
"No appropriate charset found.";
79 using namespace TemplateParser;
81 TemplateParserJobPrivate::TemplateParserJobPrivate(
const KMime::Message::Ptr &amsg,
const TemplateParserJob::Mode amode)
86 mEmptySource->setDecryptMessage(mAllowDecryption);
89 mOtp->setAllowAsync(
false);
92 TemplateParserJobPrivate::~TemplateParserJobPrivate()
98 void TemplateParserJobPrivate::setAllowDecryption(
const bool allowDecryption)
100 mAllowDecryption = allowDecryption;
101 mEmptySource->setDecryptMessage(mAllowDecryption);
106 , d(new TemplateParserJobPrivate(amsg, amode))
110 TemplateParserJob::~TemplateParserJob() =
default;
114 d->mSelection = selection;
119 d->setAllowDecryption(allowDecryption);
122 bool TemplateParserJob::shouldStripSignature()
const
125 return (d->mMode == Reply || d->mMode == ReplyAll) && TemplateParserSettings::self()->stripSignature();
130 d->m_identityManager = ident;
135 d->mCharsets = charsets;
140 int pos = prefix.
length();
142 const int str_len = str.
length();
153 while (pos < str_len) {
154 const QChar c = str[pos];
159 if (!prev.isNull()) {
165 }
else if (quoteChars.
contains(c)) {
178 if (aorig_msg ==
nullptr) {
179 qCDebug(TEMPLATEPARSER_LOG) <<
"aorig_msg == 0!";
180 Q_EMIT parsingDone(d->mForceCursorPosition);
185 d->mOrigMsg = aorig_msg;
186 d->mFolder = afolder;
187 const QString tmpl = findTemplate();
189 Q_EMIT parsingDone(d->mForceCursorPosition);
193 processWithTemplate(tmpl);
198 d->mForceCursorPosition =
false;
199 d->mOrigMsg = aorig_msg;
200 d->mFolder = afolder;
201 const QString tmpl = findCustomTemplate(tmplName);
202 processWithTemplate(tmpl);
205 void TemplateParserJob::processWithIdentity(uint uoid,
const KMime::Message::Ptr &aorig_msg, qint64 afolder)
208 process(aorig_msg, afolder);
213 const auto subParts = messageTree->subParts();
214 for (
const auto &mp : subParts) {
217 if (text && !attach) {
219 const auto mpSubParts{mp->subParts()};
220 for (
const auto &sub : mpSubParts) {
221 if (!sub->text().trimmed().isEmpty()) {
231 auto ret = toplevelTextNode(mp);
240 void TemplateParserJob::processWithTemplate(
const QString &tmpl)
242 d->mOtp->parseObjectTree(d->mOrigMsg.data());
244 const auto mp = toplevelTextNode(d->mOtp->parsedPart());
246 qCWarning(TEMPLATEPARSER_LOG) <<
"Invalid message! mp is null ";
251 QString plainText = mp->plaintextContent();
255 htmlElement = d->mOtp->htmlContent();
257 plainText = htmlElement;
262 htmlElement = QStringLiteral(
"<html><head></head><body>%1</body></html>\n").
arg(htmlReplace);
265 auto job =
new TemplateParserExtractHtmlInfo(
this);
266 connect(job, &TemplateParserExtractHtmlInfo::finished,
this, &TemplateParserJob::slotExtractInfoDone);
268 job->setHtmlForExtractingTextPlain(plainText);
269 job->setTemplate(tmpl);
271 job->setHtmlForExtractionHeaderAndBody(htmlElement);
275 void TemplateParserJob::setReplyAsHtml(
bool replyAsHtml)
277 d->mReplyAsHtml = replyAsHtml;
280 void TemplateParserJob::slotExtractInfoDone(
const TemplateParserExtractHtmlInfoResult &result)
282 d->mExtractHtmlInfoResult = result;
283 const QString tmpl = d->mExtractHtmlInfoResult.mTemplate;
284 const int tmpl_len = tmpl.
length();
289 auto definedLocale =
QLocale();
290 for (
int i = 0; i < tmpl_len; ++i) {
298 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: -";
303 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: REM=";
305 const int len = parseQuotes(QStringLiteral(
"REM="), cmd, q);
309 const int len = parseQuotes(QStringLiteral(
"LANGUAGE="), cmd, q);
316 const int len = parseQuotes(QStringLiteral(
"DICTIONARYLANGUAGE="), cmd, q);
320 header->fromUnicodeString(q,
"utf-8");
321 d->mMsg->setHeader(header);
328 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: INSERT=";
329 len = parseQuotes(QStringLiteral(
"INSERT="), cmd, q);
332 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: PUT=";
333 len = parseQuotes(QStringLiteral(
"PUT="), cmd, q);
338 if (finfo.isRelative()) {
346 const QString body = plainTextToHtml(str);
348 }
else if (d->mDebug) {
349 KMessageBox::error(
nullptr,
i18nc(
"@info",
"Cannot insert content from file %1: %2", path, file.errorString()));
353 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: SYSTEM=";
355 const int len = parseQuotes(QStringLiteral(
"SYSTEM="), cmd, q);
360 const QString body = plainTextToHtml(str);
364 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: QUOTEPIPE=";
366 const int len = parseQuotes(QStringLiteral(
"QUOTEPIPE="), cmd, q);
370 const QString plainStr = pipe(pipe_cmd, plainMessageText(shouldStripSignature(), NoSelectionAllowed));
371 QString plainQuote = quotedPlainText(plainStr);
375 plainBody.
append(plainQuote);
377 const QString htmlStr = pipe(pipe_cmd, htmlMessageText(shouldStripSignature(), NoSelectionAllowed));
378 const QString htmlQuote = quotedHtmlText(htmlStr);
379 htmlBody.
append(htmlQuote);
382 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: QUOTE";
383 i += strlen(
"QUOTE");
385 QString plainQuote = quotedPlainText(plainMessageText(shouldStripSignature(), SelectionAllowed));
389 plainBody.
append(plainQuote);
391 const QString htmlQuote = quotedHtmlText(htmlMessageText(shouldStripSignature(), SelectionAllowed));
392 htmlBody.
append(htmlQuote);
395 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FORCEDPLAIN";
396 d->mQuotes = ReplyAsPlain;
397 i += strlen(
"FORCEDPLAIN");
399 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FORCEDHTML";
400 d->mQuotes = ReplyAsHtml;
401 i += strlen(
"FORCEDHTML");
403 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: QHEADERS";
404 i += strlen(
"QHEADERS");
407 QString plainQuote = quotedPlainText(headerStr);
411 plainBody.
append(plainQuote);
413 const QString htmlQuote = quotedHtmlText(headerStr);
414 const QString str = plainTextToHtml(htmlQuote);
418 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: HEADERS";
419 i += strlen(
"HEADERS");
423 const QString body = plainTextToHtml(str);
428 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TEXTPIPE=";
430 const int len = parseQuotes(QStringLiteral(
"TEXTPIPE="), cmd, q);
434 const QString plainStr = pipe(pipe_cmd, plainMessageText(shouldStripSignature(), NoSelectionAllowed));
435 plainBody.
append(plainStr);
437 const QString htmlStr = pipe(pipe_cmd, htmlMessageText(shouldStripSignature(), NoSelectionAllowed));
442 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: MSGPIPE=";
444 const int len = parseQuotes(QStringLiteral(
"MSGPIPE="), cmd, q);
450 const QString body = plainTextToHtml(str);
455 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: BODYPIPE=";
457 const int len = parseQuotes(QStringLiteral(
"BODYPIPE="), cmd, q);
460 const QString plainStr = pipe(q, plainBody);
461 plainBody.
append(plainStr);
463 const QString htmlStr = pipe(pipe_cmd, htmlBody);
464 const QString body = plainTextToHtml(htmlStr);
469 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CLEARPIPE=";
471 const int len = parseQuotes(QStringLiteral(
"CLEARPIPE="), cmd, q);
474 const QString plainStr = pipe(pipe_cmd, plainBody);
475 plainBody = plainStr;
477 const QString htmlStr = pipe(pipe_cmd, htmlBody);
482 d->mMsg->setHeader(header);
484 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TEXT";
487 const QString plainStr = plainMessageText(shouldStripSignature(), NoSelectionAllowed);
488 plainBody.
append(plainStr);
490 const QString htmlStr = htmlMessageText(shouldStripSignature(), NoSelectionAllowed);
494 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTEXTSIZE";
495 i += strlen(
"OTEXTSIZE");
497 const QString str = QStringLiteral(
"%1").
arg(d->mOrigMsg->body().length());
499 const QString body = plainTextToHtml(str);
503 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTEXT";
504 i += strlen(
"OTEXT");
506 const QString plainStr = plainMessageText(shouldStripSignature(), NoSelectionAllowed);
507 plainBody.
append(plainStr);
509 const QString htmlStr = htmlMessageText(shouldStripSignature(), NoSelectionAllowed);
513 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OADDRESSEESADDR";
514 i += strlen(
"OADDRESSEESADDR");
516 const QString to = d->mOrigMsg->to()->asUnicodeString();
517 const QString cc = d->mOrigMsg->cc()->asUnicodeString();
521 const QString body = plainTextToHtml(toLine);
532 const QString str = plainTextToHtml(ccLine);
537 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCADDR";
538 i += strlen(
"CCADDR");
539 const QString str = d->mMsg->cc()->asUnicodeString();
541 const QString body = plainTextToHtml(str);
544 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCNAME";
545 i += strlen(
"CCNAME");
546 const QString str = d->mMsg->cc()->displayString();
548 const QString body = plainTextToHtml(str);
551 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCFNAME";
552 i += strlen(
"CCFNAME");
553 const QString str = d->mMsg->cc()->displayString();
554 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
555 plainBody.
append(firstNameFromEmail);
556 const QString body = plainTextToHtml(firstNameFromEmail);
559 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCLNAME";
560 i += strlen(
"CCLNAME");
561 const QString str = d->mMsg->cc()->displayString();
562 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
563 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
566 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOADDR";
567 i += strlen(
"TOADDR");
568 const QString str = d->mMsg->to()->asUnicodeString();
570 const QString body = plainTextToHtml(str);
573 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TONAME";
574 i += strlen(
"TONAME");
575 const QString str = (d->mMsg->to()->displayString());
577 const QString body = plainTextToHtml(str);
580 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOFNAME";
581 i += strlen(
"TOFNAME");
582 const QString str = d->mMsg->to()->displayString();
583 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
584 plainBody.
append(firstNameFromEmail);
585 const QString body = plainTextToHtml(firstNameFromEmail);
588 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOLNAME";
589 i += strlen(
"TOLNAME");
590 const QString str = d->mMsg->to()->displayString();
591 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
592 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
595 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOLIST";
596 i += strlen(
"TOLIST");
597 const QString str = d->mMsg->to()->asUnicodeString();
599 const QString body = plainTextToHtml(str);
602 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMADDR";
603 i += strlen(
"FROMADDR");
604 const QString str = d->mMsg->from()->asUnicodeString();
606 const QString body = plainTextToHtml(str);
609 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMNAME";
610 i += strlen(
"FROMNAME");
611 const QString str = d->mMsg->from()->displayString();
613 const QString body = plainTextToHtml(str);
616 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMFNAME";
617 i += strlen(
"FROMFNAME");
618 const QString str = d->mMsg->from()->displayString();
619 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
620 plainBody.
append(firstNameFromEmail);
621 const QString body = plainTextToHtml(firstNameFromEmail);
624 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMLNAME";
625 i += strlen(
"FROMLNAME");
626 const QString str = d->mMsg->from()->displayString();
627 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
628 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
632 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FULLSUBJ";
633 i += strlen(
"FULLSUBJ");
635 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FULLSUBJECT";
636 i += strlen(
"FULLSUBJECT");
638 const QString str = d->mMsg->subject()->asUnicodeString();
640 const QString body = plainTextToHtml(str);
643 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: MSGID";
644 i += strlen(
"MSGID");
645 const QString str = d->mMsg->messageID()->asUnicodeString();
647 const QString body = plainTextToHtml(str);
651 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OHEADER=";
653 const int len = parseQuotes(QStringLiteral(
"OHEADER="), cmd, q);
659 str = hrdMsgOrigin->asUnicodeString();
662 const QString body = plainTextToHtml(str);
667 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: HEADER=";
669 const int len = parseQuotes(QStringLiteral(
"HEADER="), cmd, q);
674 str = hrdMsgOrigin->asUnicodeString();
677 const QString body = plainTextToHtml(str);
681 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: HEADER(";
684 const int res = cmd.
indexOf(reg, 0, &match);
687 i += strlen(
"HEADER( ");
689 i +=
match.capturedLength(0);
693 str = hrdMsgOrigin->asUnicodeString();
696 const QString body = plainTextToHtml(str);
700 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCADDR";
701 i += strlen(
"OCCADDR");
703 const QString str = d->mOrigMsg->cc()->asUnicodeString();
705 const QString body = plainTextToHtml(str);
709 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCNAME";
710 i += strlen(
"OCCNAME");
712 const QString str = d->mOrigMsg->cc()->displayString();
714 const QString body = plainTextToHtml(str);
718 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCFNAME";
719 i += strlen(
"OCCFNAME");
721 const QString str = d->mOrigMsg->cc()->displayString();
722 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
723 plainBody.
append(firstNameFromEmail);
724 const QString body = plainTextToHtml(firstNameFromEmail);
728 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCLNAME";
729 i += strlen(
"OCCLNAME");
731 const QString str = d->mOrigMsg->cc()->displayString();
732 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
733 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
737 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOADDR";
738 i += strlen(
"OTOADDR");
740 const QString str = d->mOrigMsg->to()->asUnicodeString();
742 const QString body = plainTextToHtml(str);
746 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTONAME";
747 i += strlen(
"OTONAME");
749 const QString str = d->mOrigMsg->to()->displayString();
751 const QString body = plainTextToHtml(str);
755 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOFNAME";
756 i += strlen(
"OTOFNAME");
758 const QString str = d->mOrigMsg->to()->displayString();
759 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
760 plainBody.
append(firstNameFromEmail);
761 const QString body = plainTextToHtml(firstNameFromEmail);
765 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOLNAME";
766 i += strlen(
"OTOLNAME");
768 const QString str = d->mOrigMsg->to()->displayString();
769 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
770 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
774 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOLIST";
775 i += strlen(
"OTOLIST");
777 const QString str = d->mOrigMsg->to()->asUnicodeString();
779 const QString body = plainTextToHtml(str);
783 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTO";
786 const QString str = d->mOrigMsg->to()->asUnicodeString();
788 const QString body = plainTextToHtml(str);
792 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMADDR";
793 i += strlen(
"OFROMADDR");
795 const QString str = d->mOrigMsg->from()->asUnicodeString();
797 const QString body = plainTextToHtml(str);
801 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMNAME";
802 i += strlen(
"OFROMNAME");
804 const QString str = d->mOrigMsg->from()->displayString();
806 const QString body = plainTextToHtml(str);
810 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMFNAME";
811 i += strlen(
"OFROMFNAME");
813 const QString str = d->mOrigMsg->from()->displayString();
814 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
815 plainBody.
append(firstNameFromEmail);
816 const QString body = plainTextToHtml(firstNameFromEmail);
820 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMLNAME";
821 i += strlen(
"OFROMLNAME");
823 const QString str = d->mOrigMsg->from()->displayString();
824 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
825 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
830 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFULLSUBJECT";
831 i += strlen(
"OFULLSUBJECT");
833 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFULLSUBJ";
834 i += strlen(
"OFULLSUBJ");
837 const QString str = d->mOrigMsg->subject()->asUnicodeString();
839 const QString body = plainTextToHtml(str);
843 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OMSGID";
844 i += strlen(
"OMSGID");
846 const QString str = d->mOrigMsg->messageID()->asUnicodeString();
848 const QString body = plainTextToHtml(str);
852 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DATEEN";
853 i += strlen(
"DATEEN");
858 const QString body = plainTextToHtml(str);
861 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DATESHORT";
862 i += strlen(
"DATESHORT");
866 const QString body = plainTextToHtml(str);
869 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DATE";
874 const QString body = plainTextToHtml(str);
877 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DOW";
882 const QString body = plainTextToHtml(str);
885 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TIMELONGEN";
886 i += strlen(
"TIMELONGEN");
891 const QString body = plainTextToHtml(str);
894 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TIMELONG";
895 i += strlen(
"TIMELONG");
899 const QString body = plainTextToHtml(str);
902 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TIME";
907 const QString body = plainTextToHtml(str);
910 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODATEEN";
911 i += strlen(
"ODATEEN");
913 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
916 const QString body = plainTextToHtml(str);
920 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODATESHORT";
921 i += strlen(
"ODATESHORT");
923 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
926 const QString body = plainTextToHtml(str);
930 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODATE";
931 i += strlen(
"ODATE");
933 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
936 const QString body = plainTextToHtml(str);
940 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODOW";
943 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
946 const QString body = plainTextToHtml(str);
950 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTIMELONGEN";
951 i += strlen(
"OTIMELONGEN");
953 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
957 const QString body = plainTextToHtml(str);
961 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTIMELONG";
962 i += strlen(
"OTIMELONG");
964 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
967 const QString body = plainTextToHtml(str);
971 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTIME";
972 i += strlen(
"OTIME");
974 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
977 const QString body = plainTextToHtml(str);
982 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: BLANK";
983 i += strlen(
"BLANK");
986 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: NOP";
990 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CLEAR";
991 i += strlen(
"CLEAR");
996 d->mMsg->setHeader(header);
999 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DEBUGOFF";
1000 i += strlen(
"DEBUGOFF");
1004 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DEBUG";
1005 i += strlen(
"DEBUG");
1009 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CURSOR";
1011 i += strlen(
"CURSOR");
1020 if (oldI > 0 && tmpl[oldI - 1] ==
QLatin1Char(
'\n') && i == tmpl_len - 1) {
1023 d->mMsg->setHeader(header);
1024 d->mForceCursorPosition =
true;
1027 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: SIGNATURE";
1028 i += strlen(
"SIGNATURE");
1029 plainBody.
append(getPlainSignature());
1030 htmlBody.
append(getHtmlSignature());
1038 if ((tmpl.
size() > i + 1)
1049 if (tmpl.
size() > i + 1
1051 htmlBody.
append(tmpl[i + 1]);
1052 plainBody.
append(tmpl[i + 1]);
1063 const KMime::Content *content = d->mOrigMsg->mainBodyPart(
"text/html");
1064 if (d->mQuotes == ReplyAsPlain || (!d->mReplyAsHtml && TemplateParserSettings::self()->replyUsingVisualFormat())
1065 || !TemplateParserSettings::self()->replyUsingVisualFormat() || (!content || !content->
hasContent())) {
1069 makeValidHtml(htmlBody);
1071 if (d->mMode == NewMessage && plainBody.
isEmpty() && !d->mExtractHtmlInfoResult.mPlainText.isEmpty()) {
1072 plainBody = d->mExtractHtmlInfoResult.mPlainText;
1075 addProcessedBodyToMessage(plainBody, htmlBody);
1076 Q_EMIT parsingDone(d->mForceCursorPosition);
1080 QString TemplateParserJob::getPlainSignature()
const
1090 if (signature.
type() == KIdentityManagement::Signature::Inlined && signature.
isInlinedHtml()) {
1100 QString TemplateParserJob::getHtmlSignature()
const
1116 void TemplateParserJob::addProcessedBodyToMessage(
const QString &plainBody,
const QString &htmlBody)
const
1123 const auto parts = d->mMsg->contents();
1125 d->mMsg->removeContent(content,
true );
1129 if (!d->mTo.isEmpty()) {
1130 d->mMsg->to()->fromUnicodeString(d->mMsg->to()->asUnicodeString() +
QLatin1Char(
',') + d->mTo,
"utf-8");
1133 if (!d->mCC.isEmpty()) {
1134 d->mMsg->cc()->fromUnicodeString(d->mMsg->cc()->asUnicodeString() +
QLatin1Char(
',') + d->mCC,
"utf-8");
1137 d->mMsg->contentType()->clear();
1140 KMime::Content *
const mainTextPart = htmlBody.
isEmpty() ? createPlainPartContent(plainBody) : createMultipartAlternativeContent(plainBody, htmlBody);
1144 if (!ic.
images().empty()) {
1145 textPart = createMultipartRelated(ic, mainTextPart);
1152 if (d->mMode == Forward) {
1153 auto attachments = d->mOrigMsg->attachments();
1154 attachments += d->mOtp->nodeHelper()->attachmentsOfExtraContents();
1155 if (!attachments.isEmpty()) {
1156 mainPart = createMultipartMixed(attachments, textPart);
1164 d->mMsg->assemble();
1171 const QByteArray boundary = KMime::multiPartBoundary();
1172 auto contentType = mixedPart->contentType();
1173 contentType->setMimeType(
"multipart/mixed");
1174 contentType->setBoundary(boundary);
1175 mixedPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit);
1176 mixedPart->addContent(textPart);
1178 int attachmentNumber = 1;
1180 mixedPart->addContent(attachment);
1183 if (
auto ct = attachment->contentType(
false)) {
1184 if (!ct->hasParameter(QStringLiteral(
"name")) && !ct->hasParameter(QStringLiteral(
"filename"))) {
1185 ct->setParameter(QStringLiteral(
"name"),
i18nc(
"@item:intext",
"Attachment %1", attachmentNumber));
1196 const QByteArray boundary = KMime::multiPartBoundary();
1197 auto contentType = relatedPart->contentType();
1198 contentType->setMimeType(
"multipart/related");
1199 contentType->setBoundary(boundary);
1200 relatedPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit);
1201 relatedPart->addContent(mainTextPart);
1203 qCWarning(TEMPLATEPARSER_LOG) <<
"Adding" << image->contentID() <<
"as an embedded image";
1204 relatedPart->addContent(image);
1214 QTextCodec *charset = selectCharset(d->mCharsets, plainBody);
1215 ct->setCharset(charset->
name());
1224 multipartAlternative->contentType()->setMimeType(
"multipart/alternative");
1225 const QByteArray boundary = KMime::multiPartBoundary();
1226 multipartAlternative->contentType(
false)->setBoundary(boundary);
1229 multipartAlternative->addContent(textPart);
1232 htmlPart->contentType(
true)->setMimeType(
"text/html");
1233 QTextCodec *charset = selectCharset(d->mCharsets, htmlBody);
1234 htmlPart->contentType(
false)->setCharset(charset->
name());
1235 htmlPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit);
1236 htmlPart->fromUnicodeString(htmlBody);
1237 multipartAlternative->addContent(htmlPart);
1239 return multipartAlternative;
1242 QString TemplateParserJob::findCustomTemplate(
const QString &tmplName)
1244 CTemplates t(tmplName);
1251 return findTemplate();
1255 QString TemplateParserJob::findTemplate()
1261 qCDebug(TEMPLATEPARSER_LOG) <<
"Folder identify found:" << d->mFolder;
1262 if (d->mFolder >= 0) {
1264 Templates fconf(fid);
1265 if (fconf.useCustomTemplates()) {
1268 tmpl = fconf.templateNewMessage();
1271 tmpl = fconf.templateReply();
1274 tmpl = fconf.templateReplyAll();
1277 tmpl = fconf.templateForward();
1280 qCDebug(TEMPLATEPARSER_LOG) <<
"Unknown message mode:" << d->mMode;
1283 d->mQuoteString = fconf.quoteString();
1290 if (!d->mIdentity) {
1291 d->mIdentity = identityUoid(d->mMsg);
1292 if (!d->mIdentity && d->mOrigMsg) {
1293 d->mIdentity = identityUoid(d->mOrigMsg);
1295 d->mIdentity = d->m_identityManager->identityForUoidOrDefault(d->mIdentity).uoid();
1296 if (!d->mIdentity) {
1297 qCDebug(TEMPLATEPARSER_LOG) <<
"Oops! No identity for message";
1300 qCDebug(TEMPLATEPARSER_LOG) <<
"Identity found:" << d->mIdentity;
1306 iid = QStringLiteral(
"IDENTITY_NO_IDENTITY");
1309 Templates iconf(iid);
1310 if (iconf.useCustomTemplates()) {
1313 tmpl = iconf.templateNewMessage();
1316 tmpl = iconf.templateReply();
1319 tmpl = iconf.templateReplyAll();
1322 tmpl = iconf.templateForward();
1325 qCDebug(TEMPLATEPARSER_LOG) <<
"Unknown message mode:" << d->mMode;
1328 d->mQuoteString = iconf.quoteString();
1336 tmpl = TemplateParserSettings::self()->templateNewMessage();
1339 tmpl = TemplateParserSettings::self()->templateReply();
1342 tmpl = TemplateParserSettings::self()->templateReplyAll();
1345 tmpl = TemplateParserSettings::self()->templateForward();
1348 qCDebug(TEMPLATEPARSER_LOG) <<
"Unknown message mode:" << d->mMode;
1352 d->mQuoteString = TemplateParserSettings::self()->quoteString();
1365 bool finished =
false;
1393 if (!success && d->mDebug) {
1407 d->mColWrap = wrapColWidth;
1410 QString TemplateParserJob::plainMessageText(
bool aStripSignature, AllowSelection isSelectionAllowed)
const
1412 if (!d->mSelection.isEmpty() && (isSelectionAllowed == SelectionAllowed)) {
1413 return d->mSelection;
1419 const auto mp = toplevelTextNode(d->mOtp->parsedPart());
1420 QString result = mp->plaintextContent();
1422 result = d->mExtractHtmlInfoResult.mPlainText;
1424 if (aStripSignature) {
1431 QString TemplateParserJob::htmlMessageText(
bool aStripSignature, AllowSelection isSelectionAllowed)
1433 if (!d->mSelection.isEmpty() && (isSelectionAllowed == SelectionAllowed)) {
1435 return d->mSelection;
1437 d->mHeadElement = d->mExtractHtmlInfoResult.mHeaderElement;
1438 const QString bodyElement = d->mExtractHtmlInfoResult.mBodyElement;
1440 if (aStripSignature) {
1447 if (aStripSignature) {
1451 return d->mExtractHtmlInfoResult.mHtmlElement;
1454 QString TemplateParserJob::quotedPlainText(
const QString &selection)
const
1456 QString content = TemplateParser::Util::removeSpaceAtBegin(selection);
1459 if (TemplateParserSettings::self()->
smartQuote() && d->mWrap) {
1469 QString TemplateParserJob::quotedHtmlText(
const QString &selection)
const
1486 if (
auto hrd = msg->headerByType(
"X-KMail-Identity")) {
1487 idString = hrd->asUnicodeString().
trimmed();
1490 unsigned int id = idString.
toUInt(&ok);
1492 if (!ok ||
id == 0) {
1493 id = d->m_identityManager->identityForAddress(msg->to()->asUnicodeString() +
QLatin1String(
", ") + msg->cc()->asUnicodeString()).uoid();
1499 bool TemplateParserJob::isHtmlSignature()
const
1520 void TemplateParserJob::makeValidHtml(
QString &body)
1528 regEx.
setPattern(QStringLiteral(
"<html.*?>"));
1530 regEx.
setPattern(QStringLiteral(
"<body.*?>"));
1534 regEx.
setPattern(QStringLiteral(
"<head.*?>"));