diff options
Diffstat (limited to 'kmail/partNode.cpp')
-rw-r--r-- | kmail/partNode.cpp | 236 |
1 files changed, 200 insertions, 36 deletions
diff --git a/kmail/partNode.cpp b/kmail/partNode.cpp index 80e0545bf..dbd5442ca 100644 --- a/kmail/partNode.cpp +++ b/kmail/partNode.cpp @@ -30,7 +30,10 @@ */ #include <config.h> + #include "partNode.h" +#include "kmreaderwin.h" + #include <klocale.h> #include <kdebug.h> #include "kmmimeparttree.h" @@ -64,12 +67,14 @@ partNode::partNode() mEncodedOk( false ), mDeleteDwBodyPart( false ), mMimePartTreeItem( 0 ), - mBodyPartMemento( 0 ) + mBodyPartMementoMap(), + mReader( 0 ), + mDisplayedEmbedded( false ) { adjustDefaultType( this ); } -partNode::partNode( DwBodyPart* dwPart, int explicitType, int explicitSubType, +partNode::partNode( KMReaderWin * win, DwBodyPart* dwPart, int explicitType, int explicitSubType, bool deleteDwBodyPart ) : mRoot( 0 ), mNext( 0 ), mChild( 0 ), mWasProcessed( false ), @@ -80,13 +85,15 @@ partNode::partNode( DwBodyPart* dwPart, int explicitType, int explicitSubType, mEncodedOk( false ), mDeleteDwBodyPart( deleteDwBodyPart ), mMimePartTreeItem( 0 ), - mBodyPartMemento( 0 ) + mBodyPartMementoMap(), + mReader( win ), + mDisplayedEmbedded( false ), + mDisplayedHidden( false ) { if ( explicitType != DwMime::kTypeUnknown ) { mType = explicitType; // this happens e.g. for the Root Node mSubType = explicitSubType; // representing the _whole_ message } else { -// kdDebug(5006) << "\n partNode::partNode() explicitType == DwMime::kTypeUnknown\n" << endl; if(dwPart && dwPart->hasHeaders() && dwPart->Headers().HasContentType()) { mType = (!dwPart->Headers().ContentType().Type())?DwMime::kTypeUnknown:dwPart->Headers().ContentType().Type(); mSubType = dwPart->Headers().ContentType().Subtype(); @@ -95,17 +102,9 @@ partNode::partNode( DwBodyPart* dwPart, int explicitType, int explicitSubType, mSubType = DwMime::kSubtypeUnknown; } } -#ifdef DEBUG - { - DwString type, subType; - DwTypeEnumToStr( mType, type ); - DwSubtypeEnumToStr( mSubType, subType ); - kdDebug(5006) << "\npartNode::partNode() " << type.c_str() << "/" << subType.c_str() << "\n" << endl; - } -#endif } -partNode * partNode::fromMessage( const KMMessage * msg ) { +partNode * partNode::fromMessage( const KMMessage * msg, KMReaderWin * win ) { if ( !msg ) return 0; @@ -124,11 +123,11 @@ partNode * partNode::fromMessage( const KMMessage * msg ) { // as just another DwBodyPart... DwBodyPart * mainBody = new DwBodyPart( *msg->getTopLevelPart() ); - partNode * root = new partNode( mainBody, mainType, mainSubType, true ); + partNode * root = new partNode( win, mainBody, mainType, mainSubType, true ); root->buildObjectTree(); root->setFromAddress( msg->from() ); - root->dump(); + //root->dump(); return root; } @@ -142,7 +141,9 @@ partNode::partNode( bool deleteDwBodyPart, DwBodyPart* dwPart ) mEncodedOk( false ), mDeleteDwBodyPart( deleteDwBodyPart ), mMimePartTreeItem( 0 ), - mBodyPartMemento( 0 ) + mBodyPartMementoMap(), + mReader( 0 ), + mDisplayedEmbedded( false ) { if ( dwPart && dwPart->hasHeaders() && dwPart->Headers().HasContentType() ) { mType = (!dwPart->Headers().ContentType().Type())?DwMime::kTypeUnknown:dwPart->Headers().ContentType().Type(); @@ -159,13 +160,16 @@ partNode::~partNode() { mDwPart = 0; delete mChild; mChild = 0; delete mNext; mNext = 0; - delete mBodyPartMemento; mBodyPartMemento = 0; + for ( std::map<TQCString,KMail::Interface::BodyPartMemento*>::const_iterator it = mBodyPartMementoMap.begin(), end = mBodyPartMementoMap.end() ; it != end ; ++it ) + delete it->second; + mBodyPartMementoMap.clear(); } #ifndef NDEBUG void partNode::dump( int chars ) const { - kdDebug(5006) << TQString().fill( ' ', chars ) << "+ " - << typeString() << '/' << subTypeString() << endl; + kdDebug(5006) << nodeId() << " " << TQString().fill( ' ', chars ) << "+ " + << typeString() << '/' << subTypeString() << " embedded:" << mDisplayedEmbedded + << " address:" << this << endl; if ( mChild ) mChild->dump( chars + 1 ); if ( mNext ) @@ -194,7 +198,7 @@ void partNode::buildObjectTree( bool processSiblings ) while( curNode && curNode->dwPart() ) { //dive into multipart messages while( DwMime::kTypeMultipart == curNode->type() ) { - partNode * newNode = new partNode( curNode->dwPart()->Body().FirstBodyPart() ); + partNode * newNode = new partNode( mReader, curNode->dwPart()->Body().FirstBodyPart() ); curNode->setFirstChild( newNode ); curNode = newNode; } @@ -210,7 +214,7 @@ void partNode::buildObjectTree( bool processSiblings ) return; // store next node if( curNode && curNode->dwPart() && curNode->dwPart()->Next() ) { - partNode* nextNode = new partNode( curNode->dwPart()->Next() ); + partNode* nextNode = new partNode( mReader, curNode->dwPart()->Next() ); curNode->setNext( nextNode ); curNode = nextNode; } else @@ -230,6 +234,13 @@ TQCString partNode::subTypeString() const { return s.c_str(); } +const partNode* partNode::topLevelParent() const { + const partNode *ret = this; + while ( ret->parentNode() ) + ret = ret->parentNode(); + return ret; +} + int partNode::childCount() const { int count = 0; for ( partNode * child = firstChild() ; child ; child = child->nextSibling() ) @@ -237,6 +248,15 @@ int partNode::childCount() const { return count; } +int partNode::totalChildCount() const { + int count = 0; + for ( partNode * child = firstChild() ; child ; child = child->nextSibling() ) { + ++count; + count += child->totalChildCount(); + } + return count; +} + TQString partNode::contentTypeParameter( const char * name ) const { if ( !mDwPart || !mDwPart->hasHeaders() ) return TQString::null; @@ -292,8 +312,6 @@ KMMsgEncryptionState partNode::overallEncryptionState() const } } -//kdDebug(5006) << "\n\n KMMsgEncryptionState: " << myState << endl; - return myState; } @@ -335,11 +353,24 @@ KMMsgSignatureState partNode::overallSignatureState() const } } -//kdDebug(5006) << "\n\n KMMsgSignatureState: " << myState << endl; - return myState; } +TQCString partNode::path() const +{ + if ( !parentNode() ) + return ':'; + const partNode * p = parentNode(); + + // count number of siblings with the same type as us: + int nth = 0; + for ( const partNode * c = p->firstChild() ; c != this ; c = c->nextSibling() ) + if ( c->type() == type() && c->subType() == subType() ) + ++nth; + + return p->path() + TQCString().sprintf( ":%X/%X[%X]", type(), subType(), nth ); +} + int partNode::nodeId() const { @@ -392,13 +423,6 @@ int partNode::calcNodeIdOrFindNode( int &curId, const partNode* findNode, int fi partNode* partNode::findType( int type, int subType, bool deep, bool wide ) { -#ifndef NDEBUG - DwString typeStr, subTypeStr; - DwTypeEnumToStr( mType, typeStr ); - DwSubtypeEnumToStr( mSubType, subTypeStr ); - kdDebug(5006) << "partNode::findType() is looking at " << typeStr.c_str() - << "/" << subTypeStr.c_str() << endl; -#endif if( (mType != DwMime::kTypeUnknown) && ( (type == DwMime::kTypeUnknown) || (type == mType) ) @@ -471,11 +495,11 @@ void partNode::fillMimePartTree( KMMimePartTreeItem* parentItem, else cntType = "text/plain"; if( cntDesc.isEmpty() ) - cntDesc = msgPart().contentDescription(); - if( cntDesc.isEmpty() ) cntDesc = msgPart().name().stripWhiteSpace(); if( cntDesc.isEmpty() ) cntDesc = msgPart().fileName(); + if( cntDesc.isEmpty() ) + cntDesc = msgPart().contentDescription(); if( cntDesc.isEmpty() ) { if( mRoot && mRoot->mRoot ) cntDesc = i18n("internal part"); @@ -494,8 +518,6 @@ void partNode::fillMimePartTree( KMMimePartTreeItem* parentItem, // remove linebreak+whitespace from folded Content-Description cntDesc.replace( TQRegExp("\\n\\s*"), " " ); -kdDebug(5006) << " Inserting one item into MimePartTree" << endl; -kdDebug(5006) << " Content-Type: " << cntType << endl; if( parentItem ) mMimePartTreeItem = new KMMimePartTreeItem( parentItem, this, @@ -547,6 +569,13 @@ bool partNode::isAttachment() const if ( !dwPart()->hasHeaders() ) return false; DwHeaders& headers = dwPart()->Headers(); + if ( headers.HasContentType() && + headers.ContentType().Type() == DwMime::kTypeMessage && + headers.ContentType().Subtype() == DwMime::kSubtypeRfc822 ) { + // Messages are always attachments. Normally message attachments created from KMail have a content + // disposition, but some mail clients omit that. + return true; + } if( !headers.HasContentDisposition() ) return false; return ( headers.ContentDisposition().DispositionType() @@ -591,6 +620,47 @@ bool partNode::isFirstTextPart() const { return false; // make comiler happy } +bool partNode::isToltecMessage() const +{ + if ( type() != DwMime::kTypeMultipart || subType() != DwMime::kSubtypeMixed ) + return false; + + if ( childCount() != 3 ) + return false; + + const DwField* library = dwPart()->Headers().FindField( "X-Library" ); + if ( !library ) + return false; + + if ( !library->FieldBody() || + TQString( library->FieldBody()->AsString().c_str() ) != TQString( "Toltec" ) ) + return false; + + const DwField* kolabType = dwPart()->Headers().FindField( "X-Kolab-Type" ); + if ( !kolabType ) + return false; + + if ( !kolabType->FieldBody() || + !TQString( kolabType->FieldBody()->AsString().c_str() ).startsWith( "application/x-vnd.kolab" ) ) + return false; + + return true; +} + +bool partNode::isInEncapsulatedMessage() const +{ + const partNode * const topLevel = topLevelParent(); + const partNode *cur = this; + while ( cur && cur != topLevel ) { + const bool parentIsMessage = cur->parentNode() && + cur->parentNode()->msgPart().typeStr().lower() == "message"; + if ( parentIsMessage && cur->parentNode() != topLevel ) + return true; + cur = cur->parentNode(); + } + return false; +} + bool partNode::hasContentDispositionInline() const { if( !dwPart() ) @@ -610,3 +680,97 @@ const TQString& partNode::trueFromAddress() const node = node->mRoot; return node->mFromAddress; } + +KMail::Interface::BodyPartMemento * partNode::bodyPartMemento( const TQCString & which ) const +{ + if ( const KMReaderWin * r = reader() ) + return r->bodyPartMemento( this, which ); + else + return internalBodyPartMemento( which ); +} + +KMail::Interface::BodyPartMemento * partNode::internalBodyPartMemento( const TQCString & which ) const +{ + assert( !reader() ); + + const std::map<TQCString,KMail::Interface::BodyPartMemento*>::const_iterator it = mBodyPartMementoMap.find( which.lower() ); + return it != mBodyPartMementoMap.end() ? it->second : 0 ; +} + +void partNode::setBodyPartMemento( const TQCString & which, KMail::Interface::BodyPartMemento * memento ) +{ + if ( KMReaderWin * r = reader() ) + r->setBodyPartMemento( this, which, memento ); + else + internalSetBodyPartMemento( which, memento ); +} + +void partNode::internalSetBodyPartMemento( const TQCString & which, KMail::Interface::BodyPartMemento * memento ) +{ + assert( !reader() ); + + const std::map<TQCString,KMail::Interface::BodyPartMemento*>::iterator it = mBodyPartMementoMap.lower_bound( which.lower() ); + if ( it != mBodyPartMementoMap.end() && it->first == which.lower() ) { + delete it->second; + if ( memento ) { + it->second = memento; + } + else { + mBodyPartMementoMap.erase( it ); + } + } else { + mBodyPartMementoMap.insert( it, std::make_pair( which.lower(), memento ) ); + } +} + +bool partNode::isDisplayedEmbedded() const +{ + return mDisplayedEmbedded; +} + +void partNode::setDisplayedEmbedded( bool displayedEmbedded ) +{ + mDisplayedEmbedded = displayedEmbedded; +} + +bool partNode::isDisplayedHidden() const +{ + return mDisplayedHidden; +} + +void partNode::setDisplayedHidden( bool displayedHidden ) +{ + mDisplayedHidden = displayedHidden; +} + + +TQString partNode::asHREF( const TQString &place ) const +{ + return TQString( "attachment:%1?place=%2" ).arg( nodeId() ).arg( place ); +} + +partNode::AttachmentDisplayInfo partNode::attachmentDisplayInfo() const +{ + AttachmentDisplayInfo info; + info.icon = msgPart().iconName( KIcon::Small ); + info.label = msgPart().name().stripWhiteSpace(); + if ( info.label.isEmpty() ) + info.label = msgPart().fileName(); + if ( info.label.isEmpty() ) + info.label = msgPart().contentDescription(); + bool typeBlacklisted = msgPart().typeStr().lower() == "multipart"; + if ( !typeBlacklisted && msgPart().typeStr().lower() == "application" ) { + typeBlacklisted = msgPart().subtypeStr() == "pgp-encrypted" + || msgPart().subtypeStr().lower() == "pgp-signature" + || msgPart().subtypeStr().lower() == "pkcs7-mime" + || msgPart().subtypeStr().lower() == "pkcs7-signature"; + } + typeBlacklisted = typeBlacklisted || this == topLevelParent(); + bool firstTextChildOfEncapsulatedMsg = msgPart().typeStr().lower() == "text" && + msgPart().subtypeStr().lower() == "plain" && + parentNode() && + parentNode()->msgPart().typeStr().lower() == "message"; + typeBlacklisted = typeBlacklisted || firstTextChildOfEncapsulatedMsg; + info.displayInHeader = !info.label.isEmpty() && !info.icon.isEmpty() && !typeBlacklisted; + return info; +} |