Changeset View
Changeset View
Standalone View
Standalone View
messageviewer/src/viewer/messagepart.cpp
Show All 15 Lines | 1 | /* | |||
---|---|---|---|---|---|
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | 16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
17 | 02110-1301, USA. | 17 | 02110-1301, USA. | ||
18 | */ | 18 | */ | ||
19 | 19 | | |||
20 | #include "messagepart.h" | 20 | #include "messagepart.h" | ||
21 | #include "objecttreeparser.h" | 21 | #include "objecttreeparser.h" | ||
22 | 22 | | |||
23 | #include <interfaces/htmlwriter.h> | 23 | #include <interfaces/htmlwriter.h> | ||
24 | #include <htmlwriter/queuehtmlwriter.h> | ||||
24 | #include <kmime/kmime_content.h> | 25 | #include <kmime/kmime_content.h> | ||
25 | #include <gpgme++/key.h> | 26 | #include <gpgme++/key.h> | ||
26 | #include <gpgme.h> | 27 | #include <gpgme.h> | ||
27 | #include <KLocalizedString> | 28 | #include <KLocalizedString> | ||
28 | 29 | | |||
29 | #include <QTextCodec> | 30 | #include <QTextCodec> | ||
30 | #include <boost/graph/graph_concepts.hpp> | 31 | #include <boost/graph/graph_concepts.hpp> | ||
31 | 32 | | |||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Line(s) | |||||
113 | 114 | | |||
114 | CryptoMessagePart::CryptoMessagePart(ObjectTreeParser *otp, | 115 | CryptoMessagePart::CryptoMessagePart(ObjectTreeParser *otp, | ||
115 | PartMetaData *block, | 116 | PartMetaData *block, | ||
116 | const QString &text, | 117 | const QString &text, | ||
117 | const Kleo::CryptoBackend::Protocol *cryptoProto, | 118 | const Kleo::CryptoBackend::Protocol *cryptoProto, | ||
118 | const QString &fromAddress, | 119 | const QString &fromAddress, | ||
119 | KMime::Content *node) | 120 | KMime::Content *node) | ||
120 | : MessagePart(otp, block, text) | 121 | : MessagePart(otp, block, text) | ||
122 | , mSubOtp(0) | ||||
121 | , mCryptoProto(cryptoProto) | 123 | , mCryptoProto(cryptoProto) | ||
122 | , mDecryptMessage(false) | 124 | , mDecryptMessage(false) | ||
123 | , mFromAddress(fromAddress) | 125 | , mFromAddress(fromAddress) | ||
124 | , mNode(node) | 126 | , mNode(node) | ||
125 | , mTextNode(0) | | |||
126 | { | 127 | { | ||
127 | mMetaData->technicalProblem = (mCryptoProto == 0); | 128 | mMetaData->technicalProblem = (mCryptoProto == 0); | ||
128 | mMetaData->isSigned = false; | 129 | mMetaData->isSigned = false; | ||
129 | mMetaData->isGoodSignature = false; | 130 | mMetaData->isGoodSignature = false; | ||
130 | mMetaData->isEncrypted = false; | 131 | mMetaData->isEncrypted = false; | ||
131 | mMetaData->isDecryptable = false; | 132 | mMetaData->isDecryptable = false; | ||
132 | mMetaData->keyTrust = GpgME::Signature::Unknown; | 133 | mMetaData->keyTrust = GpgME::Signature::Unknown; | ||
133 | mMetaData->status = i18n("Wrong Crypto Plug-In."); | 134 | mMetaData->status = i18n("Wrong Crypto Plug-In."); | ||
134 | mMetaData->status_code = GPGME_SIG_STAT_NONE; | 135 | mMetaData->status_code = GPGME_SIG_STAT_NONE; | ||
135 | } | 136 | } | ||
136 | 137 | | |||
138 | CryptoMessagePart::~CryptoMessagePart() | ||||
139 | { | ||||
140 | if (mSubOtp) { | ||||
141 | delete mSubOtp->mHtmlWriter; | ||||
142 | delete mSubOtp; | ||||
143 | mSubOtp = 0; | ||||
144 | } | ||||
145 | } | ||||
146 | | ||||
147 | | ||||
137 | void CryptoMessagePart::startDecryption(const QByteArray &text, const QTextCodec *aCodec) | 148 | void CryptoMessagePart::startDecryption(const QByteArray &text, const QTextCodec *aCodec) | ||
138 | { | 149 | { | ||
139 | mDecryptMessage = true; | 150 | mDecryptMessage = true; | ||
140 | 151 | | |||
141 | KMime::Content *content = new KMime::Content; | 152 | KMime::Content *content = new KMime::Content; | ||
142 | content->setBody(text); | 153 | content->setBody(text); | ||
143 | content->parse(); | 154 | content->parse(); | ||
144 | 155 | | |||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Line(s) | 164 | { | |||
188 | 199 | | |||
189 | if (mMetaData->isSigned) { | 200 | if (mMetaData->isSigned) { | ||
190 | mOtp->sigStatusToMetaData(mSignatures, mCryptoProto, *mMetaData, GpgME::Key()); | 201 | mOtp->sigStatusToMetaData(mSignatures, mCryptoProto, *mMetaData, GpgME::Key()); | ||
191 | mVerifiedText = mDecryptedData; | 202 | mVerifiedText = mDecryptedData; | ||
192 | } | 203 | } | ||
193 | 204 | | |||
194 | if (mNode) { | 205 | if (mNode) { | ||
195 | mOtp->mNodeHelper->setPartMetaData(mNode, *mMetaData); | 206 | mOtp->mNodeHelper->setPartMetaData(mNode, *mMetaData); | ||
207 | | ||||
208 | if (mDecryptMessage) { | ||||
209 | auto tempNode = new KMime::Content(); | ||||
210 | tempNode->setContent(KMime::CRLFtoLF(mDecryptedData.constData())); | ||||
211 | tempNode->parse(); | ||||
212 | | ||||
213 | if (!tempNode->head().isEmpty()) { | ||||
214 | tempNode->contentDescription()->from7BitString("encrypted data"); | ||||
215 | } | ||||
216 | mOtp->mNodeHelper->attachExtraContent(mNode, tempNode); | ||||
217 | | ||||
218 | mSubOtp = new ObjectTreeParser(mOtp, true); | ||||
219 | mSubOtp->setAllowAsync(mOtp->allowAsync()); | ||||
220 | if (mOtp->htmlWriter()) { | ||||
221 | mSubOtp->mHtmlWriter = new QueueHtmlWriter(mOtp->htmlWriter()); | ||||
222 | } | ||||
223 | mSubOtp->parseObjectTreeInternal(tempNode); | ||||
224 | } | ||||
196 | } | 225 | } | ||
197 | } | 226 | } | ||
198 | 227 | | |||
199 | void CryptoMessagePart::startVerification(const QByteArray &text, const QTextCodec *aCodec) | 228 | void CryptoMessagePart::startVerification(const QByteArray &text, const QTextCodec *aCodec) | ||
200 | { | 229 | { | ||
201 | startVerificationDetached(text, 0, QByteArray()); | 230 | startVerificationDetached(text, 0, QByteArray()); | ||
202 | 231 | | |||
203 | if (!mNode && mMetaData->isSigned) { | 232 | if (!mNode && mMetaData->isSigned) { | ||
Show All 11 Lines | 238 | { | |||
215 | if (mMetaData->isSigned) { | 244 | if (mMetaData->isSigned) { | ||
216 | mOtp->sigStatusToMetaData(mSignatures, mCryptoProto, *mMetaData, GpgME::Key()); | 245 | mOtp->sigStatusToMetaData(mSignatures, mCryptoProto, *mMetaData, GpgME::Key()); | ||
217 | } else { | 246 | } else { | ||
218 | mMetaData->creationTime = QDateTime(); | 247 | mMetaData->creationTime = QDateTime(); | ||
219 | } | 248 | } | ||
220 | 249 | | |||
221 | if (mNode) { | 250 | if (mNode) { | ||
222 | if (textNode && !signature.isEmpty()) { | 251 | if (textNode && !signature.isEmpty()) { | ||
223 | mTextNode = textNode; | | |||
224 | mVerifiedText = text; | 252 | mVerifiedText = text; | ||
253 | } else if (!mVerifiedText.isEmpty()) { | ||||
254 | textNode = new KMime::Content(); | ||||
255 | textNode->setContent(KMime::CRLFtoLF(mVerifiedText.constData())); | ||||
256 | textNode->parse(); | ||||
257 | | ||||
258 | if (!textNode->head().isEmpty()) { | ||||
259 | textNode->contentDescription()->from7BitString("opaque signed data"); | ||||
260 | } | ||||
261 | mOtp->mNodeHelper->attachExtraContent(mNode, textNode); | ||||
262 | } | ||||
263 | | ||||
264 | if (!mVerifiedText.isEmpty() && textNode) { | ||||
265 | mSubOtp = new ObjectTreeParser(mOtp, true); | ||||
266 | mSubOtp->setAllowAsync(mOtp->allowAsync()); | ||||
267 | if (mOtp->htmlWriter()) { | ||||
268 | mSubOtp->mHtmlWriter = new QueueHtmlWriter(mOtp->htmlWriter()); | ||||
269 | } | ||||
270 | mSubOtp->parseObjectTreeInternal(textNode); | ||||
225 | } | 271 | } | ||
226 | } | 272 | } | ||
227 | 273 | | |||
228 | } | 274 | } | ||
229 | 275 | | |||
230 | void CryptoMessagePart::writeDeferredDecryptionBlock() const | 276 | void CryptoMessagePart::writeDeferredDecryptionBlock() const | ||
231 | { | 277 | { | ||
232 | Q_ASSERT(!mMetaData->isEncrypted); | 278 | Q_ASSERT(!mMetaData->isEncrypted); | ||
Show All 17 Lines | 288 | writer->queue(QLatin1String("<div style=\"font-size:large; text-align:center;" | |||
250 | + QLatin1String("</a></div>")); | 296 | + QLatin1String("</a></div>")); | ||
251 | } | 297 | } | ||
252 | 298 | | |||
253 | void CryptoMessagePart::html(bool decorate) const | 299 | void CryptoMessagePart::html(bool decorate) const | ||
254 | { | 300 | { | ||
255 | 301 | | |||
256 | bool hideErrors = false; | 302 | bool hideErrors = false; | ||
257 | MessageViewer::HtmlWriter* writer = mOtp->htmlWriter(); | 303 | MessageViewer::HtmlWriter* writer = mOtp->htmlWriter(); | ||
258 | if (!writer) { | 304 | | ||
259 | if (mNode && (mDecryptMessage || !mVerifiedText.isEmpty())) { | 305 | //TODO: still the following part should not be here | ||
260 | //TODO: Bad hack, we need the TempNodeParsing anycase | 306 | if (mSubOtp) { | ||
261 | // but till we not make sure that the nodeparsing also creates html directly we need to have this hack. | 307 | mOtp->copyContentFrom(mSubOtp); | ||
262 | if (!mVerifiedText.isEmpty() && mTextNode) { | | |||
263 | auto otp = new ObjectTreeParser(mOtp, true); | | |||
264 | otp->setAllowAsync(mOtp->allowAsync()); | | |||
265 | otp->parseObjectTreeInternal(mTextNode); | | |||
266 | mOtp->copyContentFrom(otp); | | |||
267 | } else if (!mVerifiedText.isEmpty()) { | | |||
268 | mOtp->createAndParseTempNode(mNode, mVerifiedText.constData(), "opaque signed data"); | | |||
269 | } else { | | |||
270 | mOtp->createAndParseTempNode(mNode, mDecryptedData.constData(), "encrypted node"); | | |||
271 | } | | |||
272 | } | | |||
273 | return; | | |||
274 | } | 308 | } | ||
275 | 309 | | |||
276 | if (mMetaData->isEncrypted && !mDecryptMessage) { | 310 | if (mMetaData->isEncrypted && !mDecryptMessage) { | ||
277 | mMetaData->isDecryptable = true; | 311 | mMetaData->isDecryptable = true; | ||
278 | } | 312 | } | ||
279 | 313 | | |||
314 | if (!writer) { | ||||
315 | return; | ||||
316 | } | ||||
317 | | ||||
280 | if (mMetaData->isEncrypted && !mDecryptMessage) { | 318 | if (mMetaData->isEncrypted && !mDecryptMessage) { | ||
281 | const CryptoBlock block(mOtp, mMetaData, mCryptoProto, mFromAddress, mNode); | 319 | const CryptoBlock block(mOtp, mMetaData, mCryptoProto, mFromAddress, mNode); | ||
282 | writeDeferredDecryptionBlock(); | 320 | writeDeferredDecryptionBlock(); | ||
283 | } else if (mMetaData->inProgress) { | 321 | } else if (mMetaData->inProgress) { | ||
284 | const CryptoBlock block(mOtp, mMetaData, mCryptoProto, mFromAddress, mNode); | 322 | const CryptoBlock block(mOtp, mMetaData, mCryptoProto, mFromAddress, mNode); | ||
285 | // In progress has no special body | 323 | // In progress has no special body | ||
286 | } else if (mMetaData->isEncrypted && !mMetaData->isDecryptable) { | 324 | } else if (mMetaData->isEncrypted && !mMetaData->isDecryptable) { | ||
287 | const CryptoBlock block(mOtp, mMetaData, mCryptoProto, mFromAddress, mNode); | 325 | const CryptoBlock block(mOtp, mMetaData, mCryptoProto, mFromAddress, mNode); | ||
Show All 10 Lines | 335 | if (!mMetaData->status.isEmpty()) { | |||
298 | writer->queue(QStringLiteral("<i>")); | 336 | writer->queue(QStringLiteral("<i>")); | ||
299 | writer->queue(mMetaData->status); | 337 | writer->queue(mMetaData->status); | ||
300 | writer->queue(QStringLiteral("</i>")); | 338 | writer->queue(QStringLiteral("</i>")); | ||
301 | } else { | 339 | } else { | ||
302 | writer->queue(i18nc("Status of message unknown.", "(unknown)")); | 340 | writer->queue(i18nc("Status of message unknown.", "(unknown)")); | ||
303 | } | 341 | } | ||
304 | } else if (mNode) { | 342 | } else if (mNode) { | ||
305 | const CryptoBlock block(mOtp, mMetaData, mCryptoProto, mFromAddress, mNode); | 343 | const CryptoBlock block(mOtp, mMetaData, mCryptoProto, mFromAddress, mNode); | ||
306 | if (!mVerifiedText.isEmpty() && mTextNode) { | 344 | if (mSubOtp) { | ||
307 | auto otp = new ObjectTreeParser(mOtp, true); | 345 | static_cast<QueueHtmlWriter*>(mSubOtp->htmlWriter())->replay(); | ||
vkrause: Hm, this goes against the memory-saving streaming idea of the writer, is there no way we can… | |||||
At the moment no, our problem at the moment is, that mSubOtp->parseObjectTreeInternal(textNode); (line 208) directly creates html output and do not process first and than creates html afterwards. If everything in otp is rewritten with a clean first process than render, we can get rid of this and the QueueHTMLWriter again. Actually this is one of the main reasons I want to rewrite otp - with this QueueHTMLWriter we are now in the position, that i can split the process part from the redering part. knauss: At the moment no, our problem at the moment is, that
```
mSubOtp->parseObjectTreeInternal… | |||||
308 | otp->setAllowAsync(mOtp->allowAsync()); | | |||
309 | otp->parseObjectTreeInternal(mTextNode); | | |||
310 | mOtp->copyContentFrom(otp); | | |||
311 | } else if (!mVerifiedText.isEmpty()) { | | |||
312 | mOtp->createAndParseTempNode(mNode, mVerifiedText.constData(), "opaque signed data"); | | |||
313 | } else { | | |||
314 | mOtp->createAndParseTempNode(mNode, mDecryptedData.constData(), "encrypted node"); | | |||
315 | } | 346 | } | ||
316 | } else { | 347 | } else { | ||
317 | MessagePart::html(decorate); | 348 | MessagePart::html(decorate); | ||
318 | } | 349 | } | ||
319 | } | 350 | } | ||
320 | } | 351 | } |
Hm, this goes against the memory-saving streaming idea of the writer, is there no way we can avoid the record/replay approach? Ie. would it be possible to defer HTML generation to this point?