00001
00002
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006
00007 #include "kmmsginfo.h"
00008 #include "kmmessage.h"
00009
00010
00011 #include <stdlib.h>
00012 #include <string.h>
00013 #include <stdio.h>
00014 #include <assert.h>
00015 #include <mimelib/datetime.h>
00016
00017 class KMMsgInfo::KMMsgInfoPrivate
00018 {
00019 public:
00020 enum {
00021 SUBJECT_SET = 0x01, TO_SET = 0x02, REPLYTO_SET = 0x04, MSGID_SET=0x08,
00022 DATE_SET = 0x10, OFFSET_SET = 0x20, SIZE_SET = 0x40,
00023 XMARK_SET=0x100, FROM_SET=0x200, FILE_SET=0x400, ENCRYPTION_SET=0x800,
00024 SIGNATURE_SET=0x1000, MDN_SET=0x2000, REPLYTOAUX_SET = 0x4000,
00025 STRIPPEDSUBJECT_SET = 0x8000,
00026
00027 ALL_SET = 0xFFFF, NONE_SET = 0x0000
00028 };
00029 uint modifiers;
00030 QString subject, from, to, replyToIdMD5, replyToAuxIdMD5,
00031 strippedSubjectMD5, msgIdMD5, xmark, file;
00032 off_t folderOffset;
00033 size_t msgSize;
00034 time_t date;
00035 KMMsgEncryptionState encryptionState;
00036 KMMsgSignatureState signatureState;
00037 KMMsgMDNSentState mdnSentState;
00038
00039 KMMsgInfoPrivate() : modifiers(NONE_SET) { }
00040 KMMsgInfoPrivate& operator=(const KMMsgInfoPrivate& other) {
00041 modifiers = NONE_SET;
00042 if (other.modifiers & SUBJECT_SET) {
00043 modifiers |= SUBJECT_SET;
00044 subject = other.subject;
00045 }
00046 if (other.modifiers & STRIPPEDSUBJECT_SET) {
00047 modifiers |= STRIPPEDSUBJECT_SET;
00048 strippedSubjectMD5 = other.strippedSubjectMD5;
00049 }
00050 if (other.modifiers & FROM_SET) {
00051 modifiers |= FROM_SET;
00052 from = other.from;
00053 }
00054 if (other.modifiers & FILE_SET) {
00055 modifiers |= FILE_SET;
00056 file = other.from;
00057 }
00058 if (other.modifiers & TO_SET) {
00059 modifiers |= TO_SET;
00060 to = other.to;
00061 }
00062 if (other.modifiers & REPLYTO_SET) {
00063 modifiers |= REPLYTO_SET;
00064 replyToIdMD5 = other.replyToIdMD5;
00065 }
00066 if (other.modifiers & REPLYTOAUX_SET) {
00067 modifiers |= REPLYTOAUX_SET;
00068 replyToAuxIdMD5 = other.replyToAuxIdMD5;
00069 }
00070
00071 if(other.modifiers & MSGID_SET) {
00072 modifiers |= MSGID_SET;
00073 msgIdMD5 = other.msgIdMD5;
00074 }
00075 if(other.modifiers & XMARK_SET) {
00076 modifiers |= XMARK_SET;
00077 xmark = other.xmark;
00078 }
00079 if(other.modifiers & OFFSET_SET) {
00080 modifiers |= OFFSET_SET;
00081 folderOffset = other.folderOffset;
00082 }
00083 if(other.modifiers & SIZE_SET) {
00084 modifiers |= SIZE_SET;
00085 msgSize = other.msgSize;
00086 }
00087 if(other.modifiers & DATE_SET) {
00088 modifiers |= DATE_SET;
00089 date = other.date;
00090 }
00091 if(other.modifiers & ENCRYPTION_SET) {
00092 modifiers |= ENCRYPTION_SET;
00093 encryptionState = other.encryptionState;
00094 }
00095 if(other.modifiers & SIGNATURE_SET) {
00096 modifiers |= SIGNATURE_SET;
00097 signatureState = other.signatureState;
00098 }
00099 if(other.modifiers & ENCRYPTION_SET) {
00100 modifiers |= ENCRYPTION_SET;
00101 encryptionState = other.encryptionState;
00102 }
00103 if(other.modifiers & SIGNATURE_SET) {
00104 modifiers |= SIGNATURE_SET;
00105 signatureState = other.signatureState;
00106 }
00107 if(other.modifiers & MDN_SET) {
00108 modifiers |= MDN_SET;
00109 mdnSentState = other.mdnSentState;
00110 }
00111 return *this;
00112 }
00113 };
00114
00115
00116 KMMsgInfo::KMMsgInfo(KMFolderIndex* p, off_t off, short len) :
00117 KMMsgBase(p),
00118 kd(0)
00119 {
00120 setIndexOffset(off);
00121 setIndexLength(len);
00122 setEnableUndo(true);
00123 }
00124
00125
00126
00127 KMMsgInfo::~KMMsgInfo()
00128 {
00129 delete kd;
00130 }
00131
00132
00133
00134 KMMsgInfo& KMMsgInfo::operator=(const KMMsgInfo& other)
00135 {
00136 KMMsgBase::assign(&other);
00137 if(other.kd) {
00138 if(!kd)
00139 kd = new KMMsgInfoPrivate;
00140 *kd = *other.kd;
00141 } else {
00142 delete kd;
00143 kd = 0;
00144 }
00145 mStatus = other.status();
00146 return *this;
00147 }
00148
00149
00150
00151 KMMsgInfo& KMMsgInfo::operator=(const KMMessage& msg)
00152 {
00153 KMMsgBase::assign(&msg.toMsgBase());
00154 if(!kd)
00155 kd = new KMMsgInfoPrivate;
00156 kd->modifiers = KMMsgInfoPrivate::ALL_SET;
00157 kd->subject = msg.subject();
00158 kd->from = msg.fromStrip();
00159 kd->to = msg.toStrip();
00160 kd->replyToIdMD5 = msg.replyToIdMD5();
00161 kd->replyToAuxIdMD5 = msg.replyToAuxIdMD5();
00162 kd->strippedSubjectMD5 = msg.strippedSubjectMD5();
00163 kd->msgIdMD5 = msg.msgIdMD5();
00164 kd->xmark = msg.xmark();
00165 mStatus = msg.status();
00166 kd->folderOffset = msg.folderOffset();
00167 kd->msgSize = msg.msgSize();
00168 kd->date = msg.date();
00169 kd->file = msg.fileName();
00170 kd->encryptionState = msg.encryptionState();
00171 kd->signatureState = msg.signatureState();
00172 kd->mdnSentState = msg.mdnSentState();
00173 return *this;
00174 }
00175
00176
00177 void KMMsgInfo::init(const QCString& aSubject, const QCString& aFrom,
00178 const QCString& aTo, time_t aDate,
00179 KMMsgStatus aStatus, const QCString& aXMark,
00180 const QCString& replyToId, const QCString& replyToAuxId,
00181 const QCString& msgId,
00182 KMMsgEncryptionState encryptionState,
00183 KMMsgSignatureState signatureState,
00184 KMMsgMDNSentState mdnSentState,
00185 off_t aFolderOffset, size_t aMsgSize)
00186 {
00187 mIndexOffset = 0;
00188 mIndexLength = 0;
00189 if(!kd)
00190 kd = new KMMsgInfoPrivate;
00191 kd->modifiers = KMMsgInfoPrivate::ALL_SET;
00192 kd->subject = decodeRFC2047String(aSubject);
00193 kd->from = decodeRFC2047String( KMMessage::stripEmailAddr( aFrom ) );
00194 kd->to = decodeRFC2047String( KMMessage::stripEmailAddr( aTo ) );
00195 kd->replyToIdMD5 = base64EncodedMD5( replyToId );
00196 kd->replyToAuxIdMD5 = base64EncodedMD5( replyToAuxId );
00197 kd->strippedSubjectMD5 = base64EncodedMD5( KMMessage::stripOffPrefixes( kd->subject ), true );
00198 kd->msgIdMD5 = base64EncodedMD5( msgId );
00199 kd->xmark = aXMark;
00200 kd->folderOffset = aFolderOffset;
00201 mStatus = aStatus;
00202 kd->msgSize = aMsgSize;
00203 kd->date = aDate;
00204 kd->file = "";
00205 kd->encryptionState = encryptionState;
00206 kd->signatureState = signatureState;
00207 kd->mdnSentState = mdnSentState;
00208 mDirty = FALSE;
00209 }
00210
00211 void KMMsgInfo::init(const QCString& aSubject, const QCString& aFrom,
00212 const QCString& aTo, time_t aDate,
00213 KMMsgStatus aStatus, const QCString& aXMark,
00214 const QCString& replyToId, const QCString& replyToAuxId,
00215 const QCString& msgId,
00216 const QCString& aFileName,
00217 KMMsgEncryptionState encryptionState,
00218 KMMsgSignatureState signatureState,
00219 KMMsgMDNSentState mdnSentState,
00220 unsigned long aMsgSize)
00221 {
00222
00223 init( aSubject, aFrom, aTo, aDate, aStatus, aXMark, replyToId, replyToAuxId,
00224 msgId, encryptionState, signatureState, mdnSentState,
00225 (unsigned long)0, aMsgSize );
00226 kd->file = aFileName;
00227 }
00228
00229
00230
00231 QString KMMsgInfo::subject(void) const
00232 {
00233 if (kd && kd->modifiers & KMMsgInfoPrivate::SUBJECT_SET)
00234 return kd->subject;
00235 return getStringPart(MsgSubjectPart);
00236 }
00237
00238
00239
00240 QString KMMsgInfo::fromStrip(void) const
00241 {
00242 if (kd && kd->modifiers & KMMsgInfoPrivate::FROM_SET)
00243 return kd->from;
00244 return getStringPart(MsgFromPart);
00245 }
00246
00247
00248 QString KMMsgInfo::fileName(void) const
00249 {
00250 if (kd && kd->modifiers & KMMsgInfoPrivate::FILE_SET)
00251 return kd->file;
00252 return getStringPart(MsgFilePart);
00253 }
00254
00255
00256
00257 QString KMMsgInfo::toStrip(void) const
00258 {
00259 if (kd && kd->modifiers & KMMsgInfoPrivate::TO_SET)
00260 return kd->to;
00261 return getStringPart(MsgToPart);
00262 }
00263
00264
00265 QString KMMsgInfo::xmark(void) const
00266 {
00267 if (kd && kd->modifiers & KMMsgInfoPrivate::XMARK_SET)
00268 return kd->xmark;
00269 return getStringPart(MsgXMarkPart);
00270 }
00271
00272
00273
00274 QString KMMsgInfo::replyToIdMD5(void) const
00275 {
00276 if (kd && kd->modifiers & KMMsgInfoPrivate::REPLYTO_SET)
00277 return kd->replyToIdMD5;
00278 return getStringPart(MsgReplyToIdMD5Part);
00279 }
00280
00281
00282 QString KMMsgInfo::replyToAuxIdMD5() const
00283 {
00284 if( kd && kd->modifiers & KMMsgInfoPrivate::REPLYTOAUX_SET )
00285 return kd->replyToAuxIdMD5;
00286 return getStringPart( MsgReplyToAuxIdMD5Part );
00287 }
00288
00289
00290 QString KMMsgInfo::strippedSubjectMD5() const
00291 {
00292 if( kd && kd->modifiers & KMMsgInfoPrivate::STRIPPEDSUBJECT_SET )
00293 return kd->strippedSubjectMD5;
00294 return getStringPart( MsgStrippedSubjectMD5Part );
00295 }
00296
00297
00298
00299 bool KMMsgInfo::subjectIsPrefixed() const
00300 {
00301 return strippedSubjectMD5() != base64EncodedMD5( subject().stripWhiteSpace(), true );
00302 }
00303
00304
00305 QString KMMsgInfo::msgIdMD5(void) const
00306 {
00307 if (kd && kd->modifiers & KMMsgInfoPrivate::MSGID_SET)
00308 return kd->msgIdMD5;
00309 return getStringPart(MsgIdMD5Part);
00310 }
00311
00312
00313
00314 void KMMsgInfo::setSubject(const QString& aSubject)
00315 {
00316 if(aSubject == subject())
00317 return;
00318
00319 if (!kd)
00320 kd = new KMMsgInfoPrivate;
00321 kd->modifiers |= KMMsgInfoPrivate::SUBJECT_SET;
00322 kd->subject = aSubject;
00323 mDirty = TRUE;
00324 }
00325
00326
00327
00328 void KMMsgInfo::setXMark(const QString& aXMark)
00329 {
00330 if (aXMark == xmark())
00331 return;
00332
00333 if (!kd)
00334 kd = new KMMsgInfoPrivate;
00335 kd->modifiers |= KMMsgInfoPrivate::XMARK_SET;
00336 kd->xmark = aXMark;
00337 mDirty = TRUE;
00338 }
00339
00340
00341
00342 void KMMsgInfo::setReplyToIdMD5(const QString& aReplyToIdMD5)
00343 {
00344 if (aReplyToIdMD5 == replyToIdMD5())
00345 return;
00346
00347 if (!kd)
00348 kd = new KMMsgInfoPrivate;
00349 kd->modifiers |= KMMsgInfoPrivate::REPLYTO_SET;
00350 kd->replyToIdMD5 = aReplyToIdMD5;
00351 mDirty = TRUE;
00352 }
00353
00354
00355
00356 void KMMsgInfo::setReplyToAuxIdMD5( const QString& aReplyToAuxIdMD5 )
00357 {
00358 if( aReplyToAuxIdMD5 == replyToAuxIdMD5() )
00359 return;
00360
00361 if( !kd )
00362 kd = new KMMsgInfoPrivate;
00363 kd->modifiers |= KMMsgInfoPrivate::REPLYTOAUX_SET;
00364 kd->replyToAuxIdMD5 = aReplyToAuxIdMD5;
00365 mDirty = TRUE;
00366 }
00367
00368
00369
00370 void KMMsgInfo::initStrippedSubjectMD5()
00371 {
00372 if( kd && kd->modifiers & KMMsgInfoPrivate::STRIPPEDSUBJECT_SET )
00373 return;
00374 QString rawSubject = KMMessage::stripOffPrefixes( subject() );
00375 QString subjectMD5 = base64EncodedMD5( rawSubject, true );
00376 if( !kd )
00377 kd = new KMMsgInfoPrivate;
00378 kd->modifiers |= KMMsgInfoPrivate::STRIPPEDSUBJECT_SET;
00379 kd->strippedSubjectMD5 = subjectMD5;
00380 mDirty = TRUE;
00381 }
00382
00383
00384
00385 void KMMsgInfo::setMsgIdMD5(const QString& aMsgIdMD5)
00386 {
00387 if (aMsgIdMD5 == msgIdMD5())
00388 return;
00389
00390 if (!kd)
00391 kd = new KMMsgInfoPrivate;
00392 kd->modifiers |= KMMsgInfoPrivate::MSGID_SET;
00393 kd->msgIdMD5 = aMsgIdMD5;
00394 mDirty = TRUE;
00395 }
00396
00397
00398 void KMMsgInfo::setEncryptionState( const KMMsgEncryptionState s, int idx )
00399 {
00400 if (s == encryptionState())
00401 return;
00402
00403 if (!kd)
00404 kd = new KMMsgInfoPrivate;
00405 kd->modifiers |= KMMsgInfoPrivate::ENCRYPTION_SET;
00406 kd->encryptionState = s;
00407 KMMsgBase::setEncryptionState(s, idx);
00408 mDirty = TRUE;
00409 }
00410
00411
00412 void KMMsgInfo::setSignatureState( const KMMsgSignatureState s, int idx )
00413 {
00414 if (s == signatureState())
00415 return;
00416
00417 if (!kd)
00418 kd = new KMMsgInfoPrivate;
00419 kd->modifiers |= KMMsgInfoPrivate::SIGNATURE_SET;
00420 kd->signatureState = s;
00421 KMMsgBase::setSignatureState(s, idx);
00422 mDirty = TRUE;
00423 }
00424
00425
00426 void KMMsgInfo::setMDNSentState( const KMMsgMDNSentState s, int idx )
00427 {
00428 if (s == mdnSentState())
00429 return;
00430
00431 if (!kd)
00432 kd = new KMMsgInfoPrivate;
00433 kd->modifiers |= KMMsgInfoPrivate::MDN_SET;
00434 kd->mdnSentState = s;
00435 KMMsgBase::setMDNSentState(s, idx);
00436 mDirty = TRUE;
00437 }
00438
00439
00440 KMMsgStatus KMMsgInfo::status(void) const
00441 {
00442 if (mStatus == KMMsgStatusUnknown) {
00443 KMMsgStatus st = (KMMsgStatus)getLongPart(MsgStatusPart);
00444 if (!st) {
00445
00446
00447 mLegacyStatus = (KMLegacyMsgStatus)getLongPart(MsgLegacyStatusPart);
00448 st = KMMsgStatusRead;
00449 switch (mLegacyStatus) {
00450 case KMLegacyMsgStatusUnknown:
00451 st = KMMsgStatusUnknown;
00452 break;
00453 case KMLegacyMsgStatusNew:
00454 st = KMMsgStatusNew;
00455 break;
00456 case KMLegacyMsgStatusUnread:
00457 st = KMMsgStatusUnread;
00458 break;
00459 case KMLegacyMsgStatusRead:
00460 st = KMMsgStatusRead;
00461 break;
00462 case KMLegacyMsgStatusOld:
00463 st = KMMsgStatusOld;
00464 break;
00465 case KMLegacyMsgStatusDeleted:
00466 st |= KMMsgStatusDeleted;
00467 break;
00468 case KMLegacyMsgStatusReplied:
00469 st |= KMMsgStatusReplied;
00470 break;
00471 case KMLegacyMsgStatusForwarded:
00472 st |= KMMsgStatusForwarded;
00473 break;
00474 case KMLegacyMsgStatusQueued:
00475 st |= KMMsgStatusQueued;
00476 break;
00477 case KMLegacyMsgStatusSent:
00478 st |= KMMsgStatusSent;
00479 break;
00480 case KMLegacyMsgStatusFlag:
00481 st |= KMMsgStatusFlag;
00482 break;
00483 default:
00484 break;
00485 }
00486
00487 }
00488 mStatus = st;
00489 }
00490 return mStatus;
00491 }
00492
00493
00494
00495 KMMsgEncryptionState KMMsgInfo::encryptionState() const
00496 {
00497 if (kd && kd->modifiers & KMMsgInfoPrivate::ENCRYPTION_SET)
00498 return kd->encryptionState;
00499 unsigned long encState = getLongPart(MsgCryptoStatePart) & 0x0000FFFF;
00500 return encState ? (KMMsgEncryptionState)encState : KMMsgEncryptionStateUnknown;
00501 }
00502
00503
00504 KMMsgSignatureState KMMsgInfo::signatureState() const
00505 {
00506 if (kd && kd->modifiers & KMMsgInfoPrivate::SIGNATURE_SET)
00507 return kd->signatureState;
00508 unsigned long sigState = getLongPart(MsgCryptoStatePart) >> 16;
00509 return sigState ? (KMMsgSignatureState)sigState : KMMsgSignatureStateUnknown;
00510 }
00511
00512 KMMsgMDNSentState KMMsgInfo::mdnSentState() const {
00513 if (kd && kd->modifiers & KMMsgInfoPrivate::MDN_SET)
00514 return kd->mdnSentState;
00515 unsigned long mdnState = getLongPart(MsgMDNSentPart);
00516 return mdnState ? (KMMsgMDNSentState)mdnState : KMMsgMDNStateUnknown;
00517 }
00518
00519
00520
00521 off_t KMMsgInfo::folderOffset(void) const
00522 {
00523 if (kd && kd->modifiers & KMMsgInfoPrivate::OFFSET_SET)
00524 return kd->folderOffset;
00525 return getLongPart(MsgOffsetPart);
00526 }
00527
00528
00529 size_t KMMsgInfo::msgSize(void) const
00530 {
00531 if (kd && kd->modifiers & KMMsgInfoPrivate::SIZE_SET)
00532 return kd->msgSize;
00533 return getLongPart(MsgSizePart);
00534 }
00535
00536
00537 time_t KMMsgInfo::date(void) const
00538 {
00539 time_t res;
00540 if (kd && kd->modifiers & KMMsgInfoPrivate::DATE_SET)
00541 res = kd->date;
00542 else
00543 res = getLongPart(MsgDatePart);
00544 return res;
00545 }
00546
00547
00548 void KMMsgInfo::setMsgSize(size_t sz)
00549 {
00550 if (sz == msgSize())
00551 return;
00552
00553 if(!kd)
00554 kd = new KMMsgInfoPrivate;
00555 kd->modifiers |= KMMsgInfoPrivate::SIZE_SET;
00556 kd->msgSize = sz;
00557 mDirty = TRUE;
00558 }
00559
00560
00561 void KMMsgInfo::setFolderOffset(off_t offs)
00562 {
00563 if (folderOffset() == offs)
00564 return;
00565
00566 if (!kd)
00567 kd = new KMMsgInfoPrivate;
00568 kd->modifiers |= KMMsgInfoPrivate::OFFSET_SET;
00569 kd->folderOffset = offs;
00570 mDirty = TRUE;
00571 }
00572
00573
00574 void KMMsgInfo::setFileName(const QString& file)
00575 {
00576 if (fileName() == file)
00577 return;
00578
00579 if (!kd)
00580 kd = new KMMsgInfoPrivate;
00581 kd->modifiers |= KMMsgInfoPrivate::FILE_SET;
00582 kd->file = file;
00583 mDirty = TRUE;
00584 }
00585
00586
00587 void KMMsgInfo::setStatus(const KMMsgStatus aStatus, int idx)
00588 {
00589 if(aStatus == status())
00590 return;
00591 KMMsgBase::setStatus(aStatus, idx);
00592 }
00593
00594
00595 void KMMsgInfo::setDate(time_t aUnixTime)
00596 {
00597 if(aUnixTime == date())
00598 return;
00599
00600 if(!kd)
00601 kd = new KMMsgInfoPrivate;
00602 kd->modifiers |= KMMsgInfoPrivate::DATE_SET;
00603 kd->date = aUnixTime;
00604 mDirty = TRUE;
00605 }
00606
00607
00608 void KMMsgInfo::compat_fromOldIndexString(const QCString& str, bool toUtf8)
00609 {
00610 char *start, *offset;
00611
00612 if(!kd)
00613 kd = new KMMsgInfoPrivate;
00614 kd->modifiers = KMMsgInfoPrivate::ALL_SET;
00615 kd->xmark = str.mid(33, 3).stripWhiteSpace();
00616 kd->folderOffset = str.mid(2,9).toULong();
00617 kd->msgSize = str.mid(12,9).toULong();
00618 kd->date = (time_t)str.mid(22,10).toULong();
00619 mStatus = (KMMsgStatus)str.at(0);
00620 if (toUtf8) {
00621 kd->subject = str.mid(37, 100).stripWhiteSpace();
00622 kd->from = str.mid(138, 50).stripWhiteSpace();
00623 kd->to = str.mid(189, 50).stripWhiteSpace();
00624 } else {
00625 start = offset = str.data() + 37;
00626 while (*start == ' ' && start - offset < 100) start++;
00627 kd->subject = QString::fromUtf8(str.mid(start - str.data(),
00628 100 - (start - offset)), 100 - (start - offset));
00629 start = offset = str.data() + 138;
00630 while (*start == ' ' && start - offset < 50) start++;
00631 kd->from = QString::fromUtf8(str.mid(start - str.data(),
00632 50 - (start - offset)), 50 - (start - offset));
00633 start = offset = str.data() + 189;
00634 while (*start == ' ' && start - offset < 50) start++;
00635 kd->to = QString::fromUtf8(str.mid(start - str.data(),
00636 50 - (start - offset)), 50 - (start - offset));
00637 }
00638 kd->replyToIdMD5 = str.mid(240, 22).stripWhiteSpace();
00639 kd->msgIdMD5 = str.mid(263, 22).stripWhiteSpace();
00640 mDirty = FALSE;
00641 }
00642
00643 bool KMMsgInfo::dirty(void) const
00644 {
00645 if(KMMsgBase::dirty())
00646 return TRUE;
00647 return kd && kd->modifiers != KMMsgInfoPrivate::NONE_SET;
00648 }