kmail Library API Documentation

kmmsgbase.cpp

00001 // kmmsgbase.cpp 00002 00003 #include <config.h> 00004 00005 #include "kmmsgbase.h" 00006 00007 #include "kmfolderindex.h" 00008 #include "kmheaders.h" 00009 #include "kmmsgdict.h" 00010 #include "messageproperty.h" 00011 using KMail::MessageProperty; 00012 00013 #include <kdebug.h> 00014 #include <kglobal.h> 00015 #include <kcharsets.h> 00016 #include <kmdcodec.h> 00017 #include <krfcdate.h> 00018 00019 #include <mimelib/mimepp.h> 00020 #include <kmime_codecs.h> 00021 00022 #include <qtextcodec.h> 00023 #include <qdeepcopy.h> 00024 00025 #include <ctype.h> 00026 #include <stdlib.h> 00027 #include <unistd.h> 00028 00029 #ifdef HAVE_BYTESWAP_H 00030 #include <byteswap.h> 00031 #endif 00032 00033 // We define functions as kmail_swap_NN so that we don't get compile errors 00034 // on platforms where bswap_NN happens to be a function instead of a define. 00035 00036 /* Swap bytes in 16 bit value. */ 00037 #ifdef bswap_16 00038 #define kmail_swap_16(x) bswap_16(x) 00039 #else 00040 #define kmail_swap_16(x) \ 00041 ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) 00042 #endif 00043 00044 /* Swap bytes in 32 bit value. */ 00045 #ifdef bswap_32 00046 #define kmail_swap_32(x) bswap_32(x) 00047 #else 00048 #define kmail_swap_32(x) \ 00049 ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ 00050 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) 00051 #endif 00052 00053 /* Swap bytes in 64 bit value. */ 00054 #ifdef bswap_64 00055 #define kmail_swap_64(x) bswap_64(x) 00056 #else 00057 #define kmail_swap_64(x) \ 00058 ((((x) & 0xff00000000000000ull) >> 56) \ 00059 | (((x) & 0x00ff000000000000ull) >> 40) \ 00060 | (((x) & 0x0000ff0000000000ull) >> 24) \ 00061 | (((x) & 0x000000ff00000000ull) >> 8) \ 00062 | (((x) & 0x00000000ff000000ull) << 8) \ 00063 | (((x) & 0x0000000000ff0000ull) << 24) \ 00064 | (((x) & 0x000000000000ff00ull) << 40) \ 00065 | (((x) & 0x00000000000000ffull) << 56)) 00066 #endif 00067 00068 //----------------------------------------------------------------------------- 00069 KMMsgBase::KMMsgBase(KMFolderIndex* aParent) 00070 { 00071 mParent = aParent; 00072 mDirty = FALSE; 00073 mIndexOffset = 0; 00074 mIndexLength = 0; 00075 mStatus = KMMsgStatusUnknown; 00076 mEnableUndo = false; 00077 } 00078 00079 00080 //----------------------------------------------------------------------------- 00081 KMMsgBase::~KMMsgBase() 00082 { 00083 MessageProperty::forget( this ); 00084 } 00085 00086 00087 //----------------------------------------------------------------------------- 00088 void KMMsgBase::assign(const KMMsgBase* other) 00089 { 00090 mParent = other->mParent; 00091 mDirty = other->mDirty; 00092 mIndexOffset = other->mIndexOffset; 00093 mIndexLength = other->mIndexLength; 00094 MessageProperty::forget( this ); 00095 bool otherTransfer = MessageProperty::transferInProgress( other ); 00096 MessageProperty::setTransferInProgress( this, otherTransfer ); 00097 } 00098 00099 00100 //----------------------------------------------------------------------------- 00101 KMMsgBase& KMMsgBase::operator=(const KMMsgBase& other) 00102 { 00103 assign(&other); 00104 return *this; 00105 } 00106 00107 00108 //---------------------------------------------------------------------------- 00109 KMMsgBase::KMMsgBase( const KMMsgBase& other ) 00110 { 00111 assign( &other ); 00112 } 00113 00114 00115 //----------------------------------------------------------------------------- 00116 bool KMMsgBase::isMessage(void) const 00117 { 00118 return FALSE; 00119 } 00120 //----------------------------------------------------------------------------- 00121 void KMMsgBase::toggleStatus(const KMMsgStatus aStatus, int idx) 00122 { 00123 mDirty = true; 00124 KMMsgStatus oldStatus = status(); 00125 if ( status() & aStatus ) { 00126 mStatus &= ~aStatus; 00127 } else { 00128 mStatus |= aStatus; 00129 // Ignored and Watched are toggleable, yet mutually exclusive. 00130 // That is an arbitrary restriction on my part. HAR HAR HAR :) -till 00131 if (aStatus == KMMsgStatusWatched) 00132 mStatus &= ~KMMsgStatusIgnored; 00133 if (aStatus == KMMsgStatusIgnored) { 00134 mStatus &= ~KMMsgStatusWatched; 00135 setStatus(KMMsgStatusRead, idx); 00136 } 00137 if (aStatus == KMMsgStatusSpam) 00138 mStatus &= ~KMMsgStatusHam; 00139 if (aStatus == KMMsgStatusHam) 00140 mStatus &= ~KMMsgStatusSpam; 00141 } 00142 if (mParent) { 00143 if (idx < 0) 00144 idx = mParent->find( this ); 00145 mParent->msgStatusChanged( oldStatus, status(), idx ); 00146 mParent->headerOfMsgChanged(this, idx); 00147 } 00148 00149 } 00150 00151 //----------------------------------------------------------------------------- 00152 void KMMsgBase::setStatus(const KMMsgStatus aStatus, int idx) 00153 { 00154 mDirty = TRUE; 00155 KMMsgStatus oldStatus = status(); 00156 switch (aStatus) { 00157 case KMMsgStatusRead: 00158 // Unset unread and new, set read 00159 mStatus &= ~KMMsgStatusUnread; 00160 mStatus &= ~KMMsgStatusNew; 00161 mStatus |= KMMsgStatusRead; 00162 break; 00163 00164 case KMMsgStatusUnread: 00165 // unread overrides read 00166 mStatus &= ~KMMsgStatusOld; 00167 mStatus &= ~KMMsgStatusRead; 00168 mStatus &= ~KMMsgStatusNew; 00169 mStatus |= KMMsgStatusUnread; 00170 break; 00171 00172 case KMMsgStatusOld: 00173 // old can't be new or unread 00174 mStatus &= ~KMMsgStatusNew; 00175 mStatus &= ~KMMsgStatusUnread; 00176 mStatus |= KMMsgStatusOld; 00177 break; 00178 00179 case KMMsgStatusNew: 00180 // new overrides old and read 00181 mStatus &= ~KMMsgStatusOld; 00182 mStatus &= ~KMMsgStatusRead; 00183 mStatus &= ~KMMsgStatusUnread; 00184 mStatus |= KMMsgStatusNew; 00185 break; 00186 00187 case KMMsgStatusDeleted: 00188 mStatus |= KMMsgStatusDeleted; 00189 break; 00190 00191 case KMMsgStatusReplied: 00192 mStatus |= KMMsgStatusReplied; 00193 break; 00194 00195 case KMMsgStatusForwarded: 00196 mStatus |= KMMsgStatusForwarded; 00197 break; 00198 00199 case KMMsgStatusQueued: 00200 mStatus |= KMMsgStatusQueued; 00201 break; 00202 00203 case KMMsgStatusSent: 00204 mStatus &= ~KMMsgStatusQueued; 00205 mStatus &= ~KMMsgStatusUnread; 00206 mStatus &= ~KMMsgStatusNew; 00207 mStatus |= KMMsgStatusSent; 00208 break; 00209 00210 case KMMsgStatusFlag: 00211 mStatus |= KMMsgStatusFlag; 00212 break; 00213 00214 // Watched and ignored are mutually exclusive 00215 case KMMsgStatusWatched: 00216 mStatus &= ~KMMsgStatusIgnored; 00217 mStatus |= KMMsgStatusWatched; 00218 break; 00219 00220 case KMMsgStatusIgnored: 00221 mStatus &= ~KMMsgStatusWatched; 00222 mStatus |= KMMsgStatusIgnored; 00223 break; 00224 // as are ham and spam 00225 case KMMsgStatusSpam: 00226 mStatus &= ~KMMsgStatusHam; 00227 mStatus |= KMMsgStatusSpam; 00228 break; 00229 case KMMsgStatusHam: 00230 mStatus &= ~KMMsgStatusSpam; 00231 mStatus |= KMMsgStatusHam; 00232 break; 00233 default: 00234 mStatus = aStatus; 00235 break; 00236 } 00237 00238 if (mParent) { 00239 if (idx < 0) 00240 idx = mParent->find( this ); 00241 mParent->msgStatusChanged( oldStatus, status(), idx ); 00242 mParent->headerOfMsgChanged( this, idx ); 00243 } 00244 } 00245 00246 00247 00248 //----------------------------------------------------------------------------- 00249 void KMMsgBase::setStatus(const char* aStatusStr, const char* aXStatusStr) 00250 { 00251 // first try to find status from "X-Status" field if given 00252 if (aXStatusStr) { 00253 if (strchr(aXStatusStr, 'N')) setStatus(KMMsgStatusNew); 00254 if (strchr(aXStatusStr, 'U')) setStatus(KMMsgStatusUnread); 00255 if (strchr(aXStatusStr, 'O')) setStatus(KMMsgStatusOld); 00256 if (strchr(aXStatusStr, 'R')) setStatus(KMMsgStatusRead); 00257 if (strchr(aXStatusStr, 'D')) setStatus(KMMsgStatusDeleted); 00258 if (strchr(aXStatusStr, 'A')) setStatus(KMMsgStatusReplied); 00259 if (strchr(aXStatusStr, 'F')) setStatus(KMMsgStatusForwarded); 00260 if (strchr(aXStatusStr, 'Q')) setStatus(KMMsgStatusQueued); 00261 if (strchr(aXStatusStr, 'S')) setStatus(KMMsgStatusSent); 00262 if (strchr(aXStatusStr, 'G')) setStatus(KMMsgStatusFlag); 00263 if (strchr(aXStatusStr, 'P')) setStatus(KMMsgStatusSpam); 00264 if (strchr(aXStatusStr, 'H')) setStatus(KMMsgStatusHam); 00265 } 00266 00267 // Merge the contents of the "Status" field 00268 if (aStatusStr) { 00269 if ((aStatusStr[0]== 'R' && aStatusStr[1]== 'O') || 00270 (aStatusStr[0]== 'O' && aStatusStr[1]== 'R')) { 00271 setStatus( KMMsgStatusOld ); 00272 setStatus( KMMsgStatusRead ); 00273 } 00274 else if (aStatusStr[0] == 'R') 00275 setStatus(KMMsgStatusRead); 00276 else if (aStatusStr[0] == 'D') 00277 setStatus(KMMsgStatusDeleted); 00278 else 00279 setStatus(KMMsgStatusNew); 00280 } 00281 } 00282 00283 00284 void KMMsgBase::setEncryptionState( const KMMsgEncryptionState status, int idx ) 00285 { 00286 kdDebug(5006) << "***setEncryptionState1( " << status << " )" << endl; 00287 mDirty = TRUE; 00288 if (mParent) 00289 mParent->headerOfMsgChanged(this, idx); 00290 } 00291 00292 void KMMsgBase::setEncryptionStateChar( QChar status, int idx ) 00293 { 00294 kdDebug(5006) << "***setEncryptionState2( " << (status.isNull() ? '?' : status.latin1()) << " )" << endl; 00295 00296 if( status.latin1() == (char)KMMsgEncryptionStateUnknown ) 00297 setEncryptionState( KMMsgEncryptionStateUnknown, idx ); 00298 else if( status.latin1() == (char)KMMsgNotEncrypted ) 00299 setEncryptionState( KMMsgNotEncrypted, idx ); 00300 else if( status.latin1() == (char)KMMsgPartiallyEncrypted ) 00301 setEncryptionState( KMMsgPartiallyEncrypted, idx ); 00302 else if( status.latin1() == (char)KMMsgFullyEncrypted ) 00303 setEncryptionState( KMMsgFullyEncrypted, idx ); 00304 else 00305 setEncryptionState( KMMsgEncryptionStateUnknown, idx ); 00306 } 00307 00308 00309 void KMMsgBase::setSignatureState( const KMMsgSignatureState status, int idx ) 00310 { 00311 kdDebug(5006) << "***setSignatureState1( " << status << " )" << endl; 00312 mDirty = TRUE; 00313 if (mParent) 00314 mParent->headerOfMsgChanged(this, idx); 00315 } 00316 00317 void KMMsgBase::setMDNSentState( KMMsgMDNSentState, int idx ) { 00318 mDirty = true; 00319 if ( mParent ) 00320 mParent->headerOfMsgChanged(this, idx); 00321 } 00322 00323 void KMMsgBase::setSignatureStateChar( QChar status, int idx ) 00324 { 00325 kdDebug(5006) << "***setSignatureState2( " << (status.isNull() ? '?' : status.latin1()) << " )" << endl; 00326 00327 if( status.latin1() == (char)KMMsgSignatureStateUnknown ) 00328 setSignatureState( KMMsgSignatureStateUnknown, idx ); 00329 else if( status.latin1() == (char)KMMsgNotSigned ) 00330 setSignatureState( KMMsgNotSigned, idx ); 00331 else if( status.latin1() == (char)KMMsgPartiallySigned ) 00332 setSignatureState( KMMsgPartiallySigned,idx ); 00333 else if( status.latin1() == (char)KMMsgFullySigned ) 00334 setSignatureState( KMMsgFullySigned, idx ); 00335 else 00336 setSignatureState( KMMsgSignatureStateUnknown, idx ); 00337 } 00338 00339 //----------------------------------------------------------------------------- 00340 bool KMMsgBase::isUnread(void) const 00341 { 00342 KMMsgStatus st = status(); 00343 return (st & KMMsgStatusUnread); 00344 } 00345 00346 //----------------------------------------------------------------------------- 00347 bool KMMsgBase::isNew(void) const 00348 { 00349 KMMsgStatus st = status(); 00350 return (st & KMMsgStatusNew); 00351 } 00352 00353 //----------------------------------------------------------------------------- 00354 bool KMMsgBase::isOfUnknownStatus(void) const 00355 { 00356 KMMsgStatus st = status(); 00357 return (st == KMMsgStatusUnknown); 00358 } 00359 00360 //----------------------------------------------------------------------------- 00361 bool KMMsgBase::isOld(void) const 00362 { 00363 KMMsgStatus st = status(); 00364 return (st & KMMsgStatusOld); 00365 } 00366 00367 //----------------------------------------------------------------------------- 00368 bool KMMsgBase::isRead(void) const 00369 { 00370 KMMsgStatus st = status(); 00371 return (st & KMMsgStatusRead); 00372 } 00373 00374 //----------------------------------------------------------------------------- 00375 bool KMMsgBase::isDeleted(void) const 00376 { 00377 KMMsgStatus st = status(); 00378 return (st & KMMsgStatusDeleted); 00379 } 00380 00381 //----------------------------------------------------------------------------- 00382 bool KMMsgBase::isReplied(void) const 00383 { 00384 KMMsgStatus st = status(); 00385 return (st & KMMsgStatusReplied); 00386 } 00387 00388 //----------------------------------------------------------------------------- 00389 bool KMMsgBase::isForwarded(void) const 00390 { 00391 KMMsgStatus st = status(); 00392 return (st & KMMsgStatusForwarded); 00393 } 00394 00395 //----------------------------------------------------------------------------- 00396 bool KMMsgBase::isQueued(void) const 00397 { 00398 KMMsgStatus st = status(); 00399 return (st & KMMsgStatusQueued); 00400 } 00401 00402 //----------------------------------------------------------------------------- 00403 bool KMMsgBase::isSent(void) const 00404 { 00405 KMMsgStatus st = status(); 00406 return (st & KMMsgStatusSent); 00407 } 00408 00409 //----------------------------------------------------------------------------- 00410 bool KMMsgBase::isFlag(void) const 00411 { 00412 KMMsgStatus st = status(); 00413 return (st & KMMsgStatusFlag); 00414 } 00415 00416 //----------------------------------------------------------------------------- 00417 bool KMMsgBase::isWatched(void) const 00418 { 00419 KMMsgStatus st = status(); 00420 return (st & KMMsgStatusWatched); 00421 } 00422 00423 //----------------------------------------------------------------------------- 00424 bool KMMsgBase::isIgnored(void) const 00425 { 00426 KMMsgStatus st = status(); 00427 return (st & KMMsgStatusIgnored); 00428 } 00429 00430 //----------------------------------------------------------------------------- 00431 bool KMMsgBase::isSpam(void) const 00432 { 00433 KMMsgStatus st = status(); 00434 return (st & KMMsgStatusSpam); 00435 } 00436 00437 //----------------------------------------------------------------------------- 00438 bool KMMsgBase::isHam(void) const 00439 { 00440 KMMsgStatus st = status(); 00441 return (st & KMMsgStatusHam); 00442 } 00443 00444 //----------------------------------------------------------------------------- 00445 QCString KMMsgBase::statusToStr(const KMMsgStatus status) 00446 { 00447 QCString sstr; 00448 if (status & KMMsgStatusNew) sstr += 'N'; 00449 if (status & KMMsgStatusUnread) sstr += 'U'; 00450 if (status & KMMsgStatusOld) sstr += 'O'; 00451 if (status & KMMsgStatusRead) sstr += 'R'; 00452 if (status & KMMsgStatusDeleted) sstr += 'D'; 00453 if (status & KMMsgStatusReplied) sstr += 'A'; 00454 if (status & KMMsgStatusForwarded) sstr += 'F'; 00455 if (status & KMMsgStatusQueued) sstr += 'Q'; 00456 if (status & KMMsgStatusSent) sstr += 'S'; 00457 if (status & KMMsgStatusFlag) sstr += 'G'; 00458 if (status & KMMsgStatusWatched) sstr += 'W'; 00459 if (status & KMMsgStatusIgnored) sstr += 'I'; 00460 if (status & KMMsgStatusSpam) sstr += 'P'; 00461 if (status & KMMsgStatusHam) sstr += 'H'; 00462 00463 return sstr; 00464 } 00465 00466 //----------------------------------------------------------------------------- 00467 QString KMMsgBase::statusToSortRank() 00468 { 00469 QString sstr = "bcbbbbbbb"; 00470 00471 // put watched ones first, then normal ones, ignored ones last 00472 if (status() & KMMsgStatusWatched) sstr[0] = 'a'; 00473 if (status() & KMMsgStatusIgnored) sstr[0] = 'c'; 00474 00475 // Second level. One of new, old, read, unread 00476 if (status() & KMMsgStatusNew) sstr[1] = 'a'; 00477 if (status() & KMMsgStatusUnread) sstr[1] = 'b'; 00478 //if (status() & KMMsgStatusOld) sstr[1] = 'c'; 00479 //if (status() & KMMsgStatusRead) sstr[1] = 'c'; 00480 00481 // Third level. In somewhat arbitrary order. 00482 if (status() & KMMsgStatusDeleted) sstr[2] = 'a'; 00483 if (status() & KMMsgStatusFlag) sstr[3] = 'a'; 00484 if (status() & KMMsgStatusReplied) sstr[4] = 'a'; 00485 if (status() & KMMsgStatusForwarded) sstr[5] = 'a'; 00486 if (status() & KMMsgStatusQueued) sstr[6] = 'a'; 00487 if (status() & KMMsgStatusSent) sstr[7] = 'a'; 00488 if (status() & KMMsgStatusHam) sstr[8] = 'a'; 00489 if (status() & KMMsgStatusSpam) sstr[8] = 'c'; 00490 00491 return sstr; 00492 } 00493 00494 00495 //----------------------------------------------------------------------------- 00496 void KMMsgBase::setDate(const QCString& aDateStr) 00497 { 00498 setDate( KRFCDate::parseDate( aDateStr ) ); 00499 } 00500 00501 00502 //----------------------------------------------------------------------------- 00503 QString KMMsgBase::dateStr(void) const 00504 { 00505 time_t d = date(); 00506 return KMime::DateFormatter::formatDate(KMime::DateFormatter::Fancy, d); 00507 } 00508 00509 00510 //----------------------------------------------------------------------------- 00511 QString KMMsgBase::skipKeyword(const QString& aStr, QChar sepChar, 00512 bool* hasKeyword) 00513 { 00514 unsigned int i = 0, maxChars = 3; 00515 QString str = aStr; 00516 00517 while (str[0] == ' ') str.remove(0,1); 00518 if (hasKeyword) *hasKeyword=FALSE; 00519 00520 for (i=0; i < str.length() && i < maxChars; i++) 00521 { 00522 if (str[i] < 'A' || str[i] == sepChar) break; 00523 } 00524 00525 if (str[i] == sepChar) // skip following spaces too 00526 { 00527 do { 00528 i++; 00529 } while (str[i] == ' '); 00530 if (hasKeyword) *hasKeyword=TRUE; 00531 return str.mid(i); 00532 } 00533 return str; 00534 } 00535 00536 00537 //----------------------------------------------------------------------------- 00538 const QTextCodec* KMMsgBase::codecForName(const QCString& _str) 00539 { 00540 if (_str.isEmpty()) return 0; 00541 return KGlobal::charsets()->codecForName(_str.lower()); 00542 } 00543 00544 00545 //----------------------------------------------------------------------------- 00546 QCString KMMsgBase::toUsAscii(const QString& _str, bool *ok) 00547 { 00548 bool all_ok =true; 00549 QString result = _str; 00550 int len = result.length(); 00551 for (int i = 0; i < len; i++) 00552 if (result.at(i).unicode() >= 128) { 00553 result.at(i) = '?'; 00554 all_ok = false; 00555 } 00556 if (ok) 00557 *ok = all_ok; 00558 return result.latin1(); 00559 } 00560 00561 00562 //----------------------------------------------------------------------------- 00563 QStringList KMMsgBase::supportedEncodings(bool usAscii) 00564 { 00565 QStringList encodingNames = KGlobal::charsets()->availableEncodingNames(); 00566 QStringList encodings; 00567 QMap<QString,bool> mimeNames; 00568 for (QStringList::Iterator it = encodingNames.begin(); 00569 it != encodingNames.end(); it++) 00570 { 00571 QTextCodec *codec = KGlobal::charsets()->codecForName(*it); 00572 QString mimeName = (codec) ? QString(codec->mimeName()).lower() : (*it); 00573 if (mimeNames.find(mimeName) == mimeNames.end()) 00574 { 00575 encodings.append(KGlobal::charsets()->languageForEncoding(*it) 00576 + " ( " + mimeName + " )"); 00577 mimeNames.insert(mimeName, TRUE); 00578 } 00579 } 00580 encodings.sort(); 00581 if (usAscii) encodings.prepend(KGlobal::charsets() 00582 ->languageForEncoding("us-ascii") + " ( us-ascii )"); 00583 return encodings; 00584 } 00585 00586 namespace { 00587 // don't rely on isblank(), which is a GNU extension in 00588 // <cctype>. But if someone wants to write a configure test for 00589 // isblank(), we can then rename this function to isblank and #ifdef 00590 // it's definition... 00591 inline bool isBlank( char ch ) { return ch == ' ' || ch == '\t' ; } 00592 00593 QCString unfold( const QCString & header ) { 00594 if ( header.isEmpty() ) 00595 return QCString(); 00596 00597 QCString result( header.size() ); // size() >= length()+1 and size() is O(1) 00598 char * d = result.data(); 00599 00600 for ( const char * s = header.data() ; *s ; ) 00601 if ( *s == '\r' ) { // ignore 00602 ++s; 00603 continue; 00604 } else if ( *s == '\n' ) { // unfold 00605 while ( isBlank( *++s ) ); 00606 *d++ = ' '; 00607 } else 00608 *d++ = *s++; 00609 00610 *d++ = '\0'; 00611 00612 result.truncate( d - result.data() ); 00613 return result; 00614 } 00615 } 00616 00617 00618 //----------------------------------------------------------------------------- 00619 QString KMMsgBase::decodeRFC2047String(const QCString& aStr) 00620 { 00621 if ( aStr.isEmpty() ) 00622 return QString::null; 00623 00624 const QCString str = unfold( aStr ); 00625 00626 if ( str.isEmpty() ) 00627 return QString::null; 00628 00629 if ( str.find( "=?" ) < 0 ) 00630 return kmkernel->networkCodec()->toUnicode( str ); 00631 00632 QString result; 00633 QCString LWSP_buffer; 00634 bool lastWasEncodedWord = false; 00635 static const int maxLen = 200; 00636 00637 for ( const char * pos = str.data() ; *pos ; ++pos ) { 00638 // collect LWSP after encoded-words, 00639 // because we might need to throw it out 00640 // (when the next word is an encoded-word) 00641 if ( lastWasEncodedWord && isBlank( pos[0] ) ) { 00642 LWSP_buffer += pos[0]; 00643 continue; 00644 } 00645 // verbatimly copy normal text 00646 if (pos[0]!='=' || pos[1]!='?') { 00647 result += LWSP_buffer + pos[0]; 00648 LWSP_buffer = 0; 00649 lastWasEncodedWord = FALSE; 00650 continue; 00651 } 00652 // found possible encoded-word 00653 const char * const beg = pos; 00654 { 00655 // parse charset name 00656 QCString charset; 00657 int i = 2; 00658 for (pos+=2; i<maxLen && (*pos!='?'&&(*pos==' '||ispunct(*pos)||isalnum(*pos))); ++i) { 00659 charset += *pos; 00660 pos++; 00661 } 00662 if (*pos!='?' || i<4 || i>=maxLen) 00663 goto invalid_encoded_word; 00664 00665 // get encoding and check delimiting question marks 00666 const char encoding[2] = { pos[1], '\0' }; 00667 if (pos[2]!='?' || (encoding[0]!='Q' && encoding[0]!='q' && 00668 encoding[0]!='B' && encoding[0]!='b')) 00669 goto invalid_encoded_word; 00670 pos+=3; i+=3; // skip ?x? 00671 const char * enc_start = pos; 00672 // search for end of encoded part 00673 while (i<maxLen && *pos && !(*pos=='?' && *(pos+1)=='=')) { 00674 i++; 00675 pos++; 00676 } 00677 if (i>=maxLen || !*pos) 00678 goto invalid_encoded_word; 00679 00680 // valid encoding: decode and throw away separating LWSP 00681 const KMime::Codec * c = KMime::Codec::codecForName( encoding ); 00682 kdFatal( !c, 5006 ) << "No \"" << encoding << "\" codec!?" << endl; 00683 00684 QByteArray in; in.setRawData( enc_start, pos - enc_start ); 00685 const QByteArray enc = c->decode( in ); 00686 in.resetRawData( enc_start, pos - enc_start ); 00687 00688 const QTextCodec * codec = codecForName(charset); 00689 if (!codec) codec = kmkernel->networkCodec(); 00690 result += codec->toUnicode(enc); 00691 lastWasEncodedWord = true; 00692 00693 ++pos; // eat '?' (for loop eats '=') 00694 LWSP_buffer = 0; 00695 } 00696 continue; 00697 invalid_encoded_word: 00698 // invalid encoding, keep separating LWSP. 00699 pos = beg; 00700 result += LWSP_buffer; 00701 result += "=?"; 00702 lastWasEncodedWord = false; 00703 LWSP_buffer = 0; 00704 } 00705 return result; 00706 } 00707 00708 00709 //----------------------------------------------------------------------------- 00710 static const QCString especials = "()<>@,;:\"/[]?.= \033"; 00711 00712 QCString KMMsgBase::encodeRFC2047Quoted( const QCString & s, bool base64 ) { 00713 const char * codecName = base64 ? "b" : "q" ; 00714 const KMime::Codec * codec = KMime::Codec::codecForName( codecName ); 00715 kdFatal( !codec, 5006 ) << "No \"" << codecName << "\" found!?" << endl; 00716 QByteArray in; in.setRawData( s.data(), s.length() ); 00717 const QByteArray result = codec->encode( in ); 00718 in.resetRawData( s.data(), s.length() ); 00719 return QCString( result.data(), result.size() + 1 ); 00720 } 00721 00722 QCString KMMsgBase::encodeRFC2047String(const QString& _str, 00723 const QCString& charset) 00724 { 00725 static const QString dontQuote = "\"()<>,@"; 00726 00727 if (_str.isEmpty()) return QCString(); 00728 if (charset == "us-ascii") return toUsAscii(_str); 00729 00730 QCString cset; 00731 if (charset.isEmpty()) cset = QCString(kmkernel->networkCodec()->mimeName()).lower(); 00732 else cset = charset; 00733 const QTextCodec *codec = codecForName(cset); 00734 if (!codec) codec = kmkernel->networkCodec(); 00735 00736 unsigned int nonAscii = 0; 00737 for (unsigned int i = 0; i < _str.length(); i++) 00738 if (_str.at(i).unicode() >= 128) nonAscii++; 00739 bool useBase64 = (nonAscii * 6 > _str.length()); 00740 00741 unsigned int start, stop, p, pos = 0, encLength; 00742 QCString result; 00743 bool breakLine = FALSE; 00744 const unsigned int maxLen = 75 - 7 - cset.length(); 00745 00746 while (pos < _str.length()) 00747 { 00748 start = pos; p = pos; 00749 while (p < _str.length()) 00750 { 00751 if (!breakLine && (_str.at(p) == ' ' || dontQuote.find(_str.at(p)) != -1)) 00752 start = p + 1; 00753 if (_str.at(p).unicode() >= 128 || _str.at(p).unicode() < 32) 00754 break; 00755 p++; 00756 } 00757 if (breakLine || p < _str.length()) 00758 { 00759 while (dontQuote.find(_str.at(start)) != -1) start++; 00760 stop = start; 00761 while (stop < _str.length() && dontQuote.find(_str.at(stop)) == -1) 00762 stop++; 00763 result += _str.mid(pos, start - pos).latin1(); 00764 encLength = encodeRFC2047Quoted(codec->fromUnicode(_str. 00765 mid(start, stop - start)), useBase64).length(); 00766 breakLine = (encLength > maxLen); 00767 if (breakLine) 00768 { 00769 int dif = (stop - start) / 2; 00770 int step = dif; 00771 while (abs(step) > 1) 00772 { 00773 encLength = encodeRFC2047Quoted(codec->fromUnicode(_str. 00774 mid(start, dif)), useBase64).length(); 00775 step = (encLength > maxLen) ? (-abs(step) / 2) : (abs(step) / 2); 00776 dif += step; 00777 } 00778 stop = start + dif; 00779 } 00780 p = stop; 00781 while (p > start && _str.at(p) != ' ') p--; 00782 if (p > start) stop = p; 00783 if (result.right(3) == "?= ") start--; 00784 if (result.right(5) == "?=\n ") { 00785 start--; result.truncate(result.length() - 1); 00786 } 00787 int lastNewLine = result.findRev("\n "); 00788 if (!result.mid(lastNewLine).stripWhiteSpace().isEmpty() 00789 && result.length() - lastNewLine + encLength + 2 > maxLen) 00790 result += "\n "; 00791 result += "=?"; 00792 result += cset; 00793 result += (useBase64) ? "?b?" : "?q?"; 00794 result += encodeRFC2047Quoted(codec->fromUnicode(_str.mid(start, 00795 stop - start)), useBase64); 00796 result += "?="; 00797 if (breakLine) result += "\n "; 00798 pos = stop; 00799 } else { 00800 result += _str.mid(pos).latin1(); 00801 break; 00802 } 00803 } 00804 return result; 00805 } 00806 00807 00808 //----------------------------------------------------------------------------- 00809 QCString KMMsgBase::encodeRFC2231String( const QString& _str, 00810 const QCString& charset ) 00811 { 00812 if ( _str.isEmpty() ) 00813 return QCString(); 00814 00815 QCString cset; 00816 if ( charset.isEmpty() ) 00817 cset = QCString( kmkernel->networkCodec()->mimeName() ).lower(); 00818 else 00819 cset = charset; 00820 const QTextCodec *codec = codecForName( cset ); 00821 QCString latin; 00822 if ( charset == "us-ascii" ) 00823 latin = toUsAscii( _str ); 00824 else if ( codec ) 00825 latin = codec->fromUnicode( _str ); 00826 else 00827 latin = _str.local8Bit(); 00828 00829 char *l; 00830 for ( l = latin.data(); *l; ++l ) { 00831 if ( ( *l & 0xE0 == 0 ) || ( *l & 0x80 ) ) 00832 // *l is control character or 8-bit char 00833 break; 00834 } 00835 if ( !*l ) 00836 return latin; 00837 00838 QCString result = cset + "''"; 00839 for ( l = latin.data(); *l; ++l ) { 00840 bool needsQuoting = ( *l & 0x80 ); 00841 if( !needsQuoting ) { 00842 int len = especials.length(); 00843 for ( int i = 0; i < len; i++ ) 00844 if ( *l == especials[i] ) { 00845 needsQuoting = true; 00846 break; 00847 } 00848 } 00849 if ( needsQuoting ) { 00850 result += '%'; 00851 unsigned char hexcode; 00852 hexcode = ( ( *l & 0xF0 ) >> 4 ) + 48; 00853 if ( hexcode >= 58 ) 00854 hexcode += 7; 00855 result += hexcode; 00856 hexcode = ( *l & 0x0F ) + 48; 00857 if ( hexcode >= 58 ) 00858 hexcode += 7; 00859 result += hexcode; 00860 } else { 00861 result += *l; 00862 } 00863 } 00864 return result; 00865 } 00866 00867 00868 //----------------------------------------------------------------------------- 00869 QString KMMsgBase::decodeRFC2231String(const QCString& _str) 00870 { 00871 int p = _str.find('\''); 00872 if (p < 0) return kmkernel->networkCodec()->toUnicode(_str); 00873 00874 QCString charset = _str.left(p); 00875 00876 QCString st = _str.mid(_str.findRev('\'') + 1); 00877 char ch, ch2; 00878 p = 0; 00879 while (p < (int)st.length()) 00880 { 00881 if (st.at(p) == 37) 00882 { 00883 ch = st.at(p+1) - 48; 00884 if (ch > 16) ch -= 7; 00885 ch2 = st.at(p+2) - 48; 00886 if (ch2 > 16) ch2 -= 7; 00887 st.at(p) = ch * 16 + ch2; 00888 st.remove( p+1, 2 ); 00889 } 00890 p++; 00891 } 00892 QString result; 00893 const QTextCodec * codec = codecForName( charset ); 00894 if ( !codec ) 00895 codec = kmkernel->networkCodec(); 00896 return codec->toUnicode( st ); 00897 } 00898 00899 QString KMMsgBase::base64EncodedMD5( const QString & s, bool utf8 ) { 00900 if (s.stripWhiteSpace().isEmpty()) return ""; 00901 if ( utf8 ) 00902 return base64EncodedMD5( s.stripWhiteSpace().utf8() ); // QCString overload 00903 else 00904 return base64EncodedMD5( s.stripWhiteSpace().latin1() ); // const char * overload 00905 } 00906 00907 QString KMMsgBase::base64EncodedMD5( const QCString & s ) { 00908 if (s.stripWhiteSpace().isEmpty()) return ""; 00909 return base64EncodedMD5( s.stripWhiteSpace().data() ); 00910 } 00911 00912 QString KMMsgBase::base64EncodedMD5( const char * s, int len ) { 00913 if (!s || !len) return ""; 00914 static const int Base64EncodedMD5Len = 22; 00915 KMD5 md5( s, len ); 00916 return md5.base64Digest().left( Base64EncodedMD5Len ); 00917 } 00918 00919 00920 //----------------------------------------------------------------------------- 00921 QCString KMMsgBase::autoDetectCharset(const QCString &_encoding, const QStringList &encodingList, const QString &text) 00922 { 00923 QStringList charsets = encodingList; 00924 if (!_encoding.isEmpty()) 00925 { 00926 QString currentCharset = QString::fromLatin1(_encoding); 00927 charsets.remove(currentCharset); 00928 charsets.prepend(currentCharset); 00929 } 00930 00931 QStringList::ConstIterator it = charsets.begin(); 00932 for (; it != charsets.end(); ++it) 00933 { 00934 QCString encoding = (*it).latin1(); 00935 if (encoding == "locale") 00936 encoding = QCString(kmkernel->networkCodec()->mimeName()).lower(); 00937 if (text.isEmpty()) 00938 return encoding; 00939 if (encoding == "us-ascii") { 00940 bool ok; 00941 (void) KMMsgBase::toUsAscii(text, &ok); 00942 if (ok) 00943 return encoding; 00944 } 00945 else 00946 { 00947 const QTextCodec *codec = KMMsgBase::codecForName(encoding); 00948 if (!codec) { 00949 kdDebug(5006) << "Auto-Charset: Something is wrong and I can not get a codec. [" << encoding << "]" << endl; 00950 } else { 00951 if (codec->canEncode(text)) 00952 return encoding; 00953 } 00954 } 00955 } 00956 return 0; 00957 } 00958 00959 00960 //----------------------------------------------------------------------------- 00961 unsigned long KMMsgBase::getMsgSerNum() const 00962 { 00963 unsigned long msn = MessageProperty::serialCache( this ); 00964 if (msn) 00965 return msn; 00966 if (mParent) { 00967 int index = mParent->find((KMMsgBase*)this); 00968 msn = kmkernel->msgDict()->getMsgSerNum(mParent, index); 00969 if (msn) 00970 MessageProperty::setSerialCache( this, msn ); 00971 } 00972 return msn; 00973 } 00974 00975 00976 //----------------------------------------------------------------------------- 00977 bool KMMsgBase::isComplete() 00978 { 00979 return MessageProperty::complete( getMsgSerNum() ); 00980 } 00981 00982 00983 //----------------------------------------------------------------------------- 00984 void KMMsgBase::setComplete(bool value) 00985 { 00986 MessageProperty::setComplete( getMsgSerNum(), value ); 00987 if ( value ) 00988 setReadyToShow( true ); 00989 } 00990 00991 //----------------------------------------------------------------------------- 00992 bool KMMsgBase::readyToShow() 00993 { 00994 return MessageProperty::readyToShow( getMsgSerNum() ); 00995 } 00996 00997 00998 //----------------------------------------------------------------------------- 00999 void KMMsgBase::setReadyToShow(bool value) 01000 { 01001 MessageProperty::setReadyToShow( getMsgSerNum(), value ); 01002 } 01003 01004 01005 //----------------------------------------------------------------------------- 01006 bool KMMsgBase::transferInProgress() 01007 { 01008 return MessageProperty::transferInProgress( getMsgSerNum() ); 01009 } 01010 01011 01012 //----------------------------------------------------------------------------- 01013 void KMMsgBase::setTransferInProgress(bool value, bool force) 01014 { 01015 MessageProperty::setTransferInProgress( getMsgSerNum(), value, force ); 01016 } 01017 01018 01019 //----------------------------------------------------------------------------- 01020 static void swapEndian(QString &str) 01021 { 01022 uint len = str.length(); 01023 str = QDeepCopy<QString>(str); 01024 QChar *unicode = const_cast<QChar*>( str.unicode() ); 01025 for (uint i = 0; i < len; i++) 01026 unicode[i] = kmail_swap_16(unicode[i].unicode()); 01027 } 01028 01029 //----------------------------------------------------------------------------- 01030 static int g_chunk_length = 0, g_chunk_offset=0; 01031 static uchar *g_chunk = 0; 01032 01033 namespace { 01034 template < typename T > void copy_from_stream( T & x ) { 01035 if( g_chunk_offset + int(sizeof(T)) > g_chunk_length ) { 01036 g_chunk_offset = g_chunk_length; 01037 kdDebug( 5006 ) << "This should never happen.. " 01038 << __FILE__ << ":" << __LINE__ << endl; 01039 x = 0; 01040 } else { 01041 // the memcpy is optimized out by the compiler for the values 01042 // of sizeof(T) that is called with 01043 memcpy( &x, g_chunk + g_chunk_offset, sizeof(T) ); 01044 g_chunk_offset += sizeof(T); 01045 } 01046 } 01047 } 01048 01049 //----------------------------------------------------------------------------- 01050 QString KMMsgBase::getStringPart(MsgPartType t) const 01051 { 01052 QString ret; 01053 01054 g_chunk_offset = 0; 01055 bool using_mmap = FALSE; 01056 bool swapByteOrder = mParent->indexSwapByteOrder(); 01057 if (mParent->indexStreamBasePtr()) { 01058 if (g_chunk) 01059 free(g_chunk); 01060 using_mmap = TRUE; 01061 g_chunk = mParent->indexStreamBasePtr() + mIndexOffset; 01062 g_chunk_length = mIndexLength; 01063 } else { 01064 if(!mParent->mIndexStream) 01065 return ret; 01066 if (g_chunk_length < mIndexLength) 01067 g_chunk = (uchar *)realloc(g_chunk, g_chunk_length = mIndexLength); 01068 off_t first_off=ftell(mParent->mIndexStream); 01069 fseek(mParent->mIndexStream, mIndexOffset, SEEK_SET); 01070 fread( g_chunk, mIndexLength, 1, mParent->mIndexStream); 01071 fseek(mParent->mIndexStream, first_off, SEEK_SET); 01072 } 01073 01074 MsgPartType type; 01075 Q_UINT16 l; 01076 while(g_chunk_offset < mIndexLength) { 01077 Q_UINT32 tmp; 01078 copy_from_stream(tmp); 01079 copy_from_stream(l); 01080 if (swapByteOrder) 01081 { 01082 tmp = kmail_swap_32(tmp); 01083 l = kmail_swap_16(l); 01084 } 01085 type = (MsgPartType) tmp; 01086 if(g_chunk_offset + l > mIndexLength) { 01087 kdDebug(5006) << "This should never happen.. " << __FILE__ << ":" << __LINE__ << endl; 01088 break; 01089 } 01090 if(type == t) { 01091 // This works because the QString constructor does a memcpy. 01092 // Otherwise we would need to be concerned about the alignment. 01093 if(l) 01094 ret = QString((QChar *)(g_chunk + g_chunk_offset), l/2); 01095 break; 01096 } 01097 g_chunk_offset += l; 01098 } 01099 if(using_mmap) { 01100 g_chunk_length = 0; 01101 g_chunk = 0; 01102 } 01103 // Normally we need to swap the byte order because the QStrings are written 01104 // in the style of Qt2 (MSB -> network ordered). 01105 // QStrings in Qt3 expect host ordering. 01106 // On e.g. Intel host ordering is LSB, on e.g. Sparc it is MSB. 01107 01108 #ifndef WORDS_BIGENDIAN 01109 // #warning Byte order is little endian (swap is true) 01110 swapEndian(ret); 01111 #else 01112 // #warning Byte order is big endian (swap is false) 01113 #endif 01114 01115 return ret; 01116 } 01117 01118 //----------------------------------------------------------------------------- 01119 off_t KMMsgBase::getLongPart(MsgPartType t) const 01120 { 01121 off_t ret = 0; 01122 01123 g_chunk_offset = 0; 01124 bool using_mmap = FALSE; 01125 int sizeOfLong = mParent->indexSizeOfLong(); 01126 bool swapByteOrder = mParent->indexSwapByteOrder(); 01127 if (mParent->indexStreamBasePtr()) { 01128 if (g_chunk) 01129 free(g_chunk); 01130 using_mmap = TRUE; 01131 g_chunk = mParent->indexStreamBasePtr() + mIndexOffset; 01132 g_chunk_length = mIndexLength; 01133 } else { 01134 if (!mParent->mIndexStream) 01135 return ret; 01136 assert(mIndexLength >= 0); 01137 if (g_chunk_length < mIndexLength) 01138 g_chunk = (uchar *)realloc(g_chunk, g_chunk_length = mIndexLength); 01139 off_t first_off=ftell(mParent->mIndexStream); 01140 fseek(mParent->mIndexStream, mIndexOffset, SEEK_SET); 01141 fread( g_chunk, mIndexLength, 1, mParent->mIndexStream); 01142 fseek(mParent->mIndexStream, first_off, SEEK_SET); 01143 } 01144 01145 MsgPartType type; 01146 Q_UINT16 l; 01147 while (g_chunk_offset < mIndexLength) { 01148 Q_UINT32 tmp; 01149 copy_from_stream(tmp); 01150 copy_from_stream(l); 01151 if (swapByteOrder) 01152 { 01153 tmp = kmail_swap_32(tmp); 01154 l = kmail_swap_16(l); 01155 } 01156 type = (MsgPartType) tmp; 01157 01158 if (g_chunk_offset + l > mIndexLength) { 01159 kdDebug(5006) << "This should never happen.. " << __FILE__ << ":" << __LINE__ << endl; 01160 break; 01161 } 01162 if(type == t) { 01163 assert(sizeOfLong == l); 01164 if (sizeOfLong == sizeof(ret)) 01165 { 01166 copy_from_stream(ret); 01167 if (swapByteOrder) 01168 { 01169 if (sizeof(ret) == 4) 01170 ret = kmail_swap_32(ret); 01171 else 01172 ret = kmail_swap_64(ret); 01173 } 01174 } 01175 else if (sizeOfLong == 4) 01176 { 01177 // Long is stored as 4 bytes in index file, sizeof(long) = 8 01178 Q_UINT32 ret_32; 01179 copy_from_stream(ret_32); 01180 if (swapByteOrder) 01181 ret_32 = kmail_swap_32(ret_32); 01182 ret = ret_32; 01183 } 01184 else if (sizeOfLong == 8) 01185 { 01186 // Long is stored as 8 bytes in index file, sizeof(long) = 4 01187 Q_UINT32 ret_1; 01188 Q_UINT32 ret_2; 01189 copy_from_stream(ret_1); 01190 copy_from_stream(ret_2); 01191 if (!swapByteOrder) 01192 { 01193 // Index file order is the same as the order of this CPU. 01194 #ifndef WORDS_BIGENDIAN 01195 // Index file order is little endian 01196 ret = ret_1; // We drop the 4 most significant bytes 01197 #else 01198 // Index file order is big endian 01199 ret = ret_2; // We drop the 4 most significant bytes 01200 #endif 01201 } 01202 else 01203 { 01204 // Index file order is different from this CPU. 01205 #ifndef WORDS_BIGENDIAN 01206 // Index file order is big endian 01207 ret = ret_2; // We drop the 4 most significant bytes 01208 #else 01209 // Index file order is little endian 01210 ret = ret_1; // We drop the 4 most significant bytes 01211 #endif 01212 // We swap the result to host order. 01213 ret = kmail_swap_32(ret); 01214 } 01215 01216 } 01217 break; 01218 } 01219 g_chunk_offset += l; 01220 } 01221 if(using_mmap) { 01222 g_chunk_length = 0; 01223 g_chunk = 0; 01224 } 01225 return ret; 01226 } 01227 01228 #ifndef WORDS_BIGENDIAN 01229 // We need to use swab to swap bytes to network byte order 01230 #define memcpy_networkorder(to, from, len) swab((char *)(from), (char *)(to), len) 01231 #else 01232 // We're already in network byte order 01233 #define memcpy_networkorder(to, from, len) memcpy(to, from, len) 01234 #endif 01235 01236 #define STORE_DATA_LEN(type, x, len, network_order) do { \ 01237 int len2 = (len > 256) ? 256 : len; \ 01238 if(csize < (length + (len2 + sizeof(short) + sizeof(MsgPartType)))) \ 01239 ret = (uchar *)realloc(ret, csize += len2+sizeof(short)+sizeof(MsgPartType)); \ 01240 Q_UINT32 t = (Q_UINT32) type; memcpy(ret+length, &t, sizeof(t)); \ 01241 Q_UINT16 l = len2; memcpy(ret+length+sizeof(t), &l, sizeof(l)); \ 01242 if (network_order) \ 01243 memcpy_networkorder(ret+length+sizeof(t)+sizeof(l), x, len2); \ 01244 else \ 01245 memcpy(ret+length+sizeof(t)+sizeof(l), x, len2); \ 01246 length += len2+sizeof(t)+sizeof(l); \ 01247 } while(0) 01248 #define STORE_DATA(type, x) STORE_DATA_LEN(type, &x, sizeof(x), false) 01249 01250 //----------------------------------------------------------------------------- 01251 const uchar *KMMsgBase::asIndexString(int &length) const 01252 { 01253 unsigned int csize = 256; 01254 static uchar *ret = 0; //different static buffer here for we may use the other buffer in the functions below 01255 if(!ret) 01256 ret = (uchar *)malloc(csize); 01257 length = 0; 01258 01259 unsigned long tmp; 01260 QString tmp_str; 01261 01262 //these is at the beginning because it is queried quite often 01263 tmp_str = msgIdMD5().stripWhiteSpace(); 01264 STORE_DATA_LEN(MsgIdMD5Part, tmp_str.unicode(), tmp_str.length() * 2, true); 01265 tmp = mLegacyStatus; 01266 STORE_DATA(MsgLegacyStatusPart, tmp); 01267 01268 //these are completely arbitrary order 01269 tmp_str = fromStrip().stripWhiteSpace(); 01270 STORE_DATA_LEN(MsgFromPart, tmp_str.unicode(), tmp_str.length() * 2, true); 01271 tmp_str = subject().stripWhiteSpace(); 01272 STORE_DATA_LEN(MsgSubjectPart, tmp_str.unicode(), tmp_str.length() * 2, true); 01273 tmp_str = toStrip().stripWhiteSpace(); 01274 STORE_DATA_LEN(MsgToPart, tmp_str.unicode(), tmp_str.length() * 2, true); 01275 tmp_str = replyToIdMD5().stripWhiteSpace(); 01276 STORE_DATA_LEN(MsgReplyToIdMD5Part, tmp_str.unicode(), tmp_str.length() * 2, true); 01277 tmp_str = xmark().stripWhiteSpace(); 01278 STORE_DATA_LEN(MsgXMarkPart, tmp_str.unicode(), tmp_str.length() * 2, true); 01279 tmp_str = fileName().stripWhiteSpace(); 01280 STORE_DATA_LEN(MsgFilePart, tmp_str.unicode(), tmp_str.length() * 2, true); 01281 tmp = msgSize(); 01282 STORE_DATA(MsgSizePart, tmp); 01283 tmp = folderOffset(); 01284 STORE_DATA(MsgOffsetPart, tmp); 01285 tmp = date(); 01286 STORE_DATA(MsgDatePart, tmp); 01287 tmp = (signatureState() << 16) | encryptionState(); 01288 STORE_DATA(MsgCryptoStatePart, tmp); 01289 tmp = mdnSentState(); 01290 STORE_DATA(MsgMDNSentPart, tmp); 01291 01292 tmp_str = replyToAuxIdMD5().stripWhiteSpace(); 01293 STORE_DATA_LEN(MsgReplyToAuxIdMD5Part, tmp_str.unicode(), tmp_str.length() * 2, true); 01294 01295 tmp_str = strippedSubjectMD5().stripWhiteSpace(); 01296 STORE_DATA_LEN(MsgStrippedSubjectMD5Part, tmp_str.unicode(), tmp_str.length() * 2, true); 01297 01298 tmp = status(); 01299 STORE_DATA(MsgStatusPart, tmp); 01300 01301 return ret; 01302 } 01303 #undef STORE_DATA_LEN 01304 #undef STORE_DATA 01305 01306 bool KMMsgBase::syncIndexString() const 01307 { 01308 if(!dirty()) 01309 return TRUE; 01310 int len; 01311 const uchar *buffer = asIndexString(len); 01312 if (len == mIndexLength) { 01313 Q_ASSERT(mParent->mIndexStream); 01314 fseek(mParent->mIndexStream, mIndexOffset, SEEK_SET); 01315 assert( mIndexOffset > 0 ); 01316 fwrite( buffer, len, 1, mParent->mIndexStream); 01317 return TRUE; 01318 } 01319 return FALSE; 01320 }
KDE Logo
This file is part of the documentation for kmail Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jul 28 23:58:03 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003