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 <KIdentityManagementCore/Identity>
25#include <KIdentityManagementCore/IdentityManager>
27#include "templateparser_debug.h"
28#include <KLocalizedString>
37#include <QRegularExpression>
38#include <QStringDecoder>
42Q_DECL_CONSTEXPR
inline int pipeTimeout()
48using namespace TemplateParser;
50TemplateParserJobPrivate::TemplateParserJobPrivate(
const KMime::Message::Ptr &amsg,
const TemplateParserJob::Mode amode)
55 mEmptySource->setDecryptMessage(mAllowDecryption);
58 mOtp->setAllowAsync(
false);
61TemplateParserJobPrivate::~TemplateParserJobPrivate()
67void TemplateParserJobPrivate::setAllowDecryption(
const bool allowDecryption)
69 mAllowDecryption = allowDecryption;
70 mEmptySource->setDecryptMessage(mAllowDecryption);
75 , d(new TemplateParserJobPrivate(amsg, amode))
79TemplateParserJob::~TemplateParserJob() =
default;
83 d->mSelection = selection;
88 d->setAllowDecryption(allowDecryption);
91bool TemplateParserJob::shouldStripSignature()
const
94 return (d->mMode == Reply || d->mMode == ReplyAll) && TemplateParserSettings::self()->stripSignature();
99 d->m_identityManager = ident;
104 int pos = prefix.
length();
106 const int str_len = str.
length();
117 while (pos < str_len) {
118 const QChar c = str[pos];
123 if (!prev.isNull()) {
129 }
else if (quoteChars.
contains(c)) {
142 if (aorig_msg ==
nullptr) {
143 qCDebug(TEMPLATEPARSER_LOG) <<
"aorig_msg == 0!";
144 Q_EMIT parsingDone(d->mForceCursorPosition);
149 d->mOrigMsg = aorig_msg;
150 d->mFolder = afolder;
151 const QString tmpl = findTemplate();
153 Q_EMIT parsingDone(d->mForceCursorPosition);
157 processWithTemplate(tmpl);
162 d->mForceCursorPosition =
false;
163 d->mOrigMsg = aorig_msg;
164 d->mFolder = afolder;
165 const QString tmpl = findCustomTemplate(tmplName);
166 processWithTemplate(tmpl);
169void TemplateParserJob::processWithIdentity(uint uoid,
const KMime::Message::Ptr &aorig_msg, qint64 afolder)
172 process(aorig_msg, afolder);
177 const auto subParts = messageTree->subParts();
178 for (
const auto &mp : subParts) {
181 if (text && !attach) {
183 const auto mpSubParts{mp->subParts()};
184 for (
const auto &sub : mpSubParts) {
185 if (!sub->text().trimmed().isEmpty()) {
195 auto ret = toplevelTextNode(mp);
204void TemplateParserJob::processWithTemplate(
const QString &tmpl)
206 d->mOtp->parseObjectTree(d->mOrigMsg.data());
208 const auto mp = toplevelTextNode(d->mOtp->parsedPart());
210 qCWarning(TEMPLATEPARSER_LOG) <<
"Invalid message! mp is null ";
215 QString plainText = mp->plaintextContent();
219 htmlElement = d->mOtp->htmlContent();
221 plainText = htmlElement;
226 htmlElement = QStringLiteral(
"<html><head></head><body>%1</body></html>\n").
arg(htmlReplace);
229 auto job =
new TemplateParserExtractHtmlInfo(
this);
230 connect(job, &TemplateParserExtractHtmlInfo::finished,
this, &TemplateParserJob::slotExtractInfoDone);
232 job->setHtmlForExtractingTextPlain(plainText);
233 job->setTemplate(tmpl);
235 job->setHtmlForExtractionHeaderAndBody(htmlElement);
239void TemplateParserJob::setReplyAsHtml(
bool replyAsHtml)
241 d->mReplyAsHtml = replyAsHtml;
244void TemplateParserJob::slotExtractInfoDone(
const TemplateParserExtractHtmlInfoResult &result)
246 d->mExtractHtmlInfoResult = result;
247 const QString tmpl = d->mExtractHtmlInfoResult.mTemplate;
248 const int tmpl_len = tmpl.
length();
253 auto definedLocale =
QLocale();
254 for (
int i = 0; i < tmpl_len; ++i) {
262 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: -";
267 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: REM=";
269 const int len = parseQuotes(QStringLiteral(
"REM="), cmd, q);
273 const int len = parseQuotes(QStringLiteral(
"LANGUAGE="), cmd, q);
280 const int len = parseQuotes(QStringLiteral(
"DICTIONARYLANGUAGE="), cmd, q);
284 header->fromUnicodeString(q);
285 d->mMsg->setHeader(header);
292 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: INSERT=";
293 len = parseQuotes(QStringLiteral(
"INSERT="), cmd, q);
296 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: PUT=";
297 len = parseQuotes(QStringLiteral(
"PUT="), cmd, q);
302 if (finfo.isRelative()) {
310 const QString body = plainTextToHtml(str);
312 }
else if (d->mDebug) {
313 KMessageBox::error(
nullptr,
i18nc(
"@info",
"Cannot insert content from file %1: %2", path, file.errorString()));
317 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: SYSTEM=";
319 const int len = parseQuotes(QStringLiteral(
"SYSTEM="), cmd, q);
324 const QString body = plainTextToHtml(str);
328 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: QUOTEPIPE=";
330 const int len = parseQuotes(QStringLiteral(
"QUOTEPIPE="), cmd, q);
334 const QString plainStr = pipe(pipe_cmd, plainMessageText(shouldStripSignature(), NoSelectionAllowed));
335 QString plainQuote = quotedPlainText(plainStr);
339 plainBody.
append(plainQuote);
341 const QString htmlStr = pipe(pipe_cmd, htmlMessageText(shouldStripSignature(), NoSelectionAllowed));
342 const QString htmlQuote = quotedHtmlText(htmlStr);
343 htmlBody.
append(htmlQuote);
346 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: QUOTE";
347 i += strlen(
"QUOTE");
349 QString plainQuote = quotedPlainText(plainMessageText(shouldStripSignature(), SelectionAllowed));
353 plainBody.
append(plainQuote);
355 const QString htmlQuote = quotedHtmlText(htmlMessageText(shouldStripSignature(), SelectionAllowed));
356 htmlBody.
append(htmlQuote);
359 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FORCEDPLAIN";
360 d->mQuotes = ReplyAsPlain;
361 i += strlen(
"FORCEDPLAIN");
363 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FORCEDHTML";
364 d->mQuotes = ReplyAsHtml;
365 i += strlen(
"FORCEDHTML");
367 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: QHEADERS";
368 i += strlen(
"QHEADERS");
371 QString plainQuote = quotedPlainText(headerStr);
375 plainBody.
append(plainQuote);
377 const QString htmlQuote = quotedHtmlText(headerStr);
378 const QString str = plainTextToHtml(htmlQuote);
382 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: HEADERS";
383 i += strlen(
"HEADERS");
387 const QString body = plainTextToHtml(str);
392 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TEXTPIPE=";
394 const int len = parseQuotes(QStringLiteral(
"TEXTPIPE="), cmd, q);
398 const QString plainStr = pipe(pipe_cmd, plainMessageText(shouldStripSignature(), NoSelectionAllowed));
399 plainBody.
append(plainStr);
401 const QString htmlStr = pipe(pipe_cmd, htmlMessageText(shouldStripSignature(), NoSelectionAllowed));
406 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: MSGPIPE=";
408 const int len = parseQuotes(QStringLiteral(
"MSGPIPE="), cmd, q);
414 const QString body = plainTextToHtml(str);
419 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: BODYPIPE=";
421 const int len = parseQuotes(QStringLiteral(
"BODYPIPE="), cmd, q);
424 const QString plainStr = pipe(q, plainBody);
425 plainBody.
append(plainStr);
427 const QString htmlStr = pipe(pipe_cmd, htmlBody);
428 const QString body = plainTextToHtml(htmlStr);
433 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CLEARPIPE=";
435 const int len = parseQuotes(QStringLiteral(
"CLEARPIPE="), cmd, q);
438 const QString plainStr = pipe(pipe_cmd, plainBody);
439 plainBody = plainStr;
441 const QString htmlStr = pipe(pipe_cmd, htmlBody);
446 d->mMsg->setHeader(header);
448 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TEXT";
451 const QString plainStr = plainMessageText(shouldStripSignature(), NoSelectionAllowed);
452 plainBody.
append(plainStr);
454 const QString htmlStr = htmlMessageText(shouldStripSignature(), NoSelectionAllowed);
458 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTEXTSIZE";
459 i += strlen(
"OTEXTSIZE");
461 const QString str = QStringLiteral(
"%1").
arg(d->mOrigMsg->body().length());
463 const QString body = plainTextToHtml(str);
467 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTEXT";
468 i += strlen(
"OTEXT");
470 const QString plainStr = plainMessageText(shouldStripSignature(), NoSelectionAllowed);
471 plainBody.
append(plainStr);
473 const QString htmlStr = htmlMessageText(shouldStripSignature(), NoSelectionAllowed);
477 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OADDRESSEESADDR";
478 i += strlen(
"OADDRESSEESADDR");
480 const QString to = d->mOrigMsg->to()->asUnicodeString();
481 const QString cc = d->mOrigMsg->cc()->asUnicodeString();
485 const QString body = plainTextToHtml(toLine);
496 const QString str = plainTextToHtml(ccLine);
501 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCADDR";
502 i += strlen(
"CCADDR");
503 const QString str = d->mMsg->cc()->asUnicodeString();
505 const QString body = plainTextToHtml(str);
508 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCNAME";
509 i += strlen(
"CCNAME");
510 const QString str = d->mMsg->cc()->displayString();
512 const QString body = plainTextToHtml(str);
515 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCFNAME";
516 i += strlen(
"CCFNAME");
517 const QString str = d->mMsg->cc()->displayString();
518 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
519 plainBody.
append(firstNameFromEmail);
520 const QString body = plainTextToHtml(firstNameFromEmail);
523 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCLNAME";
524 i += strlen(
"CCLNAME");
525 const QString str = d->mMsg->cc()->displayString();
526 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
527 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
530 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOADDR";
531 i += strlen(
"TOADDR");
532 const QString str = d->mMsg->to()->asUnicodeString();
534 const QString body = plainTextToHtml(str);
537 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TONAME";
538 i += strlen(
"TONAME");
539 const QString str = (d->mMsg->to()->displayString());
541 const QString body = plainTextToHtml(str);
544 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOFNAME";
545 i += strlen(
"TOFNAME");
546 const QString str = d->mMsg->to()->displayString();
547 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
548 plainBody.
append(firstNameFromEmail);
549 const QString body = plainTextToHtml(firstNameFromEmail);
552 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOLNAME";
553 i += strlen(
"TOLNAME");
554 const QString str = d->mMsg->to()->displayString();
555 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
556 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
559 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOLIST";
560 i += strlen(
"TOLIST");
561 const QString str = d->mMsg->to()->asUnicodeString();
563 const QString body = plainTextToHtml(str);
566 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMADDR";
567 i += strlen(
"FROMADDR");
568 const QString str = d->mMsg->from()->asUnicodeString();
570 const QString body = plainTextToHtml(str);
573 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMNAME";
574 i += strlen(
"FROMNAME");
575 const QString str = d->mMsg->from()->displayString();
577 const QString body = plainTextToHtml(str);
580 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMFNAME";
581 i += strlen(
"FROMFNAME");
582 const QString str = d->mMsg->from()->displayString();
583 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
584 plainBody.
append(firstNameFromEmail);
585 const QString body = plainTextToHtml(firstNameFromEmail);
588 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMLNAME";
589 i += strlen(
"FROMLNAME");
590 const QString str = d->mMsg->from()->displayString();
591 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
592 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
596 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FULLSUBJ";
597 i += strlen(
"FULLSUBJ");
599 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FULLSUBJECT";
600 i += strlen(
"FULLSUBJECT");
602 const QString str = d->mMsg->subject()->asUnicodeString();
604 const QString body = plainTextToHtml(str);
607 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: MSGID";
608 i += strlen(
"MSGID");
609 const QString str = d->mMsg->messageID()->asUnicodeString();
611 const QString body = plainTextToHtml(str);
615 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OHEADER=";
617 const int len = parseQuotes(QStringLiteral(
"OHEADER="), cmd, q);
623 str = hrdMsgOrigin->asUnicodeString();
626 const QString body = plainTextToHtml(str);
631 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: HEADER=";
633 const int len = parseQuotes(QStringLiteral(
"HEADER="), cmd, q);
638 str = hrdMsgOrigin->asUnicodeString();
641 const QString body = plainTextToHtml(str);
645 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: HEADER(";
648 const int res = cmd.
indexOf(reg, 0, &match);
651 i += strlen(
"HEADER( ");
653 i +=
match.capturedLength(0);
657 str = hrdMsgOrigin->asUnicodeString();
660 const QString body = plainTextToHtml(str);
664 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCADDR";
665 i += strlen(
"OCCADDR");
667 const QString str = d->mOrigMsg->cc()->asUnicodeString();
669 const QString body = plainTextToHtml(str);
673 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCNAME";
674 i += strlen(
"OCCNAME");
676 const QString str = d->mOrigMsg->cc()->displayString();
678 const QString body = plainTextToHtml(str);
682 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCFNAME";
683 i += strlen(
"OCCFNAME");
685 const QString str = d->mOrigMsg->cc()->displayString();
686 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
687 plainBody.
append(firstNameFromEmail);
688 const QString body = plainTextToHtml(firstNameFromEmail);
692 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCLNAME";
693 i += strlen(
"OCCLNAME");
695 const QString str = d->mOrigMsg->cc()->displayString();
696 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
697 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
701 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOADDR";
702 i += strlen(
"OTOADDR");
704 const QString str = d->mOrigMsg->to()->asUnicodeString();
706 const QString body = plainTextToHtml(str);
710 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTONAME";
711 i += strlen(
"OTONAME");
713 const QString str = d->mOrigMsg->to()->displayString();
715 const QString body = plainTextToHtml(str);
719 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOFNAME";
720 i += strlen(
"OTOFNAME");
722 const QString str = d->mOrigMsg->to()->displayString();
723 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
724 plainBody.
append(firstNameFromEmail);
725 const QString body = plainTextToHtml(firstNameFromEmail);
729 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOLNAME";
730 i += strlen(
"OTOLNAME");
732 const QString str = d->mOrigMsg->to()->displayString();
733 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
734 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
738 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOLIST";
739 i += strlen(
"OTOLIST");
741 const QString str = d->mOrigMsg->to()->asUnicodeString();
743 const QString body = plainTextToHtml(str);
747 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTO";
750 const QString str = d->mOrigMsg->to()->asUnicodeString();
752 const QString body = plainTextToHtml(str);
756 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMADDR";
757 i += strlen(
"OFROMADDR");
759 const QString str = d->mOrigMsg->from()->asUnicodeString();
761 const QString body = plainTextToHtml(str);
765 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMNAME";
766 i += strlen(
"OFROMNAME");
768 const QString str = d->mOrigMsg->from()->displayString();
770 const QString body = plainTextToHtml(str);
774 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMFNAME";
775 i += strlen(
"OFROMFNAME");
777 const QString str = d->mOrigMsg->from()->displayString();
778 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
779 plainBody.
append(firstNameFromEmail);
780 const QString body = plainTextToHtml(firstNameFromEmail);
784 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMLNAME";
785 i += strlen(
"OFROMLNAME");
787 const QString str = d->mOrigMsg->from()->displayString();
788 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
789 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
794 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFULLSUBJECT";
795 i += strlen(
"OFULLSUBJECT");
797 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFULLSUBJ";
798 i += strlen(
"OFULLSUBJ");
801 const QString str = d->mOrigMsg->subject()->asUnicodeString();
803 const QString body = plainTextToHtml(str);
807 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OMSGID";
808 i += strlen(
"OMSGID");
810 const QString str = d->mOrigMsg->messageID()->asUnicodeString();
812 const QString body = plainTextToHtml(str);
816 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DATEEN";
817 i += strlen(
"DATEEN");
822 const QString body = plainTextToHtml(str);
825 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DATESHORT";
826 i += strlen(
"DATESHORT");
830 const QString body = plainTextToHtml(str);
833 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DATE";
838 const QString body = plainTextToHtml(str);
841 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DOW";
846 const QString body = plainTextToHtml(str);
849 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TIMELONGEN";
850 i += strlen(
"TIMELONGEN");
855 const QString body = plainTextToHtml(str);
858 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TIMELONG";
859 i += strlen(
"TIMELONG");
863 const QString body = plainTextToHtml(str);
866 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TIME";
871 const QString body = plainTextToHtml(str);
874 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODATEEN";
875 i += strlen(
"ODATEEN");
877 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
880 const QString body = plainTextToHtml(str);
884 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODATESHORT";
885 i += strlen(
"ODATESHORT");
887 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
890 const QString body = plainTextToHtml(str);
894 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODATE";
895 i += strlen(
"ODATE");
897 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
900 const QString body = plainTextToHtml(str);
904 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODOW";
907 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
910 const QString body = plainTextToHtml(str);
914 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTIMELONGEN";
915 i += strlen(
"OTIMELONGEN");
917 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
921 const QString body = plainTextToHtml(str);
925 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTIMELONG";
926 i += strlen(
"OTIMELONG");
928 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
931 const QString body = plainTextToHtml(str);
935 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTIME";
936 i += strlen(
"OTIME");
938 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
941 const QString body = plainTextToHtml(str);
946 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: BLANK";
947 i += strlen(
"BLANK");
950 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: NOP";
954 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CLEAR";
955 i += strlen(
"CLEAR");
960 d->mMsg->setHeader(header);
963 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DEBUGOFF";
964 i += strlen(
"DEBUGOFF");
968 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DEBUG";
969 i += strlen(
"DEBUG");
973 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CURSOR";
975 i += strlen(
"CURSOR");
984 if (oldI > 0 && tmpl[oldI - 1] ==
QLatin1Char(
'\n') && i == tmpl_len - 1) {
987 d->mMsg->setHeader(header);
988 d->mForceCursorPosition =
true;
991 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: SIGNATURE";
992 i += strlen(
"SIGNATURE");
993 plainBody.
append(getPlainSignature());
994 htmlBody.
append(getHtmlSignature());
1002 if ((tmpl.
size() > i + 1)
1013 if (tmpl.
size() > i + 1
1015 htmlBody.
append(tmpl[i + 1]);
1016 plainBody.
append(tmpl[i + 1]);
1027 const KMime::Content *content = d->mOrigMsg->mainBodyPart(
"text/html");
1028 if (d->mQuotes == ReplyAsPlain || (!d->mReplyAsHtml && TemplateParserSettings::self()->replyUsingVisualFormat())
1029 || !TemplateParserSettings::self()->replyUsingVisualFormat() || (!content || !content->
hasContent())) {
1033 makeValidHtml(htmlBody);
1035 if (d->mMode == NewMessage && plainBody.
isEmpty() && !d->mExtractHtmlInfoResult.mPlainText.isEmpty()) {
1036 plainBody = d->mExtractHtmlInfoResult.mPlainText;
1039 addProcessedBodyToMessage(plainBody, htmlBody);
1040 Q_EMIT parsingDone(d->mForceCursorPosition);
1044QString TemplateParserJob::getPlainSignature()
const
1054 if (signature.
type() == KIdentityManagementCore::Signature::Inlined && signature.
isInlinedHtml()) {
1064QString TemplateParserJob::getHtmlSignature()
const
1080void TemplateParserJob::addProcessedBodyToMessage(
const QString &plainBody,
const QString &htmlBody)
const
1087 const auto parts = d->mMsg->contents();
1089 auto c = d->mMsg->takeContent(content);
1094 if (!d->mTo.isEmpty()) {
1095 d->mMsg->to()->fromUnicodeString(d->mMsg->to()->asUnicodeString() +
QLatin1Char(
',') + d->mTo);
1098 if (!d->mCC.isEmpty()) {
1099 d->mMsg->cc()->fromUnicodeString(d->mMsg->cc()->asUnicodeString() +
QLatin1Char(
',') + d->mCC);
1105 KMime::Content *
const mainTextPart = htmlBody.
isEmpty() ? createPlainPartContent(plainBody) : createMultipartAlternativeContent(plainBody, htmlBody);
1109 if (!ic.
images().empty()) {
1110 textPart = createMultipartRelated(ic, mainTextPart);
1111 textPart->assemble();
1117 if (d->mMode == Forward) {
1118 auto attachments = d->mOrigMsg->attachments();
1119 attachments += d->mOtp->nodeHelper()->attachmentsOfExtraContents();
1120 if (!attachments.isEmpty()) {
1121 mainPart = createMultipartMixed(attachments, textPart);
1122 mainPart->assemble();
1126 d->mMsg->setBody(mainPart->encodedBody());
1127 d->mMsg->setHeader(mainPart->contentType());
1128 d->mMsg->setHeader(mainPart->contentTransferEncoding());
1129 d->mMsg->assemble();
1136 const QByteArray boundary = KMime::multiPartBoundary();
1137 auto contentType = mixedPart->contentType();
1138 contentType->setMimeType(
"multipart/mixed");
1139 contentType->setBoundary(boundary);
1140 mixedPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit);
1141 mixedPart->appendContent(textPart);
1143 int attachmentNumber = 1;
1145 mixedPart->appendContent(attachment);
1148 if (
auto ct = attachment->contentType(
false)) {
1149 if (!ct->hasParameter(
"name") && !ct->hasParameter(
"filename")) {
1150 ct->setParameter(QByteArrayLiteral(
"name"),
i18nc(
"@item:intext",
"Attachment %1", attachmentNumber));
1161 const QByteArray boundary = KMime::multiPartBoundary();
1162 auto contentType = relatedPart->contentType();
1163 contentType->setMimeType(
"multipart/related");
1164 contentType->setBoundary(boundary);
1165 relatedPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit);
1166 relatedPart->appendContent(mainTextPart);
1168 qCWarning(TEMPLATEPARSER_LOG) <<
"Adding" << image->contentID() <<
"as an embedded image";
1169 relatedPart->appendContent(image);
1179 ct->setCharset(QByteArrayLiteral(
"UTF-8"));
1188 multipartAlternative->contentType()->setMimeType(
"multipart/alternative");
1189 const QByteArray boundary = KMime::multiPartBoundary();
1190 multipartAlternative->contentType(
false)->setBoundary(boundary);
1193 multipartAlternative->appendContent(textPart);
1196 htmlPart->contentType(
true)->setMimeType(
"text/html");
1197 htmlPart->contentType(
false)->setCharset(QByteArrayLiteral(
"UTF-8"));
1198 htmlPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit);
1199 htmlPart->fromUnicodeString(htmlBody);
1200 multipartAlternative->appendContent(htmlPart);
1202 return multipartAlternative;
1205QString TemplateParserJob::findCustomTemplate(
const QString &tmplName)
1207 CTemplates t(tmplName);
1214 return findTemplate();
1218QString TemplateParserJob::findTemplate()
1224 qCDebug(TEMPLATEPARSER_LOG) <<
"Folder identify found:" << d->mFolder;
1225 if (d->mFolder >= 0) {
1227 Templates fconf(fid);
1228 if (fconf.useCustomTemplates()) {
1231 tmpl = fconf.templateNewMessage();
1234 tmpl = fconf.templateReply();
1237 tmpl = fconf.templateReplyAll();
1240 tmpl = fconf.templateForward();
1243 qCDebug(TEMPLATEPARSER_LOG) <<
"Unknown message mode:" << d->mMode;
1246 d->mQuoteString = fconf.quoteString();
1253 if (!d->mIdentity) {
1254 d->mIdentity = identityUoid(d->mMsg);
1255 if (!d->mIdentity && d->mOrigMsg) {
1256 d->mIdentity = identityUoid(d->mOrigMsg);
1258 d->mIdentity = d->m_identityManager->identityForUoidOrDefault(d->mIdentity).uoid();
1259 if (!d->mIdentity) {
1260 qCDebug(TEMPLATEPARSER_LOG) <<
"Oops! No identity for message";
1263 qCDebug(TEMPLATEPARSER_LOG) <<
"Identity found:" << d->mIdentity;
1269 iid = QStringLiteral(
"IDENTITY_NO_IDENTITY");
1272 Templates iconf(iid);
1273 if (iconf.useCustomTemplates()) {
1276 tmpl = iconf.templateNewMessage();
1279 tmpl = iconf.templateReply();
1282 tmpl = iconf.templateReplyAll();
1285 tmpl = iconf.templateForward();
1288 qCDebug(TEMPLATEPARSER_LOG) <<
"Unknown message mode:" << d->mMode;
1291 d->mQuoteString = iconf.quoteString();
1299 tmpl = TemplateParserSettings::self()->templateNewMessage();
1302 tmpl = TemplateParserSettings::self()->templateReply();
1305 tmpl = TemplateParserSettings::self()->templateReplyAll();
1308 tmpl = TemplateParserSettings::self()->templateForward();
1311 qCDebug(TEMPLATEPARSER_LOG) <<
"Unknown message mode:" << d->mMode;
1315 d->mQuoteString = TemplateParserSettings::self()->quoteString();
1328 bool finished =
false;
1356 if (!success && d->mDebug) {
1371 d->mColWrap = wrapColWidth;
1374QString TemplateParserJob::plainMessageText(
bool aStripSignature, AllowSelection isSelectionAllowed)
const
1376 if (!d->mSelection.isEmpty() && (isSelectionAllowed == SelectionAllowed)) {
1377 return d->mSelection;
1383 const auto mp = toplevelTextNode(d->mOtp->parsedPart());
1384 QString result = mp->plaintextContent();
1386 result = d->mExtractHtmlInfoResult.mPlainText;
1388 if (aStripSignature) {
1395QString TemplateParserJob::htmlMessageText(
bool aStripSignature, AllowSelection isSelectionAllowed)
1397 if (!d->mSelection.isEmpty() && (isSelectionAllowed == SelectionAllowed)) {
1399 return d->mSelection;
1401 d->mHeadElement = d->mExtractHtmlInfoResult.mHeaderElement;
1402 const QString bodyElement = d->mExtractHtmlInfoResult.mBodyElement;
1404 if (aStripSignature) {
1411 if (aStripSignature) {
1415 return d->mExtractHtmlInfoResult.mHtmlElement;
1418QString TemplateParserJob::quotedPlainText(
const QString &selection)
const
1420 QString content = TemplateParser::Util::removeSpaceAtBegin(selection);
1423 if (TemplateParserSettings::self()->
smartQuote() && d->mWrap) {
1433QString TemplateParserJob::quotedHtmlText(
const QString &selection)
const
1450 if (
auto hrd = msg->headerByType(
"X-KMail-Identity")) {
1451 idString = hrd->asUnicodeString().
trimmed();
1454 unsigned int id = idString.
toUInt(&ok);
1456 if (!ok ||
id == 0) {
1457 id = d->m_identityManager->identityForAddress(msg->to()->asUnicodeString() +
QLatin1StringView(
", ") + msg->cc()->asUnicodeString()).uoid();
1463bool TemplateParserJob::isHtmlSignature()
const
1484void TemplateParserJob::makeValidHtml(
QString &body)
1492 regEx.
setPattern(QStringLiteral(
"<html.*?>"));
1494 regEx.
setPattern(QStringLiteral(
"<body.*?>"));
1498 regEx.
setPattern(QStringLiteral(
"<head.*?>"));
1506#include "moc_templateparserjob.cpp"
bool isInlinedHtml() const
QString rawText(bool *ok=nullptr, QString *errorMessage=nullptr) const
QString toPlainText() const
const Headers::ContentType * contentType() const
Content * content(const ContentIndex &index) const
const Headers::ContentTransferEncoding * contentTransferEncoding() const
void fromUnicodeString(const QString &s)
void setShellCommand(const QString &cmd)
void setOutputChannelMode(OutputChannelMode mode)
A helper class to collect the embedded images of a email.
void collectImagesFrom(KMime::Content *content)
Starts collecting the images.
const std::vector< KMime::Content * > & images() const
Returns the collected images.
The AlternativeMessagePart class.
The AttachmentMessagePart class.
The HtmlMessagePart class.
Parses messages and generates HTML display code out of them.
A very simple ObjectTreeSource.
The TextMessagePart class.
void setIdentityManager(KIdentityManagementCore::IdentityManager *ident)
Set the identity manager to be used when creating the template.
void setWordWrap(bool wrap, int wrapColWidth=80)
Tell template parser whether or not to wrap words, and at what column to wrap at.
void setSelection(const QString &selection)
Sets the selection.
void setAllowDecryption(const bool allowDecryption)
Sets whether the template parser is allowed to decrypt the original message when needing its message ...
static QString configIdString(uint id)
Returns the template configuration identifier string for a given identity.
QString xi18nc(const char *context, const char *text, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
QString path(const QString &relativePath)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
KCOREADDONS_EXPORT QString tildeExpand(const QString &path)
QString formatQuotePrefix(const QString &wildString, const QString &fromDisplayString)
Convert quote wildcards into the final quote prefix.
QByteArray headerAsSendableString(const KMime::Message::Ptr &originalMessage)
Return the message header with the headers that should not be sent stripped off.
QString stripSignature(const QString &msg)
Strips the signature blocks from a message text.
QString smartQuote(const QString &msg, int maxLineLength)
Relayouts the given string so that the individual lines don't exceed the given maximal length.
const char * constData() const const
qsizetype size() const const
int dayOfWeek() const const
QDateTime currentDateTime()
qint64 write(const QByteArray &data)
bool contains(const AT &value) const const
QString toString(QDate date, FormatType format) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QProcess::ExitStatus exitStatus() const const
QByteArray readAllStandardOutput()
virtual bool waitForBytesWritten(int msecs) override
bool waitForFinished(int msecs)
bool waitForStarted(int msecs)
void setPattern(const QString &pattern)
QString & append(QChar ch)
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
QString fromLatin1(QByteArrayView str)
QString fromLocal8Bit(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString number(double n, char format, int precision)
QString & prepend(QChar ch)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
qsizetype size() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString toHtmlEscaped() const const
QByteArray toLatin1() const const
QByteArray toLocal8Bit() const const
uint toUInt(bool *ok, int base) const const
QString trimmed() const const