00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <config.h>
00033 #include "partNode.h"
00034 #include <klocale.h>
00035 #include <kdebug.h>
00036 #include "kmmimeparttree.h"
00037 #include <mimelib/utility.h>
00038 #include <qregexp.h>
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 partNode::partNode()
00054 : mRoot( 0 ), mNext( 0 ), mChild( 0 ),
00055 mWasProcessed( false ),
00056 mDwPart( 0 ),
00057 mType( DwMime::kTypeUnknown ),
00058 mSubType( DwMime::kSubtypeUnknown ),
00059 mCryptoType( CryptoTypeUnknown ),
00060 mEncryptionState( KMMsgNotEncrypted ),
00061 mSignatureState( KMMsgNotSigned ),
00062 mMsgPartOk( false ),
00063 mEncodedOk( false ),
00064 mDeleteDwBodyPart( false ),
00065 mMimePartTreeItem( 0 )
00066 {
00067 adjustDefaultType( this );
00068 }
00069
00070 partNode::partNode( DwBodyPart* dwPart, int explicitType, int explicitSubType,
00071 bool deleteDwBodyPart )
00072 : mRoot( 0 ), mNext( 0 ), mChild( 0 ),
00073 mWasProcessed( false ),
00074 mDwPart( dwPart ),
00075 mCryptoType( CryptoTypeUnknown ),
00076 mEncryptionState( KMMsgNotEncrypted ),
00077 mSignatureState( KMMsgNotSigned ),
00078 mMsgPartOk( false ),
00079 mEncodedOk( false ),
00080 mDeleteDwBodyPart( deleteDwBodyPart ),
00081 mMimePartTreeItem( 0 )
00082 {
00083 if ( explicitType != DwMime::kTypeUnknown ) {
00084 mType = explicitType;
00085 mSubType = explicitSubType;
00086 } else {
00087 kdDebug(5006) << "\n partNode::partNode() explicitType == DwMime::kTypeUnknown\n" << endl;
00088 if(dwPart && dwPart->hasHeaders() && dwPart->Headers().HasContentType()) {
00089 mType = (!dwPart->Headers().ContentType().Type())?DwMime::kTypeUnknown:dwPart->Headers().ContentType().Type();
00090 mSubType = dwPart->Headers().ContentType().Subtype();
00091 } else {
00092 mType = DwMime::kTypeUnknown;
00093 mSubType = DwMime::kSubtypeUnknown;
00094 }
00095 }
00096 #ifdef DEBUG
00097 {
00098 DwString type, subType;
00099 DwTypeEnumToStr( mType, type );
00100 DwSubtypeEnumToStr( mSubType, subType );
00101 kdDebug(5006) << "\npartNode::partNode() " << type.c_str() << "/" << subType.c_str() << "\n" << endl;
00102 }
00103 #endif
00104 }
00105
00106 partNode::partNode( bool deleteDwBodyPart, DwBodyPart* dwPart )
00107 : mRoot( 0 ), mNext( 0 ), mChild( 0 ),
00108 mWasProcessed( false ),
00109 mDwPart( dwPart ),
00110 mCryptoType( CryptoTypeUnknown ),
00111 mEncryptionState( KMMsgNotEncrypted ),
00112 mSignatureState( KMMsgNotSigned ),
00113 mMsgPartOk( false ),
00114 mEncodedOk( false ),
00115 mDeleteDwBodyPart( deleteDwBodyPart ),
00116 mMimePartTreeItem( 0 )
00117 {
00118 if ( dwPart && dwPart->hasHeaders() && dwPart->Headers().HasContentType() ) {
00119 mType = (!dwPart->Headers().ContentType().Type())?DwMime::kTypeUnknown:dwPart->Headers().ContentType().Type();
00120 mSubType = dwPart->Headers().ContentType().Subtype();
00121 } else {
00122 mType = DwMime::kTypeUnknown;
00123 mSubType = DwMime::kSubtypeUnknown;
00124 }
00125 }
00126
00127 partNode::~partNode() {
00128 if( mDeleteDwBodyPart )
00129 delete mDwPart;
00130 delete mChild;
00131 delete mNext;
00132 }
00133
00134 #ifndef NDEBUG
00135 void partNode::dump( int chars ) const {
00136 kdDebug(5006) << QString().fill( ' ', chars ) << "+ "
00137 << typeString() << '/' << subTypeString() << endl;
00138 if ( mChild )
00139 mChild->dump( chars + 1 );
00140 if ( mNext )
00141 mNext->dump( chars );
00142 }
00143 #else
00144 void partNode::dump( int ) const {}
00145 #endif
00146
00147 const QCString & partNode::encodedBody() {
00148 if ( mEncodedOk )
00149 return mEncodedBody;
00150
00151 if ( mDwPart )
00152 mEncodedBody = mDwPart->AsString().c_str();
00153 else
00154 mEncodedBody = 0;
00155 mEncodedOk = true;
00156 return mEncodedBody;
00157 }
00158
00159
00160 void partNode::buildObjectTree( bool processSiblings )
00161 {
00162 partNode* curNode = this;
00163 while( curNode && curNode->dwPart() ) {
00164
00165 while( DwMime::kTypeMultipart == curNode->type() ) {
00166 partNode * newNode = new partNode( curNode->dwPart()->Body().FirstBodyPart() );
00167 curNode->setFirstChild( newNode );
00168 curNode = newNode;
00169 }
00170
00171
00172 while( curNode
00173 && !( curNode->dwPart()
00174 && curNode->dwPart()->Next() ) ) {
00175 curNode = curNode->mRoot;
00176 }
00177
00178 if( this == curNode && !processSiblings )
00179 return;
00180
00181 if( curNode && curNode->dwPart() && curNode->dwPart()->Next() ) {
00182 partNode* nextNode = new partNode( curNode->dwPart()->Next() );
00183 curNode->setNext( nextNode );
00184 curNode = nextNode;
00185 } else
00186 curNode = 0;
00187 }
00188 }
00189
00190 QCString partNode::typeString() const {
00191 DwString s;
00192 DwTypeEnumToStr( type(), s );
00193 return s.c_str();
00194 }
00195
00196 QCString partNode::subTypeString() const {
00197 DwString s;
00198 DwSubtypeEnumToStr( subType(), s );
00199 return s.c_str();
00200 }
00201
00202 partNode::CryptoType partNode::firstCryptoType() const
00203 {
00204 CryptoType ret = cryptoType();
00205 if( (CryptoTypeUnknown == ret || CryptoTypeNone == ret)
00206 && mChild )
00207 ret = mChild->firstCryptoType();
00208 if( (CryptoTypeUnknown == ret || CryptoTypeNone == ret)
00209 && mNext )
00210 ret = mNext->firstCryptoType();
00211 return ret;
00212 }
00213
00214
00215 KMMsgEncryptionState partNode::overallEncryptionState() const
00216 {
00217 KMMsgEncryptionState myState = KMMsgEncryptionStateUnknown;
00218 if( mEncryptionState == KMMsgNotEncrypted ) {
00219
00220 if( mChild )
00221 myState = mChild->overallEncryptionState();
00222 else
00223 myState = KMMsgNotEncrypted;
00224 }
00225 else {
00226 myState = mEncryptionState;
00227 }
00228
00229 if( mNext ) {
00230 KMMsgEncryptionState otherState = mNext->overallEncryptionState();
00231 switch( otherState ) {
00232 case KMMsgEncryptionStateUnknown:
00233 break;
00234 case KMMsgNotEncrypted:
00235 if( myState == KMMsgFullyEncrypted )
00236 myState = KMMsgPartiallyEncrypted;
00237 else if( myState != KMMsgPartiallyEncrypted )
00238 myState = KMMsgNotEncrypted;
00239 break;
00240 case KMMsgPartiallyEncrypted:
00241 myState = KMMsgPartiallyEncrypted;
00242 break;
00243 case KMMsgFullyEncrypted:
00244 if( myState != KMMsgFullyEncrypted )
00245 myState = KMMsgPartiallyEncrypted;
00246 break;
00247 case KMMsgEncryptionProblematic:
00248 break;
00249 }
00250 }
00251
00252
00253
00254 return myState;
00255 }
00256
00257
00258 KMMsgSignatureState partNode::overallSignatureState() const
00259 {
00260 KMMsgSignatureState myState = KMMsgSignatureStateUnknown;
00261 if( mSignatureState == KMMsgNotSigned ) {
00262
00263 if( mChild )
00264 myState = mChild->overallSignatureState();
00265 else
00266 myState = KMMsgNotSigned;
00267 }
00268 else {
00269 myState = mSignatureState;
00270 }
00271
00272 if( mNext ) {
00273 KMMsgSignatureState otherState = mNext->overallSignatureState();
00274 switch( otherState ) {
00275 case KMMsgSignatureStateUnknown:
00276 break;
00277 case KMMsgNotSigned:
00278 if( myState == KMMsgFullySigned )
00279 myState = KMMsgPartiallySigned;
00280 else if( myState != KMMsgPartiallySigned )
00281 myState = KMMsgNotSigned;
00282 break;
00283 case KMMsgPartiallySigned:
00284 myState = KMMsgPartiallySigned;
00285 break;
00286 case KMMsgFullySigned:
00287 if( myState != KMMsgFullySigned )
00288 myState = KMMsgPartiallySigned;
00289 break;
00290 case KMMsgEncryptionProblematic:
00291 break;
00292 }
00293 }
00294
00295
00296
00297 return myState;
00298 }
00299
00300
00301 int partNode::nodeId()
00302 {
00303 int curId = 0;
00304 partNode* rootNode = this;
00305 while( rootNode->mRoot )
00306 rootNode = rootNode->mRoot;
00307 return rootNode->calcNodeIdOrFindNode( curId, this, 0, 0 );
00308 }
00309
00310
00311 partNode* partNode::findId( int id )
00312 {
00313 int curId = 0;
00314 partNode* rootNode = this;
00315 while( rootNode->mRoot )
00316 rootNode = rootNode->mRoot;
00317 partNode* foundNode;
00318 rootNode->calcNodeIdOrFindNode( curId, 0, id, &foundNode );
00319 return foundNode;
00320 }
00321
00322
00323 int partNode::calcNodeIdOrFindNode( int &curId, const partNode* findNode, int findId, partNode** foundNode )
00324 {
00325
00326
00327 curId++;
00328
00329 if( findNode && this == findNode )
00330 return curId;
00331
00332 if( foundNode && curId == findId ) {
00333 *foundNode = this;
00334 return curId;
00335 }
00336 if( mChild )
00337 {
00338 int res = mChild->calcNodeIdOrFindNode( curId, findNode, findId, foundNode );
00339 if (res != -1) return res;
00340 }
00341 if( mNext )
00342 return mNext->calcNodeIdOrFindNode( curId, findNode, findId, foundNode );
00343
00344 if( foundNode )
00345 *foundNode = 0;
00346 return -1;
00347 }
00348
00349
00350 partNode* partNode::findType( int type, int subType, bool deep, bool wide )
00351 {
00352 #ifndef NDEBUG
00353 DwString typeStr, subTypeStr;
00354 DwTypeEnumToStr( mType, typeStr );
00355 DwSubtypeEnumToStr( mSubType, subTypeStr );
00356 kdDebug(5006) << "partNode::findType() is looking at " << typeStr.c_str()
00357 << "/" << subTypeStr.c_str() << endl;
00358 #endif
00359 if( (mType != DwMime::kTypeUnknown)
00360 && ( (type == DwMime::kTypeUnknown)
00361 || (type == mType) )
00362 && ( (subType == DwMime::kSubtypeUnknown)
00363 || (subType == mSubType) ) )
00364 return this;
00365 else if( mChild && deep )
00366 return mChild->findType( type, subType, deep, wide );
00367 else if( mNext && wide )
00368 return mNext->findType( type, subType, deep, wide );
00369 else
00370 return 0;
00371 }
00372
00373 partNode* partNode::findTypeNot( int type, int subType, bool deep, bool wide )
00374 {
00375 if( (mType != DwMime::kTypeUnknown)
00376 && ( (type == DwMime::kTypeUnknown)
00377 || (type != mType) )
00378 && ( (subType == DwMime::kSubtypeUnknown)
00379 || (subType != mSubType) ) )
00380 return this;
00381 else if( mChild && deep )
00382 return mChild->findTypeNot( type, subType, deep, wide );
00383 else if( mNext && wide )
00384 return mNext->findTypeNot( type, subType, deep, wide );
00385 else
00386 return 0;
00387 }
00388
00389 void partNode::fillMimePartTree( KMMimePartTreeItem* parentItem,
00390 KMMimePartTree* mimePartTree,
00391 QString labelDescr,
00392 QString labelCntType,
00393 QString labelEncoding,
00394 KIO::filesize_t size,
00395 bool revertOrder )
00396 {
00397 if( parentItem || mimePartTree ) {
00398
00399 if( mNext )
00400 mNext->fillMimePartTree( parentItem, mimePartTree,
00401 QString::null, QString::null, QString::null, 0,
00402 revertOrder );
00403
00404 QString cntDesc, cntType, cntEnc;
00405 KIO::filesize_t cntSize = 0;
00406
00407 if( labelDescr.isEmpty() ) {
00408 DwHeaders* headers = 0;
00409 if( mDwPart && mDwPart->hasHeaders() )
00410 headers = &mDwPart->Headers();
00411 if( headers && headers->HasSubject() )
00412 cntDesc = KMMsgBase::decodeRFC2047String( headers->Subject().AsString().c_str() );
00413 if( headers && headers->HasContentType()) {
00414 cntType = headers->ContentType().TypeStr().c_str();
00415 cntType += '/';
00416 cntType += headers->ContentType().SubtypeStr().c_str();
00417 }
00418 else
00419 cntType = "text/plain";
00420 if( cntDesc.isEmpty() )
00421 cntDesc = msgPart().contentDescription();
00422 if( cntDesc.isEmpty() )
00423 cntDesc = msgPart().name().stripWhiteSpace();
00424 if( cntDesc.isEmpty() )
00425 cntDesc = msgPart().fileName();
00426 if( cntDesc.isEmpty() ) {
00427 if( mRoot && mRoot->mRoot )
00428 cntDesc = i18n("internal part");
00429 else
00430 cntDesc = i18n("body part");
00431 }
00432 cntEnc = msgPart().contentTransferEncodingStr();
00433 if( mDwPart )
00434 cntSize = mDwPart->BodySize();
00435 } else {
00436 cntDesc = labelDescr;
00437 cntType = labelCntType;
00438 cntEnc = labelEncoding;
00439 cntSize = size;
00440 }
00441
00442 cntDesc.replace( QRegExp("\\n\\s*"), " " );
00443
00444 kdDebug(5006) << " Inserting one item into MimePartTree" << endl;
00445 kdDebug(5006) << " Content-Type: " << cntType << endl;
00446 if( parentItem )
00447 mMimePartTreeItem = new KMMimePartTreeItem( parentItem,
00448 this,
00449 cntDesc,
00450 cntType,
00451 cntEnc,
00452 cntSize,
00453 revertOrder );
00454 else if( mimePartTree )
00455 mMimePartTreeItem = new KMMimePartTreeItem( mimePartTree,
00456 this,
00457 cntDesc,
00458 cntType,
00459 cntEnc,
00460 cntSize );
00461 mMimePartTreeItem->setOpen( true );
00462 if( mChild )
00463 mChild->fillMimePartTree( mMimePartTreeItem, 0,
00464 QString::null, QString::null, QString::null, 0,
00465 revertOrder );
00466
00467 }
00468 }
00469
00470 void partNode::adjustDefaultType( partNode* node )
00471 {
00472
00473
00474
00475 if( node && DwMime::kTypeUnknown == node->type() ) {
00476 if( node->mRoot
00477 && DwMime::kTypeMultipart == node->mRoot->type()
00478 && DwMime::kSubtypeDigest == node->mRoot->subType() ) {
00479 node->setType( DwMime::kTypeMessage );
00480 node->setSubType( DwMime::kSubtypeRfc822 );
00481 }
00482 else
00483 {
00484 node->setType( DwMime::kTypeText );
00485 node->setSubType( DwMime::kSubtypePlain );
00486 }
00487 }
00488 }
00489
00490 bool partNode::isAttachment() const
00491 {
00492 if( !dwPart() )
00493 return false;
00494 DwHeaders& headers = dwPart()->Headers();
00495 if( headers.HasContentDisposition() )
00496 return ( headers.ContentDisposition().DispositionType()
00497 == DwMime::kDispTypeAttachment );
00498 else
00499 return false;
00500 }
00501
00502 bool partNode::hasContentDispositionInline() const
00503 {
00504 if( !dwPart() )
00505 return false;
00506 DwHeaders& headers = dwPart()->Headers();
00507 if( headers.HasContentDisposition() )
00508 return ( headers.ContentDisposition().DispositionType()
00509 == DwMime::kDispTypeInline );
00510 else
00511 return false;
00512 }
00513
00514 const QString& partNode::trueFromAddress() const
00515 {
00516 const partNode* node = this;
00517 while( node->mFromAddress.isEmpty() && node->mRoot )
00518 node = node->mRoot;
00519 return node->mFromAddress;
00520 }