You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
439 lines
17 KiB
439 lines
17 KiB
/* |
|
* messagecomposer.cpp |
|
* |
|
* Copyright (c) 2004 Bo Thorsen <bo@sonofthor.dk> |
|
* |
|
* This program is free software; you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation; version 2 of the License |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License along |
|
* with this program; if not, write to the Free Software Foundation, Inc., |
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
* |
|
* In addition, as a special exception, the copyright holders give |
|
* permission to link the code of this program with any edition of |
|
* the Qt library by Trolltech AS, Norway (or with modified versions |
|
* of Qt that use the same license as Qt), and distribute linked |
|
* combinations including the two. You must obey the GNU General |
|
* Public License in all respects for all of the code used other than |
|
* Qt. If you modify this file, you may extend this exception to |
|
* your version of the file, but you are not obligated to do so. If |
|
* you do not wish to do so, delete this exception statement from |
|
* your version. |
|
*/ |
|
|
|
#ifndef MESSAGECOMPOSER_H |
|
#define MESSAGECOMPOSER_H |
|
|
|
#include "kmmsgpart.h" |
|
#include "keyresolver.h" |
|
|
|
#include <QObject> |
|
|
|
#include <QList> |
|
#include <QByteArray> |
|
|
|
#include <mimelib/mediatyp.h> |
|
#include "kleo/cryptobackend.h" |
|
|
|
#include <boost/shared_ptr.hpp> |
|
#include <vector> |
|
|
|
class KMMessage; |
|
class KMComposeWin; |
|
|
|
class MessageComposerJob; |
|
class EncryptMessageJob; |
|
class SetLastMessageAsUnencryptedVersionOfLastButOne; |
|
class DwBodyPart; |
|
|
|
namespace Kleo { |
|
class KeyResolver; |
|
} |
|
|
|
namespace GpgME { |
|
class Key; |
|
} |
|
|
|
namespace KPIM { |
|
class Identity; |
|
} |
|
|
|
namespace KMail { |
|
struct EmbeddedImage; |
|
} |
|
|
|
/** |
|
* The MessageComposer actually creates and composes the message(s). |
|
*/ |
|
class MessageComposer : public QObject { |
|
Q_OBJECT |
|
friend class ::MessageComposerJob; |
|
friend class ::EncryptMessageJob; |
|
friend class ::SetLastMessageAsUnencryptedVersionOfLastButOne; |
|
|
|
public: |
|
class KeyResolver; |
|
|
|
MessageComposer( KMComposeWin *win ); |
|
~MessageComposer(); |
|
|
|
/* |
|
Applies the user changes to the message object of the composer |
|
and signs/encrypts the message if activated. Returns false in |
|
case of an error (e.g. if PGP encryption fails). |
|
If backgroundMode is true then no functions which might require |
|
user interaction (like signing/encrypting) are performed |
|
*/ |
|
void applyChanges( bool disableCrypto ); |
|
|
|
QString originalBCC() const { return mBcc; } |
|
|
|
void setDisableBreaking( bool b ) { mDisableBreaking = b; } |
|
|
|
const QVector<KMMessage*> &composedMessageList() const { return mMessageList; } |
|
|
|
bool isPerformingSignOperation() const { return mPerformingSignOperation; } |
|
|
|
signals: |
|
void done( bool ); |
|
|
|
private: |
|
|
|
/** |
|
* This reads information which we need from the composer window and saves it into |
|
* member variables. |
|
* These include the composer text, the attachments, subject, to, cc, the reference message, |
|
* the charset, the embedded images and so on. |
|
*/ |
|
void readFromComposeWin(); |
|
|
|
/** |
|
* This adjusts the signing/encryption policy for the message text and the attachments, |
|
* based on various factors. |
|
* It is called before composing the message with composeMessage(). |
|
*/ |
|
void adjustCryptFlags(); |
|
|
|
bool encryptWithChiasmus( const Kleo::CryptoBackend::Protocol *chiasmus, |
|
const QByteArray &body, |
|
QByteArray &resultData ) const; |
|
void chiasmusEncryptAllAttachments(); |
|
void composeChiasmusMessage( KMMessage &theMessage, |
|
Kleo::CryptoMessageFormat format ); |
|
|
|
/** |
|
* This calls the other composeMessage() for each message that should be created. |
|
* There can be multiple messages created, for example if we sent the encrypted version |
|
* but save the unencrypted version. |
|
*/ |
|
void composeMessage(); |
|
|
|
// And these two are the parts that should be run after job completions |
|
void createUnencryptedMessageVersion(); |
|
|
|
/** |
|
* This is the main composing function. It creates the main body part and |
|
* signs it, then calls continueComposeMessage(). |
|
* |
|
* It is called from the other composeMessage() and can be called multiple times from there, |
|
* to allow composing several messages (encrypted and unencrypted) based on the |
|
* same composer content. That's useful for storing decrypted versions of messages which |
|
* were sent in encrypted form. |
|
*/ |
|
void composeMessage( KMMessage &theMessage, |
|
bool doSign, bool doEncrypt, |
|
Kleo::CryptoMessageFormat format ); |
|
|
|
/** |
|
* This creates the EncryptMessageJobs for the message and adds them to the job queue. |
|
*/ |
|
void continueComposeMessage( KMMessage &theMessage, bool doSign, |
|
bool doEncrypt, |
|
Kleo::CryptoMessageFormat format ); |
|
|
|
/* |
|
Called by composeMessage for inline-openpgp messages |
|
*/ |
|
void composeInlineOpenPGPMessage( KMMessage &theMessage, |
|
bool doSign, bool doEncrypt ); |
|
|
|
/** |
|
* Reads the plain text version and the HTML code from the edit widget, |
|
* applies linebreaks and encodes those with the current charset. |
|
* |
|
* @return false if not all chars could be encoded with the current charset. |
|
*/ |
|
bool getSourceText( QByteArray &plainTextEncoded, QByteArray &htmlSourceEncoded ) const; |
|
|
|
/** |
|
* This sets the member variables mHtmlSource and mPlainText and mBodyText. |
|
* The text is taken from the composer (with proper wordwrapping) and |
|
* then encoded with the correct codec. |
|
* The user is warned if the codec can't encode all characters. |
|
* |
|
* @return false if any error occurred, for example if the text of the body |
|
* couldn't be encoded. |
|
*/ |
|
bool breakLinesAndApplyCodec(); |
|
|
|
/** |
|
* This will automatically detect the charset needed to encode the text of |
|
* the composer. |
|
* mCharset will be set to the detected character set, and the charset of |
|
* the composer window will be set as well. |
|
* |
|
* @return true if the detection was successful, false if no suitable |
|
* charset was found. |
|
*/ |
|
bool autoDetectCharset(); |
|
|
|
/* |
|
Gets the signature for a message (into mMessage). |
|
To build nice S/MIME objects signing and encoding must be separated. |
|
*/ |
|
void pgpSignedMsg( const QByteArray &cText, Kleo::CryptoMessageFormat f ); |
|
|
|
/* |
|
Gets the encrypted message. |
|
To build nice S/MIME objects signing and encrypting must be separate. |
|
*/ |
|
Kpgp::Result pgpEncryptedMsg( QByteArray &rEncryptedBody, |
|
const QByteArray &cText, |
|
const std::vector<GpgME::Key> &encryptionKeys, |
|
Kleo::CryptoMessageFormat f ) const; |
|
|
|
/* |
|
Gets the signed & encrypted message. |
|
To build nice S/MIME objects signing and encrypting must be separate. |
|
*/ |
|
Kpgp::Result pgpSignedAndEncryptedMsg( QByteArray &rEncryptedBody, |
|
const QByteArray &cText, |
|
const std::vector<GpgME::Key> &signingKeys, |
|
const std::vector<GpgME::Key> &encryptionKeys, |
|
Kleo::CryptoMessageFormat f ) const; |
|
|
|
/** |
|
* Builds a MIME object (or a flat text resp.) based upon structuring |
|
* information returned by a crypto plugin that was called via |
|
* pgpSignedMsg() (or pgpEncryptedMsg(), resp.). |
|
* |
|
* @return: The string representation of the MIME object (or the |
|
* flat text, resp.) is returned in resultingPart, so just |
|
* use this string as body text of the surrounding MIME object. |
|
* This string *is* encoded according to contentTEncClear |
|
* and thus should be ready for being sent via SMTP. |
|
*/ |
|
bool processStructuringInfo( const QString bugURL, |
|
const QString contentDescriptionClear, |
|
const QByteArray contentTypeClear, |
|
const QByteArray contentSubtypeClear, |
|
const QByteArray contentDispClear, |
|
const QByteArray contentTEncClear, |
|
const QByteArray &bodytext, |
|
const QString contentDescriptionCiph, |
|
const QByteArray &ciphertext, |
|
KMMessagePart &resultingPart, |
|
bool signing, Kleo::CryptoMessageFormat format ) const; |
|
|
|
void encryptMessage( KMMessage *msg, |
|
const Kleo::KeyResolver::SplitInfo &si, |
|
bool doSign, bool doEncrypt, |
|
KMMessagePart newBodyPart, |
|
Kleo::CryptoMessageFormat format ); |
|
|
|
/** |
|
* This function creates the final message. |
|
* If there are late attachments, they are added to the message, including signing/encryption. |
|
* This actually adds the body parts we have created before to the main message (@p msg). |
|
* After this, the message is complete and can be sent or saved. |
|
*/ |
|
void addBodyAndAttachments( KMMessage *msg, |
|
const Kleo::KeyResolver::SplitInfo &si, |
|
bool doSign, bool doEncrypt, |
|
const KMMessagePart &ourFineBodyPart, |
|
Kleo::CryptoMessageFormat format ); |
|
|
|
private slots: |
|
void slotDoNextJob(); |
|
|
|
private: |
|
void doNextJob(); |
|
void emitDone( bool ); |
|
|
|
bool determineWhetherToSign( bool doSignCompletely ); |
|
bool determineWhetherToEncrypt( bool doEncryptCompletely ); |
|
void markAllAttachmentsForSigning( bool sign ); |
|
void markAllAttachmentsForEncryption( bool enc ); |
|
|
|
/** |
|
* Returns the inner body part. |
|
* |
|
* The inner body part is either multipart/alternative or text/plain, depending on whether |
|
* the message is a HTML message. |
|
* |
|
* The boundary of the multipart/alternative is saved to mSaveBoundary. |
|
* |
|
* @param oldContentType If this is not empty and the message is not HTML, the body part will |
|
* be of this content type, and not text/plain |
|
* @return the complete inner body part |
|
*/ |
|
boost::shared_ptr<DwBodyPart> innerBodypart( KMMessage &theMessage, |
|
bool doSign, QString oldContentType = QString() ); |
|
|
|
/** |
|
* Helper function for innerBodypart(). This creates and returns the body of the inner body |
|
* part, which contains the text/plain and the text/html parts (with boundaries), or only |
|
* the text/plain part, depending on whether the message is HTML. |
|
* |
|
* The boundary seperating the text/plain and text/html parts is saved in mSaveBoundary. |
|
*/ |
|
QByteArray innerBodypartBody( KMMessage &theMessage, bool doSign ); |
|
|
|
/** |
|
* Returns the image body part. |
|
* |
|
* If the message has embedded HTML images, this is a multipart/related body part which |
|
* contains the inner body part and all related images. |
|
* If the message has no embedded HTML images, this is the same as innerBodyPart. |
|
* |
|
* The boundary of the multipart/related is saved to mSaveBoundary. |
|
* |
|
* @param innerBodyPart the inner body part created so far |
|
* @return the complete image body part |
|
*/ |
|
boost::shared_ptr<DwBodyPart> imageBodyPart( KMMessage &theMessage, |
|
boost::shared_ptr<DwBodyPart> innerBodyPart ); |
|
|
|
/** |
|
* Returns the mixed body part |
|
* |
|
* This is a multipart/mixed body part which contains all early attachements, |
|
* and the imageBodyPart. |
|
* If there are no early attachments, this is the same as imageBodyPart. |
|
* |
|
* The boundary of the multipart/mixed is saved to mSaveBoundary. |
|
* |
|
* @param imageBodyPart the image body part created so far |
|
* @return the complete mixed body part |
|
*/ |
|
boost::shared_ptr<DwBodyPart> mixedBodyPart( KMMessage &theMessage, |
|
boost::shared_ptr<DwBodyPart> imageBodyPart, |
|
bool doSignBody, bool doEncryptBody ); |
|
|
|
// The composer window. Mainly used in readFromComposeWin() to read the information from it. |
|
KMComposeWin *mComposeWin; |
|
|
|
MessageComposerJob *mCurrentJob; |
|
KMMessage *mReferenceMessage; |
|
|
|
// This is the list of messages we composed. Each completed message is added to this list, and |
|
// the composer window uses the messages from this list for sending and saving them. |
|
QVector<KMMessage*> mMessageList; |
|
|
|
Kleo::KeyResolver *mKeyResolver; |
|
|
|
QByteArray mSignCertFingerprint; |
|
|
|
// The list of all attachements, including signing/encryption policy |
|
struct Attachment { |
|
Attachment( KMMessagePart *p=0, bool s=false, bool e=false ) |
|
: part( p ), sign( s ), encrypt( e ) {} |
|
KMMessagePart *part; |
|
bool sign; |
|
bool encrypt; |
|
}; |
|
QVector<Attachment> mAttachments; |
|
|
|
// The list of embedded HTML images of the editor |
|
QList<KMail::EmbeddedImage*> mEmbeddedImages; |
|
|
|
QString mPGPSigningKey, mSMIMESigningKey; |
|
bool mUseOpportunisticEncryption; |
|
bool mSignBody, mEncryptBody; |
|
bool mSigningRequested, mEncryptionRequested; |
|
bool mDoSign, mDoEncrypt; |
|
unsigned int mAllowedCryptoMessageFormats; |
|
bool mDisableCrypto; |
|
bool mDisableBreaking; |
|
QString mBcc; |
|
QStringList mTo, mCc, mBccList; |
|
bool mDebugComposerCrypto; |
|
|
|
// If true, we automatically determine the charset of the text part instead of taking |
|
// the charset that is set in the composer window (mCharset). |
|
bool mAutoCharset; |
|
|
|
// The charset which will be used for the text part. It is read from the composer window. |
|
QByteArray mCharset; |
|
|
|
// True if this message is a HTML message. In this case, a multipart/alternative part will |
|
// be created, with both HTML and plain text subparts. |
|
bool mIsRichText; |
|
|
|
// The identity UID of the sender, as read from the composer window. Used, for example, |
|
// for key retrival. |
|
uint mIdentityUid; |
|
|
|
// Set this to false if something fails during the processes. |
|
bool mRc; |
|
|
|
// Don't run the next job yet |
|
bool mHoldJobs; |
|
|
|
// The HTML source and the plain text version of the composer's text, encoded |
|
QByteArray mHtmlSource; |
|
QByteArray mPlainText; |
|
|
|
// Convenience variable, this is the same as one of the two variables above, |
|
// depending on the HTML mode |
|
QByteArray mBodyText; |
|
|
|
// The old body part contains the main body part, i.e. the body part before doing |
|
// signing/encryption and before adding late attachments. |
|
// (Note that I don't know if that also applies for inline OpenPGP and Chiasmus) |
|
KMMessagePart mOldBodyPart; |
|
|
|
// The new body part, which contains the body part that has all the signing/encryption stuff |
|
// and late attachments in it. |
|
// This is the final body part which is set as the body of the final message. |
|
KMMessagePart *mNewBodyPart; |
|
|
|
QByteArray mSignature; |
|
|
|
// This is the main body part, in the encoded version. |
|
// It is only used for signing and encrypting and created in composeMessage(), after the main |
|
// body part has been created. |
|
QByteArray mEncodedBody; |
|
|
|
// True if at least one attachment will be added to the main body part, i.e. added before |
|
// signing/encrypting. Opposed to this, there are 'late' attachments, which are added after |
|
// signing/encrypting, in addBodyAndAttachments(). |
|
bool mEarlyAddAttachments; |
|
|
|
// True if all attachments are added early, see above. |
|
bool mAllAttachmentsAreInBody; |
|
|
|
int mPreviousBoundaryLevel; |
|
|
|
// The boundary of the body part body which we created in the last step. |
|
// When creating body part bodies, for example with innerBodypartBody(), we |
|
// add a boundary seperating the child body parts. However, this boundary needs |
|
// to appear in the content-type header of the body part header, so we need to remember |
|
// the boundary and add it to the content-type header when later creating the body part. |
|
DwString mSaveBoundary; |
|
|
|
// A list of all jobs which are pending execution |
|
QList<MessageComposerJob*> mJobs; |
|
|
|
bool mEncryptWithChiasmus; |
|
bool mPerformingSignOperation; |
|
}; |
|
|
|
#endif /* MESSAGECOMPOSER_H */
|
|
|