Back to index

lightning-sunbird  0.9+nobinonly
nsOEMailbox.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsOEMailbox.h"
00039 
00040 #include "OEDebugLog.h"
00041 #include "msgCore.h"
00042 #include "prprf.h"
00043 #include "nsMsgLocalFolderHdrs.h"
00044 
00045 
00046 class CMbxScanner {
00047 public:
00048   CMbxScanner( nsString& name, nsIFileSpec * mbxFile, nsIFileSpec * dstFile);
00049   ~CMbxScanner();
00050   
00051   virtual PRBool  Initialize( void);
00052   virtual PRBool  DoWork( PRBool *pAbort, PRUint32 *pDone, PRUint32 *pCount);
00053   
00054   PRBool    WasErrorFatal( void) { return( m_fatalError);}
00055   PRUint32  BytesProcessed( void) { return( m_didBytes);}
00056   
00057 protected:
00058   PRBool  WriteMailItem( PRUint32 flags, PRUint32 offset, PRUint32 size, PRUint32 *pTotalMsgSize = nsnull);
00059   virtual void  CleanUp( void);
00060   
00061 private:
00062   void ReportWriteError( nsIFileSpec * file, PRBool fatal = PR_TRUE);
00063   void ReportReadError( nsIFileSpec * file, PRBool fatal = PR_TRUE);
00064   PRBool CopyMbxFileBytes(PRUint32 flags, PRUint32 numBytes);
00065   PRBool IsFromLineKey( PRUint8 *pBuf, PRUint32 max);
00066   
00067 public:
00068   PRUint32      m_msgCount;
00069   
00070 protected:
00071   PRUint32 *    m_pDone;
00072   nsString      m_name;
00073   nsIFileSpec * m_mbxFile;
00074   nsIFileSpec * m_dstFile;
00075   PRUint8 *     m_pInBuffer;
00076   PRUint8 *     m_pOutBuffer;
00077   PRUint32      m_bufSz;
00078   PRUint32      m_didBytes;
00079   PRBool        m_fatalError;
00080   PRUint32      m_mbxFileSize;
00081   PRUint32      m_mbxOffset;
00082   
00083   static const char *       m_pFromLine;
00084   
00085 };
00086 
00087 
00088 class CIndexScanner : public CMbxScanner {
00089 public:
00090   CIndexScanner( nsString& name, nsIFileSpec * idxFile, nsIFileSpec * mbxFile, nsIFileSpec *dstFile);
00091   ~CIndexScanner();
00092   
00093   virtual PRBool  Initialize( void);
00094   virtual PRBool  DoWork( PRBool *pAbort, PRUint32 *pDone, PRUint32 *pCount);
00095   
00096 protected:
00097   virtual void    CleanUp( void);
00098   
00099 private:
00100   PRBool          ValidateIdxFile( void);
00101   PRBool          GetMailItem( PRUint32 *pFlags, PRUint32 *pOffset, PRUint32 *pSize);
00102   
00103   
00104 private:
00105   nsIFileSpec *   m_idxFile;
00106   PRUint32        m_numMessages;
00107   PRUint32        m_idxOffset;
00108   PRUint32        m_curItemIndex;
00109 };
00110 
00111 
00112 PRBool CImportMailbox::ImportMailbox( PRUint32 *pDone, PRBool *pAbort, nsString& name, nsIFileSpec * inFile, nsIFileSpec * outFile, PRUint32 *pCount)
00113 {
00114   PRBool  done = PR_FALSE;
00115   nsIFileSpec *idxFile;
00116   if (NS_FAILED( NS_NewFileSpec( &idxFile))) {
00117     IMPORT_LOG0( "New file spec failed!\n");
00118     return( PR_FALSE);
00119   }
00120   
00121   idxFile->FromFileSpec( inFile);
00122   if (GetIndexFile( idxFile)) {
00123     
00124     IMPORT_LOG1( "Using index file for: %S\n", name.get());
00125                             
00126     CIndexScanner *pIdxScanner = new CIndexScanner( name, idxFile, inFile, outFile);
00127     if (pIdxScanner->Initialize()) {
00128       if (pIdxScanner->DoWork( pAbort, pDone, pCount)) {
00129         done = PR_TRUE;
00130       }
00131       else {
00132         IMPORT_LOG0( "CIndexScanner::DoWork() failed\n");
00133       }
00134     }
00135     else {
00136       IMPORT_LOG0( "CIndexScanner::Initialize() failed\n");
00137     }
00138     
00139     delete pIdxScanner;
00140   }
00141   
00142   idxFile->Release();
00143   
00144   if (done)
00145     return( done);
00146   
00147     /* 
00148     something went wrong with the index file, just scan the mailbox
00149     file itself.
00150   */
00151   CMbxScanner *pMbx = new CMbxScanner( name, inFile, outFile);
00152   if (pMbx->Initialize()) {
00153     if (pMbx->DoWork( pAbort, pDone, pCount)) {
00154       done = PR_TRUE;
00155     }
00156     else {
00157       IMPORT_LOG0( "CMbxScanner::DoWork() failed\n");
00158     }
00159   }
00160   else {
00161     IMPORT_LOG0( "CMbxScanner::Initialize() failed\n");
00162   }
00163   
00164   delete pMbx;
00165   return( done);            
00166 }
00167 
00168 
00169 PRBool CImportMailbox::GetIndexFile( nsIFileSpec* file)
00170 {
00171   char *pLeaf = nsnull;
00172   if (NS_FAILED( file->GetLeafName( &pLeaf)))
00173     return( PR_FALSE);
00174   PRInt32     len = strlen( pLeaf);
00175   if (len < 5) {
00176     nsCRT::free( pLeaf);
00177     return( PR_FALSE);
00178   }
00179   pLeaf[len - 1] = 'x';
00180   pLeaf[len - 2] = 'd';
00181   pLeaf[len - 3] = 'i';
00182   
00183   IMPORT_LOG1( "Looking for index leaf name: %s\n", pLeaf);
00184   
00185   nsresult    rv;
00186   rv = file->SetLeafName( pLeaf);
00187   nsCRT::free( pLeaf);
00188   
00189   PRBool      isFile = PR_FALSE;
00190   PRBool      exists = PR_FALSE;
00191   if (NS_SUCCEEDED( rv)) rv = file->IsFile( &isFile);
00192   if (NS_SUCCEEDED( rv)) rv = file->Exists( &exists);
00193               
00194   if (isFile && exists)
00195     return( PR_TRUE);
00196   else
00197     return( PR_FALSE);
00198 }
00199 
00200 
00201 const char *CMbxScanner::m_pFromLine = "From - Mon Jan 1 00:00:00 1965\x0D\x0A";
00202 // let's try a 16K buffer and see how well that works?
00203 #define       kBufferKB     16
00204 
00205 
00206 CMbxScanner::CMbxScanner( nsString& name, nsIFileSpec* mbxFile, nsIFileSpec* dstFile)
00207 {
00208   m_msgCount = 0;
00209   m_name = name;
00210   m_mbxFile = mbxFile;
00211   m_mbxFile->AddRef();
00212   m_dstFile = dstFile;
00213   m_dstFile->AddRef();
00214   m_pInBuffer = nsnull;
00215   m_pOutBuffer = nsnull;
00216   m_bufSz = 0;
00217   m_fatalError = PR_FALSE;
00218   m_didBytes = 0;
00219   m_mbxFileSize = 0;
00220   m_mbxOffset = 0;
00221 }
00222 
00223 CMbxScanner::~CMbxScanner()
00224 {
00225        CleanUp();
00226        if (m_mbxFile)
00227               m_mbxFile->Release();
00228        if (m_dstFile)
00229               m_dstFile->Release();       
00230 }
00231 
00232 void CMbxScanner::ReportWriteError( nsIFileSpec * file, PRBool fatal)
00233 {
00234        m_fatalError = fatal;
00235 }
00236 
00237 void CMbxScanner::ReportReadError( nsIFileSpec * file, PRBool fatal)
00238 {
00239        m_fatalError = fatal;
00240 }
00241 
00242 PRBool CMbxScanner::Initialize( void)
00243 {
00244   m_bufSz = (kBufferKB * 1024);
00245   m_pInBuffer = new PRUint8[m_bufSz];
00246   m_pOutBuffer = new PRUint8[m_bufSz];
00247   if (!m_pInBuffer || !m_pOutBuffer) {
00248     return( PR_FALSE);
00249   }
00250   
00251   m_mbxFile->GetFileSize( &m_mbxFileSize);
00252   // open the mailbox file...
00253   if (NS_FAILED( m_mbxFile->OpenStreamForReading())) {
00254     CleanUp();
00255     return( PR_FALSE);
00256   }
00257   
00258   if (NS_FAILED( m_dstFile->OpenStreamForWriting())) {
00259     CleanUp();
00260     return( PR_FALSE);
00261   }
00262   
00263   return( PR_TRUE);
00264 }
00265 
00266 
00267 #define       kMbxHeaderSize              0x0054
00268 #define kMbxMessageHeaderSz 16
00269 
00270 PRBool CMbxScanner::DoWork( PRBool *pAbort, PRUint32 *pDone, PRUint32 *pCount)
00271 {
00272   m_mbxOffset = kMbxHeaderSize;
00273   m_didBytes = kMbxHeaderSize;
00274   
00275   while (!(*pAbort) && ((m_mbxOffset + kMbxMessageHeaderSz) < m_mbxFileSize)) {
00276     PRUint32         msgSz;
00277     if (!WriteMailItem( 0, m_mbxOffset, 0, &msgSz)) {
00278       if (!WasErrorFatal())
00279         ReportReadError( m_mbxFile);
00280       return( PR_FALSE);
00281     }
00282     m_mbxOffset += msgSz;
00283     m_didBytes += msgSz;
00284     m_msgCount++;
00285     if (pDone)
00286       *pDone = m_didBytes;
00287     if (pCount)
00288       *pCount = m_msgCount;
00289   }
00290   
00291   CleanUp();
00292   
00293   return( PR_TRUE);
00294 }
00295 
00296 
00297 void CMbxScanner::CleanUp( void)
00298 {
00299   m_mbxFile->CloseStream();
00300   m_dstFile->CloseStream();
00301   
00302   if (m_pInBuffer != nsnull) {
00303     delete [] m_pInBuffer;
00304     m_pInBuffer = nsnull;
00305   }
00306   
00307   if (m_pOutBuffer != nsnull) {
00308     delete [] m_pOutBuffer;
00309     m_pOutBuffer = nsnull;
00310   }
00311 }
00312 
00313 
00314 #define       kNumMbxLongsToRead   4
00315 
00316 PRBool CMbxScanner::WriteMailItem( PRUint32 flags, PRUint32 offset, PRUint32 size, PRUint32 *pTotalMsgSize)
00317 {
00318   PRUint32    values[kNumMbxLongsToRead];
00319   PRInt32            cnt = kNumMbxLongsToRead * sizeof( PRUint32);
00320   nsresult    rv;
00321   PRBool             failed = PR_FALSE;
00322   PRInt32            cntRead;
00323   PRInt8 *    pChar = (PRInt8 *) values;
00324   
00325   rv = m_mbxFile->Seek( offset);
00326   m_mbxFile->Failed( &failed);
00327   
00328   if (NS_FAILED( rv) || failed) {
00329     IMPORT_LOG1( "Mbx seek error: 0x%lx\n", offset);
00330     return( PR_FALSE);
00331   }
00332   rv = m_mbxFile->Read( (char **) &pChar, cnt, &cntRead);
00333   if (NS_FAILED( rv) || (cntRead != cnt)) {
00334     IMPORT_LOG1( "Mbx read error at: 0x%lx\n", offset);
00335     return( PR_FALSE);
00336   }
00337   if (values[0] != 0x7F007F00) {
00338     IMPORT_LOG2( "Mbx tag field doesn't match: 0x%lx, at offset: 0x%lx\n", values[0], offset);
00339     return( PR_FALSE);
00340   }
00341   if (size && (values[2] != size)) {
00342     IMPORT_LOG3( "Mbx size doesn't match idx, mbx: %ld, idx: %ld, at offset: 0x%lx\n", values[2], size, offset);
00343     return( PR_FALSE);
00344   }
00345   
00346   if (pTotalMsgSize != nsnull)
00347     *pTotalMsgSize = values[2];
00348   
00349   // everything looks kosher...
00350   // the actual message text follows and is values[3] bytes long...
00351   return( CopyMbxFileBytes(flags,  values[3]));
00352 }
00353 
00354 PRBool CMbxScanner::IsFromLineKey( PRUint8 * pBuf, PRUint32 max)
00355 {
00356   return (max > 5 && (pBuf[0] == 'F') && (pBuf[1] == 'r') && (pBuf[2] == 'o') && (pBuf[3] == 'm') && (pBuf[4] == ' '));
00357 }
00358 
00359 
00360 #define IS_ANY_SPACE( _ch) ((_ch == ' ') || (_ch == '\t') || (_ch == 10) || (_ch == 13))
00361 
00362 
00363 PRBool CMbxScanner::CopyMbxFileBytes(PRUint32 flags, PRUint32 numBytes)
00364 {
00365   if (!numBytes)
00366     return( PR_TRUE);
00367   
00368   PRUint32  cnt;
00369   PRUint8   last[2] = {0, 0};
00370   PRUint32  inIdx = 0;
00371   PRBool    first = PR_TRUE;
00372   PRUint8 * pIn;
00373   PRUint8 * pStart;
00374   PRInt32   fromLen = strlen( m_pFromLine);
00375   nsresult  rv;
00376   PRInt32   cntRead;
00377   PRUint8 * pChar;
00378   
00379   while (numBytes) {
00380     if (numBytes > (m_bufSz - inIdx))
00381       cnt = m_bufSz - inIdx;
00382     else
00383       cnt = numBytes;
00384     // Read some of the message from the file...
00385     pChar = m_pInBuffer + inIdx;
00386     rv = m_mbxFile->Read( (char **) &pChar, (PRInt32)cnt, &cntRead);
00387     if (NS_FAILED( rv) || (cntRead != (PRInt32)cnt)) {
00388       ReportReadError( m_mbxFile);
00389       return( PR_FALSE);
00390     }
00391     // Keep track of the last 2 bytes of the message for terminating EOL logic      
00392     if (cnt < 2) {
00393       last[0] = last[1];
00394       last[1] = m_pInBuffer[cnt - 1];
00395     }
00396     else {
00397       last[0] = m_pInBuffer[cnt - 2];
00398       last[1] = m_pInBuffer[cnt - 1];
00399     }
00400     
00401     inIdx = 0;
00402     // Handle the beginning line, don't duplicate an existing From separator
00403     if (first) {
00404       // check the first buffer to see if it already starts with a From line
00405       // If it does, throw it away and use our own
00406       if (IsFromLineKey( m_pInBuffer, cnt)) {
00407         // skip past the first line
00408         while ((inIdx < cnt) && (m_pInBuffer[inIdx] != 0x0D))
00409           inIdx++;
00410         while ((inIdx < cnt) && (IS_ANY_SPACE( m_pInBuffer[inIdx])))
00411           inIdx++;
00412         if (inIdx >= cnt) {
00413           // This should not occurr - it means the message starts
00414           // with a From separator line that is longer than our
00415           // file buffer!  In this bizarre case, just skip this message
00416           // since it is probably bogus anyway.
00417           return( PR_TRUE);
00418         }
00419         
00420       }
00421       // Begin every message with a From separator
00422       rv = m_dstFile->Write( m_pFromLine, fromLen, &cntRead);
00423       if (NS_FAILED( rv) || (cntRead != fromLen)) {
00424         ReportWriteError( m_dstFile);
00425         return( PR_FALSE);
00426       }
00427       char statusLine[50];
00428       PRUint32 msgFlags = flags; // need to convert from OE flags to mozilla flags
00429       PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF);
00430       rv = m_dstFile->Write(statusLine, strlen(statusLine), &cntRead);
00431       if (NS_SUCCEEDED(rv) && cntRead == fromLen)
00432       {
00433         PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS2_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF0000);
00434         rv = m_dstFile->Write(statusLine, strlen(statusLine), &cntRead);
00435       }
00436       if (NS_FAILED( rv) || (cntRead != fromLen)) {
00437         ReportWriteError( m_dstFile);
00438         return( PR_FALSE);
00439       }
00440       first = PR_FALSE;
00441     }
00442     
00443     // Handle generic data, escape any lines that begin with "From "
00444     pIn = m_pInBuffer + inIdx;
00445     numBytes -= cnt;
00446     m_didBytes += cnt;
00447     pStart = pIn;
00448     cnt -= inIdx;
00449     inIdx = 0;
00450     while (cnt) {
00451       if (*pIn == 0x0D) {
00452         // need more in buffer?
00453         if ((cnt < 7) && numBytes) {
00454           break;
00455         }
00456         else if (cnt > 6) {
00457           if ((pIn[1] == 0x0A) && (IsFromLineKey( pIn + 2, cnt))) {
00458             inIdx += 2;
00459             // Match, escape it
00460             rv = m_dstFile->Write( (const char *)pStart, (PRInt32)inIdx, &cntRead);
00461             if (NS_SUCCEEDED( rv) && (cntRead == (PRInt32)inIdx))
00462               rv = m_dstFile->Write( ">", 1, &cntRead);
00463             if (NS_FAILED( rv) || (cntRead != 1)) {
00464               ReportWriteError( m_dstFile);
00465               return( PR_FALSE);
00466             }
00467             cnt -= 2;
00468             pIn += 2;
00469             inIdx = 0;
00470             pStart = pIn;
00471             continue;
00472           }
00473         }
00474       } // == 0x0D
00475       cnt--;
00476       inIdx++;
00477       pIn++;
00478     }
00479     rv = m_dstFile->Write( (const char *)pStart, (PRInt32)inIdx, &cntRead);
00480     if (NS_FAILED( rv) || (cntRead != (PRInt32)inIdx)) {
00481       ReportWriteError( m_dstFile);
00482       return( PR_FALSE);
00483     }
00484     if (cnt) {
00485       inIdx = cnt;
00486       memcpy( m_pInBuffer, pIn, cnt);
00487     }
00488     else
00489       inIdx = 0;
00490   }
00491   
00492   // I used to check for an eol before writing one but
00493   // it turns out that adding a proper EOL before the next
00494   // separator never really hurts so better to be safe
00495   // and always do it.
00496   //   if ((last[0] != 0x0D) || (last[1] != 0x0A)) {
00497   rv = m_dstFile->Write( "\x0D\x0A", 2, &cntRead);
00498   if (NS_FAILED( rv) || (cntRead != 2)) {
00499     ReportWriteError( m_dstFile);
00500     return( PR_FALSE);
00501   }
00502   //   }
00503   
00504   return( PR_TRUE);
00505 }
00506 
00507 
00508 CIndexScanner::CIndexScanner( nsString& name, nsIFileSpec * idxFile, nsIFileSpec * mbxFile, nsIFileSpec * dstFile)
00509 : CMbxScanner( name, mbxFile, dstFile)
00510 {
00511   m_idxFile = idxFile;
00512   m_idxFile->AddRef();
00513   m_curItemIndex = 0;
00514   m_idxOffset = 0;
00515 }
00516 
00517 CIndexScanner::~CIndexScanner()
00518 {
00519   CleanUp();
00520   if (m_idxFile)
00521     m_idxFile->Release();
00522 }
00523 
00524 PRBool CIndexScanner::Initialize( void)
00525 {
00526   if (!CMbxScanner::Initialize())
00527     return( PR_FALSE);
00528   
00529   
00530   nsresult    rv = m_idxFile->OpenStreamForReading();
00531   if (NS_FAILED( rv)) {
00532     CleanUp();
00533     return( PR_FALSE);
00534   }
00535   
00536   return( PR_TRUE);
00537 }
00538 
00539 PRBool CIndexScanner::ValidateIdxFile( void)
00540 {
00541   PRInt8                    id[4];
00542   PRInt32                   cnt = 4;
00543   nsresult           rv;
00544   PRInt32                   cntRead;
00545   PRInt8 *           pReadTo;
00546   
00547   pReadTo = id;
00548   rv = m_idxFile->Read( (char **) &pReadTo, cnt, &cntRead);
00549   if (NS_FAILED( rv) || (cntRead != cnt))
00550     return( PR_FALSE);
00551   if ((id[0] != 'J') || (id[1] != 'M') || (id[2] != 'F') || (id[3] != '9'))
00552     return( PR_FALSE);
00553   cnt = 4;
00554   PRUint32           subId;
00555   pReadTo = (PRInt8 *) &subId;
00556   rv = m_idxFile->Read( (char **) &pReadTo, cnt, &cntRead);
00557   if (NS_FAILED( rv) || (cntRead != cnt))
00558     return( PR_FALSE);
00559   if (subId != 0x00010004) {
00560     IMPORT_LOG1( "Idx file subid doesn't match: 0x%lx\n", subId);
00561     return( PR_FALSE);
00562   }
00563   
00564   pReadTo = (PRInt8 *) &m_numMessages;
00565   rv = m_idxFile->Read( (char **) &pReadTo, cnt, &cntRead);
00566   if (NS_FAILED( rv) || (cntRead != cnt))
00567     return( PR_FALSE);
00568   
00569   IMPORT_LOG1( "Idx file num messages: %ld\n", m_numMessages);
00570   
00571   m_didBytes += 80;
00572   m_idxOffset = 80;
00573   return( PR_TRUE);
00574 }
00575 
00576 /*
00577 Idx file...
00578 Header is 80 bytes, JMF9, subId? 0x00010004, numMessages, fileSize, 1, 0x00010010
00579 Entries start at byte 80
00580 4 byte numbers
00581 Flags? maybe
00582 ?? who knows
00583 index
00584 start of this entry in the file
00585 length of this record
00586 msg offset in mbx
00587 msg length in mbx
00588 
00589 */
00590 
00591 // #define DEBUG_SUBJECT_AND_FLAGS 1
00592 #define       kNumIdxLongsToRead          7
00593 
00594 PRBool CIndexScanner::GetMailItem( PRUint32 *pFlags, PRUint32 *pOffset, PRUint32 *pSize)
00595 {
00596   PRUint32    values[kNumIdxLongsToRead];
00597   PRInt32            cnt = kNumIdxLongsToRead * sizeof( PRUint32);
00598   PRInt8 *    pReadTo = (PRInt8 *) values;
00599   PRInt32            cntRead;
00600   nsresult    rv;
00601   
00602   rv = m_idxFile->Seek( m_idxOffset);
00603   if (NS_FAILED( rv))
00604     return( PR_FALSE);
00605   
00606   rv = m_idxFile->Read( (char **) &pReadTo, cnt, &cntRead);           
00607   if (NS_FAILED( rv) || (cntRead != cnt))
00608     return( PR_FALSE);
00609               
00610   if (values[3] != m_idxOffset) {
00611     IMPORT_LOG2( "Self pointer invalid: m_idxOffset=0x%lx, self=0x%lx\n", m_idxOffset, values[3]);
00612     return( PR_FALSE);
00613   }
00614   
00615   // So... what do we have here???
00616 #ifdef DEBUG_SUBJECT_AND_FLAGS
00617   IMPORT_LOG2( "Number: %ld, msg offset: 0x%lx, ", values[2], values[5]);
00618   IMPORT_LOG2( "msg length: %ld, Flags: 0x%lx\n", values[6], values[0]);
00619   m_idxFile->seek( m_idxOffset + 212);
00620   PRUint32    subSz = 0;
00621   cnt = 4;
00622   pReadTo = (PRInt8 *) &subSz;
00623   m_idxFile->Read( (char **) &pReadTo, cnt, &cntRead);
00624   if ((subSz >= 0) && (subSz < 1024)) {
00625     char *pSub = new char[subSz + 1];
00626     m_idxFile->Read( &pSub, subSz, &cntRead);
00627     pSub[subSz] = 0;
00628     IMPORT_LOG1( "    Subject: %s\n", pSub);
00629     delete [] pSub;
00630   }
00631 #endif
00632   
00633   m_idxOffset += values[4];
00634   m_didBytes += values[4];
00635   
00636   *pFlags = values[0];
00637   *pOffset = values[5];
00638   *pSize = values[6];
00639   return( PR_TRUE);
00640 }
00641 
00642 #define       kOEDeletedFlag              0x0001
00643 
00644 PRBool CIndexScanner::DoWork( PRBool *pAbort, PRUint32 *pDone, PRUint32 *pCount)
00645 {
00646   m_didBytes = 0;
00647   if (!ValidateIdxFile())
00648     return( PR_FALSE);
00649   
00650   PRBool      failed = PR_FALSE;
00651   while ((m_curItemIndex < m_numMessages) && !failed && !(*pAbort)) {
00652     PRUint32  flags, offset, size;
00653     if (!GetMailItem( &flags, &offset, &size)) {
00654       CleanUp();
00655       return( PR_FALSE);
00656     }
00657     m_curItemIndex++;
00658     if (!(flags & kOEDeletedFlag)) {
00659       if (!WriteMailItem( flags, offset, size))
00660         failed = PR_TRUE;
00661       else {
00662         m_msgCount++;
00663       }
00664     }
00665     m_didBytes += size;
00666     if (pDone)
00667       *pDone = m_didBytes;
00668     if (pCount)
00669       *pCount = m_msgCount;
00670   }
00671   
00672   CleanUp();
00673   return( !failed);
00674 }
00675 
00676 
00677 void CIndexScanner::CleanUp( void)
00678 {
00679   CMbxScanner::CleanUp();
00680   m_idxFile->CloseStream(); 
00681 }
00682