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>
29 #include <KMessageBox>
37 #include <QRegularExpression>
38 #include <QStringDecoder>
43 Q_DECL_CONSTEXPR
inline int pipeTimeout()
50 for (
const QString &name : charsets) {
61 qCWarning(TEMPLATEPARSER_LOG) <<
"Could not get text codec for charset" <<
name;
66 if (name ==
QLatin1String(
"us-ascii") && !KMime::isUsAscii(text)) {
69 qCDebug(TEMPLATEPARSER_LOG) <<
"Chosen charset" <<
name << codec->
name();
74 qCDebug(TEMPLATEPARSER_LOG) <<
"No appropriate charset found.";
80 using namespace TemplateParser;
82 TemplateParserJobPrivate::TemplateParserJobPrivate(
const KMime::Message::Ptr &amsg,
const TemplateParserJob::Mode amode)
87 mEmptySource->setDecryptMessage(mAllowDecryption);
90 mOtp->setAllowAsync(
false);
93 TemplateParserJobPrivate::~TemplateParserJobPrivate()
99 void TemplateParserJobPrivate::setAllowDecryption(
const bool allowDecryption)
101 mAllowDecryption = allowDecryption;
102 mEmptySource->setDecryptMessage(mAllowDecryption);
107 , d(new TemplateParserJobPrivate(amsg, amode))
111 TemplateParserJob::~TemplateParserJob() =
default;
115 d->mSelection = selection;
120 d->setAllowDecryption(allowDecryption);
123 bool TemplateParserJob::shouldStripSignature()
const
126 return (d->mMode == Reply || d->mMode == ReplyAll) && TemplateParserSettings::self()->stripSignature();
131 d->m_identityManager = ident;
141 int pos = prefix.
length();
143 const int str_len = str.
length();
154 while (pos < str_len) {
155 const QChar c = str[pos];
160 if (!prev.isNull()) {
166 }
else if (quoteChars.
contains(c)) {
179 if (aorig_msg ==
nullptr) {
180 qCDebug(TEMPLATEPARSER_LOG) <<
"aorig_msg == 0!";
181 Q_EMIT parsingDone(d->mForceCursorPosition);
186 d->mOrigMsg = aorig_msg;
187 d->mFolder = afolder;
188 const QString tmpl = findTemplate();
190 Q_EMIT parsingDone(d->mForceCursorPosition);
194 processWithTemplate(tmpl);
199 d->mForceCursorPosition =
false;
200 d->mOrigMsg = aorig_msg;
201 d->mFolder = afolder;
202 const QString tmpl = findCustomTemplate(tmplName);
203 processWithTemplate(tmpl);
206 void TemplateParserJob::processWithIdentity(uint uoid,
const KMime::Message::Ptr &aorig_msg, qint64 afolder)
209 process(aorig_msg, afolder);
214 const auto subParts = messageTree->subParts();
215 for (
const auto &mp : subParts) {
218 if (text && !attach) {
220 const auto mpSubParts{mp->subParts()};
221 for (
const auto &sub : mpSubParts) {
222 if (!sub->text().trimmed().isEmpty()) {
232 auto ret = toplevelTextNode(mp);
241 void TemplateParserJob::processWithTemplate(
const QString &tmpl)
243 d->mOtp->parseObjectTree(d->mOrigMsg.data());
245 const auto mp = toplevelTextNode(d->mOtp->parsedPart());
247 qCWarning(TEMPLATEPARSER_LOG) <<
"Invalid message! mp is null ";
252 QString plainText = mp->plaintextContent();
256 htmlElement = d->mOtp->htmlContent();
258 plainText = htmlElement;
263 htmlElement = QStringLiteral(
"<html><head></head><body>%1</body></html>\n").
arg(htmlReplace);
266 auto job =
new TemplateParserExtractHtmlInfo(
this);
267 connect(job, &TemplateParserExtractHtmlInfo::finished,
this, &TemplateParserJob::slotExtractInfoDone);
269 job->setHtmlForExtractingTextPlain(plainText);
270 job->setTemplate(tmpl);
272 job->setHtmlForExtractionHeaderAndBody(htmlElement);
276 void TemplateParserJob::setReplyAsHtml(
bool replyAsHtml)
278 d->mReplyAsHtml = replyAsHtml;
281 void TemplateParserJob::slotExtractInfoDone(
const TemplateParserExtractHtmlInfoResult &result)
283 d->mExtractHtmlInfoResult = result;
284 const QString tmpl = d->mExtractHtmlInfoResult.mTemplate;
285 const int tmpl_len = tmpl.
length();
290 auto definedLocale =
QLocale();
291 for (
int i = 0; i < tmpl_len; ++i) {
299 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: -";
304 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: REM=";
306 const int len = parseQuotes(QStringLiteral(
"REM="), cmd, q);
310 const int len = parseQuotes(QStringLiteral(
"LANGUAGE="), cmd, q);
317 const int len = parseQuotes(QStringLiteral(
"DICTIONARYLANGUAGE="), cmd, q);
321 header->fromUnicodeString(q,
"utf-8");
322 d->mMsg->setHeader(header);
329 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: INSERT=";
330 len = parseQuotes(QStringLiteral(
"INSERT="), cmd, q);
333 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: PUT=";
334 len = parseQuotes(QStringLiteral(
"PUT="), cmd, q);
339 if (finfo.isRelative()) {
347 const QString body = plainTextToHtml(str);
349 }
else if (d->mDebug) {
350 KMessageBox::error(
nullptr,
i18nc(
"@info",
"Cannot insert content from file %1: %2", path, file.errorString()));
354 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: SYSTEM=";
356 const int len = parseQuotes(QStringLiteral(
"SYSTEM="), cmd, q);
361 const QString body = plainTextToHtml(str);
365 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: QUOTEPIPE=";
367 const int len = parseQuotes(QStringLiteral(
"QUOTEPIPE="), cmd, q);
371 const QString plainStr = pipe(pipe_cmd, plainMessageText(shouldStripSignature(), NoSelectionAllowed));
372 QString plainQuote = quotedPlainText(plainStr);
376 plainBody.
append(plainQuote);
378 const QString htmlStr = pipe(pipe_cmd, htmlMessageText(shouldStripSignature(), NoSelectionAllowed));
379 const QString htmlQuote = quotedHtmlText(htmlStr);
380 htmlBody.
append(htmlQuote);
383 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: QUOTE";
384 i += strlen(
"QUOTE");
386 QString plainQuote = quotedPlainText(plainMessageText(shouldStripSignature(), SelectionAllowed));
390 plainBody.
append(plainQuote);
392 const QString htmlQuote = quotedHtmlText(htmlMessageText(shouldStripSignature(), SelectionAllowed));
393 htmlBody.
append(htmlQuote);
396 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FORCEDPLAIN";
397 d->mQuotes = ReplyAsPlain;
398 i += strlen(
"FORCEDPLAIN");
400 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FORCEDHTML";
401 d->mQuotes = ReplyAsHtml;
402 i += strlen(
"FORCEDHTML");
404 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: QHEADERS";
405 i += strlen(
"QHEADERS");
408 QString plainQuote = quotedPlainText(headerStr);
412 plainBody.
append(plainQuote);
414 const QString htmlQuote = quotedHtmlText(headerStr);
415 const QString str = plainTextToHtml(htmlQuote);
419 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: HEADERS";
420 i += strlen(
"HEADERS");
424 const QString body = plainTextToHtml(str);
429 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TEXTPIPE=";
431 const int len = parseQuotes(QStringLiteral(
"TEXTPIPE="), cmd, q);
435 const QString plainStr = pipe(pipe_cmd, plainMessageText(shouldStripSignature(), NoSelectionAllowed));
436 plainBody.
append(plainStr);
438 const QString htmlStr = pipe(pipe_cmd, htmlMessageText(shouldStripSignature(), NoSelectionAllowed));
443 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: MSGPIPE=";
445 const int len = parseQuotes(QStringLiteral(
"MSGPIPE="), cmd, q);
451 const QString body = plainTextToHtml(str);
456 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: BODYPIPE=";
458 const int len = parseQuotes(QStringLiteral(
"BODYPIPE="), cmd, q);
461 const QString plainStr = pipe(q, plainBody);
462 plainBody.
append(plainStr);
464 const QString htmlStr = pipe(pipe_cmd, htmlBody);
465 const QString body = plainTextToHtml(htmlStr);
470 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CLEARPIPE=";
472 const int len = parseQuotes(QStringLiteral(
"CLEARPIPE="), cmd, q);
475 const QString plainStr = pipe(pipe_cmd, plainBody);
476 plainBody = plainStr;
478 const QString htmlStr = pipe(pipe_cmd, htmlBody);
483 d->mMsg->setHeader(header);
485 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TEXT";
488 const QString plainStr = plainMessageText(shouldStripSignature(), NoSelectionAllowed);
489 plainBody.
append(plainStr);
491 const QString htmlStr = htmlMessageText(shouldStripSignature(), NoSelectionAllowed);
495 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTEXTSIZE";
496 i += strlen(
"OTEXTSIZE");
498 const QString str = QStringLiteral(
"%1").
arg(d->mOrigMsg->body().length());
500 const QString body = plainTextToHtml(str);
504 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTEXT";
505 i += strlen(
"OTEXT");
507 const QString plainStr = plainMessageText(shouldStripSignature(), NoSelectionAllowed);
508 plainBody.
append(plainStr);
510 const QString htmlStr = htmlMessageText(shouldStripSignature(), NoSelectionAllowed);
514 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OADDRESSEESADDR";
515 i += strlen(
"OADDRESSEESADDR");
517 const QString to = d->mOrigMsg->to()->asUnicodeString();
518 const QString cc = d->mOrigMsg->cc()->asUnicodeString();
522 const QString body = plainTextToHtml(toLine);
533 const QString str = plainTextToHtml(ccLine);
538 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCADDR";
539 i += strlen(
"CCADDR");
540 const QString str = d->mMsg->cc()->asUnicodeString();
542 const QString body = plainTextToHtml(str);
545 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCNAME";
546 i += strlen(
"CCNAME");
547 const QString str = d->mMsg->cc()->displayString();
549 const QString body = plainTextToHtml(str);
552 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCFNAME";
553 i += strlen(
"CCFNAME");
554 const QString str = d->mMsg->cc()->displayString();
555 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
556 plainBody.
append(firstNameFromEmail);
557 const QString body = plainTextToHtml(firstNameFromEmail);
560 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CCLNAME";
561 i += strlen(
"CCLNAME");
562 const QString str = d->mMsg->cc()->displayString();
563 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
564 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
567 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOADDR";
568 i += strlen(
"TOADDR");
569 const QString str = d->mMsg->to()->asUnicodeString();
571 const QString body = plainTextToHtml(str);
574 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TONAME";
575 i += strlen(
"TONAME");
576 const QString str = (d->mMsg->to()->displayString());
578 const QString body = plainTextToHtml(str);
581 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOFNAME";
582 i += strlen(
"TOFNAME");
583 const QString str = d->mMsg->to()->displayString();
584 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
585 plainBody.
append(firstNameFromEmail);
586 const QString body = plainTextToHtml(firstNameFromEmail);
589 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOLNAME";
590 i += strlen(
"TOLNAME");
591 const QString str = d->mMsg->to()->displayString();
592 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
593 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
596 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TOLIST";
597 i += strlen(
"TOLIST");
598 const QString str = d->mMsg->to()->asUnicodeString();
600 const QString body = plainTextToHtml(str);
603 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMADDR";
604 i += strlen(
"FROMADDR");
605 const QString str = d->mMsg->from()->asUnicodeString();
607 const QString body = plainTextToHtml(str);
610 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMNAME";
611 i += strlen(
"FROMNAME");
612 const QString str = d->mMsg->from()->displayString();
614 const QString body = plainTextToHtml(str);
617 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMFNAME";
618 i += strlen(
"FROMFNAME");
619 const QString str = d->mMsg->from()->displayString();
620 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
621 plainBody.
append(firstNameFromEmail);
622 const QString body = plainTextToHtml(firstNameFromEmail);
625 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FROMLNAME";
626 i += strlen(
"FROMLNAME");
627 const QString str = d->mMsg->from()->displayString();
628 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
629 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
633 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FULLSUBJ";
634 i += strlen(
"FULLSUBJ");
636 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: FULLSUBJECT";
637 i += strlen(
"FULLSUBJECT");
639 const QString str = d->mMsg->subject()->asUnicodeString();
641 const QString body = plainTextToHtml(str);
644 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: MSGID";
645 i += strlen(
"MSGID");
646 const QString str = d->mMsg->messageID()->asUnicodeString();
648 const QString body = plainTextToHtml(str);
652 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OHEADER=";
654 const int len = parseQuotes(QStringLiteral(
"OHEADER="), cmd, q);
660 str = hrdMsgOrigin->asUnicodeString();
663 const QString body = plainTextToHtml(str);
668 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: HEADER=";
670 const int len = parseQuotes(QStringLiteral(
"HEADER="), cmd, q);
675 str = hrdMsgOrigin->asUnicodeString();
678 const QString body = plainTextToHtml(str);
682 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: HEADER(";
685 const int res = cmd.
indexOf(reg, 0, &match);
688 i += strlen(
"HEADER( ");
690 i +=
match.capturedLength(0);
694 str = hrdMsgOrigin->asUnicodeString();
697 const QString body = plainTextToHtml(str);
701 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCADDR";
702 i += strlen(
"OCCADDR");
704 const QString str = d->mOrigMsg->cc()->asUnicodeString();
706 const QString body = plainTextToHtml(str);
710 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCNAME";
711 i += strlen(
"OCCNAME");
713 const QString str = d->mOrigMsg->cc()->displayString();
715 const QString body = plainTextToHtml(str);
719 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCFNAME";
720 i += strlen(
"OCCFNAME");
722 const QString str = d->mOrigMsg->cc()->displayString();
723 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
724 plainBody.
append(firstNameFromEmail);
725 const QString body = plainTextToHtml(firstNameFromEmail);
729 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OCCLNAME";
730 i += strlen(
"OCCLNAME");
732 const QString str = d->mOrigMsg->cc()->displayString();
733 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
734 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
738 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOADDR";
739 i += strlen(
"OTOADDR");
741 const QString str = d->mOrigMsg->to()->asUnicodeString();
743 const QString body = plainTextToHtml(str);
747 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTONAME";
748 i += strlen(
"OTONAME");
750 const QString str = d->mOrigMsg->to()->displayString();
752 const QString body = plainTextToHtml(str);
756 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOFNAME";
757 i += strlen(
"OTOFNAME");
759 const QString str = d->mOrigMsg->to()->displayString();
760 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
761 plainBody.
append(firstNameFromEmail);
762 const QString body = plainTextToHtml(firstNameFromEmail);
766 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOLNAME";
767 i += strlen(
"OTOLNAME");
769 const QString str = d->mOrigMsg->to()->displayString();
770 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
771 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
775 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTOLIST";
776 i += strlen(
"OTOLIST");
778 const QString str = d->mOrigMsg->to()->asUnicodeString();
780 const QString body = plainTextToHtml(str);
784 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTO";
787 const QString str = d->mOrigMsg->to()->asUnicodeString();
789 const QString body = plainTextToHtml(str);
793 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMADDR";
794 i += strlen(
"OFROMADDR");
796 const QString str = d->mOrigMsg->from()->asUnicodeString();
798 const QString body = plainTextToHtml(str);
802 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMNAME";
803 i += strlen(
"OFROMNAME");
805 const QString str = d->mOrigMsg->from()->displayString();
807 const QString body = plainTextToHtml(str);
811 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMFNAME";
812 i += strlen(
"OFROMFNAME");
814 const QString str = d->mOrigMsg->from()->displayString();
815 const QString firstNameFromEmail = TemplateParser::Util::getFirstNameFromEmail(str);
816 plainBody.
append(firstNameFromEmail);
817 const QString body = plainTextToHtml(firstNameFromEmail);
821 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFROMLNAME";
822 i += strlen(
"OFROMLNAME");
824 const QString str = d->mOrigMsg->from()->displayString();
825 plainBody.
append(TemplateParser::Util::getLastNameFromEmail(str));
826 const QString body = plainTextToHtml(TemplateParser::Util::getLastNameFromEmail(str));
831 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFULLSUBJECT";
832 i += strlen(
"OFULLSUBJECT");
834 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OFULLSUBJ";
835 i += strlen(
"OFULLSUBJ");
838 const QString str = d->mOrigMsg->subject()->asUnicodeString();
840 const QString body = plainTextToHtml(str);
844 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OMSGID";
845 i += strlen(
"OMSGID");
847 const QString str = d->mOrigMsg->messageID()->asUnicodeString();
849 const QString body = plainTextToHtml(str);
853 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DATEEN";
854 i += strlen(
"DATEEN");
859 const QString body = plainTextToHtml(str);
862 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DATESHORT";
863 i += strlen(
"DATESHORT");
867 const QString body = plainTextToHtml(str);
870 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DATE";
875 const QString body = plainTextToHtml(str);
878 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DOW";
883 const QString body = plainTextToHtml(str);
886 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TIMELONGEN";
887 i += strlen(
"TIMELONGEN");
892 const QString body = plainTextToHtml(str);
895 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TIMELONG";
896 i += strlen(
"TIMELONG");
900 const QString body = plainTextToHtml(str);
903 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: TIME";
908 const QString body = plainTextToHtml(str);
911 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODATEEN";
912 i += strlen(
"ODATEEN");
914 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
917 const QString body = plainTextToHtml(str);
921 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODATESHORT";
922 i += strlen(
"ODATESHORT");
924 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
927 const QString body = plainTextToHtml(str);
931 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODATE";
932 i += strlen(
"ODATE");
934 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
937 const QString body = plainTextToHtml(str);
941 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: ODOW";
944 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
947 const QString body = plainTextToHtml(str);
951 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTIMELONGEN";
952 i += strlen(
"OTIMELONGEN");
954 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
958 const QString body = plainTextToHtml(str);
962 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTIMELONG";
963 i += strlen(
"OTIMELONG");
965 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
968 const QString body = plainTextToHtml(str);
972 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: OTIME";
973 i += strlen(
"OTIME");
975 const QDateTime date = d->mOrigMsg->date()->dateTime().toLocalTime();
978 const QString body = plainTextToHtml(str);
983 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: BLANK";
984 i += strlen(
"BLANK");
987 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: NOP";
991 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CLEAR";
992 i += strlen(
"CLEAR");
997 d->mMsg->setHeader(header);
1000 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DEBUGOFF";
1001 i += strlen(
"DEBUGOFF");
1005 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: DEBUG";
1006 i += strlen(
"DEBUG");
1010 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: CURSOR";
1012 i += strlen(
"CURSOR");
1021 if (oldI > 0 && tmpl[oldI - 1] ==
QLatin1Char(
'\n') && i == tmpl_len - 1) {
1024 d->mMsg->setHeader(header);
1025 d->mForceCursorPosition =
true;
1028 qCDebug(TEMPLATEPARSER_LOG) <<
"Command: SIGNATURE";
1029 i += strlen(
"SIGNATURE");
1030 plainBody.
append(getPlainSignature());
1031 htmlBody.
append(getHtmlSignature());
1039 if ((tmpl.
size() > i + 1)
1050 if (tmpl.
size() > i + 1
1052 htmlBody.
append(tmpl[i + 1]);
1053 plainBody.
append(tmpl[i + 1]);
1064 const KMime::Content *content = d->mOrigMsg->mainBodyPart(
"text/html");
1065 if (d->mQuotes == ReplyAsPlain || (!d->mReplyAsHtml && TemplateParserSettings::self()->replyUsingVisualFormat())
1066 || !TemplateParserSettings::self()->replyUsingVisualFormat() || (!content || !content->
hasContent())) {
1070 makeValidHtml(htmlBody);
1072 if (d->mMode == NewMessage && plainBody.
isEmpty() && !d->mExtractHtmlInfoResult.mPlainText.isEmpty()) {
1073 plainBody = d->mExtractHtmlInfoResult.mPlainText;
1076 addProcessedBodyToMessage(plainBody, htmlBody);
1077 Q_EMIT parsingDone(d->mForceCursorPosition);
1081 QString TemplateParserJob::getPlainSignature()
const
1091 if (signature.
type() == KIdentityManagementCore::Signature::Inlined && signature.
isInlinedHtml()) {
1101 QString TemplateParserJob::getHtmlSignature()
const
1117 void TemplateParserJob::addProcessedBodyToMessage(
const QString &plainBody,
const QString &htmlBody)
const
1124 const auto parts = d->mMsg->contents();
1126 d->mMsg->removeContent(content,
true );
1130 if (!d->mTo.isEmpty()) {
1131 d->mMsg->to()->fromUnicodeString(d->mMsg->to()->asUnicodeString() +
QLatin1Char(
',') + d->mTo,
"utf-8");
1134 if (!d->mCC.isEmpty()) {
1135 d->mMsg->cc()->fromUnicodeString(d->mMsg->cc()->asUnicodeString() +
QLatin1Char(
',') + d->mCC,
"utf-8");
1138 d->mMsg->contentType()->clear();
1141 KMime::Content *
const mainTextPart = htmlBody.
isEmpty() ? createPlainPartContent(plainBody) : createMultipartAlternativeContent(plainBody, htmlBody);
1145 if (!ic.
images().empty()) {
1146 textPart = createMultipartRelated(ic, mainTextPart);
1153 if (d->mMode == Forward) {
1154 auto attachments = d->mOrigMsg->attachments();
1155 attachments += d->mOtp->nodeHelper()->attachmentsOfExtraContents();
1156 if (!attachments.isEmpty()) {
1157 mainPart = createMultipartMixed(attachments, textPart);
1165 d->mMsg->assemble();
1172 const QByteArray boundary = KMime::multiPartBoundary();
1173 auto contentType = mixedPart->contentType();
1174 contentType->setMimeType(
"multipart/mixed");
1175 contentType->setBoundary(boundary);
1176 mixedPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit);
1177 mixedPart->addContent(textPart);
1179 int attachmentNumber = 1;
1181 mixedPart->addContent(attachment);
1184 if (
auto ct = attachment->contentType(
false)) {
1185 if (!ct->hasParameter(QStringLiteral(
"name")) && !ct->hasParameter(QStringLiteral(
"filename"))) {
1186 ct->setParameter(QStringLiteral(
"name"),
i18nc(
"@item:intext",
"Attachment %1", attachmentNumber));
1197 const QByteArray boundary = KMime::multiPartBoundary();
1198 auto contentType = relatedPart->contentType();
1199 contentType->setMimeType(
"multipart/related");
1200 contentType->setBoundary(boundary);
1201 relatedPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit);
1202 relatedPart->addContent(mainTextPart);
1204 qCWarning(TEMPLATEPARSER_LOG) <<
"Adding" << image->contentID() <<
"as an embedded image";
1205 relatedPart->addContent(image);
1215 QTextCodec *charset = selectCharset(d->mCharsets, plainBody);
1216 ct->setCharset(charset->
name());
1225 multipartAlternative->contentType()->setMimeType(
"multipart/alternative");
1226 const QByteArray boundary = KMime::multiPartBoundary();
1227 multipartAlternative->contentType(
false)->setBoundary(boundary);
1230 multipartAlternative->addContent(textPart);
1233 htmlPart->contentType(
true)->setMimeType(
"text/html");
1234 QTextCodec *charset = selectCharset(d->mCharsets, htmlBody);
1235 htmlPart->contentType(
false)->setCharset(charset->
name());
1236 htmlPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit);
1237 htmlPart->fromUnicodeString(htmlBody);
1238 multipartAlternative->addContent(htmlPart);
1240 return multipartAlternative;
1243 QString TemplateParserJob::findCustomTemplate(
const QString &tmplName)
1245 CTemplates t(tmplName);
1252 return findTemplate();
1256 QString TemplateParserJob::findTemplate()
1262 qCDebug(TEMPLATEPARSER_LOG) <<
"Folder identify found:" << d->mFolder;
1263 if (d->mFolder >= 0) {
1265 Templates fconf(fid);
1266 if (fconf.useCustomTemplates()) {
1269 tmpl = fconf.templateNewMessage();
1272 tmpl = fconf.templateReply();
1275 tmpl = fconf.templateReplyAll();
1278 tmpl = fconf.templateForward();
1281 qCDebug(TEMPLATEPARSER_LOG) <<
"Unknown message mode:" << d->mMode;
1284 d->mQuoteString = fconf.quoteString();
1291 if (!d->mIdentity) {
1292 d->mIdentity = identityUoid(d->mMsg);
1293 if (!d->mIdentity && d->mOrigMsg) {
1294 d->mIdentity = identityUoid(d->mOrigMsg);
1296 d->mIdentity = d->m_identityManager->identityForUoidOrDefault(d->mIdentity).uoid();
1297 if (!d->mIdentity) {
1298 qCDebug(TEMPLATEPARSER_LOG) <<
"Oops! No identity for message";
1301 qCDebug(TEMPLATEPARSER_LOG) <<
"Identity found:" << d->mIdentity;
1307 iid = QStringLiteral(
"IDENTITY_NO_IDENTITY");
1310 Templates iconf(iid);
1311 if (iconf.useCustomTemplates()) {
1314 tmpl = iconf.templateNewMessage();
1317 tmpl = iconf.templateReply();
1320 tmpl = iconf.templateReplyAll();
1323 tmpl = iconf.templateForward();
1326 qCDebug(TEMPLATEPARSER_LOG) <<
"Unknown message mode:" << d->mMode;
1329 d->mQuoteString = iconf.quoteString();
1337 tmpl = TemplateParserSettings::self()->templateNewMessage();
1340 tmpl = TemplateParserSettings::self()->templateReply();
1343 tmpl = TemplateParserSettings::self()->templateReplyAll();
1346 tmpl = TemplateParserSettings::self()->templateForward();
1349 qCDebug(TEMPLATEPARSER_LOG) <<
"Unknown message mode:" << d->mMode;
1353 d->mQuoteString = TemplateParserSettings::self()->quoteString();
1366 bool finished =
false;
1394 if (!success && d->mDebug) {
1399 QStringDecoder codecFromName(QStringEncoder::System);
1409 d->mColWrap = wrapColWidth;
1412 QString TemplateParserJob::plainMessageText(
bool aStripSignature, AllowSelection isSelectionAllowed)
const
1414 if (!d->mSelection.isEmpty() && (isSelectionAllowed == SelectionAllowed)) {
1415 return d->mSelection;
1421 const auto mp = toplevelTextNode(d->mOtp->parsedPart());
1422 QString result = mp->plaintextContent();
1424 result = d->mExtractHtmlInfoResult.mPlainText;
1426 if (aStripSignature) {
1433 QString TemplateParserJob::htmlMessageText(
bool aStripSignature, AllowSelection isSelectionAllowed)
1435 if (!d->mSelection.isEmpty() && (isSelectionAllowed == SelectionAllowed)) {
1437 return d->mSelection;
1439 d->mHeadElement = d->mExtractHtmlInfoResult.mHeaderElement;
1440 const QString bodyElement = d->mExtractHtmlInfoResult.mBodyElement;
1442 if (aStripSignature) {
1449 if (aStripSignature) {
1453 return d->mExtractHtmlInfoResult.mHtmlElement;
1456 QString TemplateParserJob::quotedPlainText(
const QString &selection)
const
1458 QString content = TemplateParser::Util::removeSpaceAtBegin(selection);
1461 if (TemplateParserSettings::self()->
smartQuote() && d->mWrap) {
1471 QString TemplateParserJob::quotedHtmlText(
const QString &selection)
const
1488 if (
auto hrd = msg->headerByType(
"X-KMail-Identity")) {
1489 idString = hrd->asUnicodeString().
trimmed();
1492 unsigned int id = idString.
toUInt(&ok);
1494 if (!ok ||
id == 0) {
1495 id = d->m_identityManager->identityForAddress(msg->to()->asUnicodeString() +
QLatin1String(
", ") + msg->cc()->asUnicodeString()).uoid();
1501 bool TemplateParserJob::isHtmlSignature()
const
1522 void TemplateParserJob::makeValidHtml(
QString &body)
1530 regEx.
setPattern(QStringLiteral(
"<html.*?>"));
1532 regEx.
setPattern(QStringLiteral(
"<body.*?>"));
1536 regEx.
setPattern(QStringLiteral(
"<head.*?>"));
1544 #include "moc_templateparserjob.cpp"