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 Sat May 1 11:37:33 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003