mailnews/import/src/nsImportEncodeScan.cpp
author hg@mozilla.org
Thu, 18 Sep 2008 16:13:11 +0200
changeset 372 7c0bfdcda6731e77303f3c47b01736aaa93d5534
parent 0 e4f4569d451a5e0d12a6aa33ebd916f979dd8faa
child 8938 1c8c69af4d1df163082aba68b7602e37e8a80363
permissions -rw-r--r--
bug 455727 - import calendar/ into comm-central, initial import of code from CVS tag HG_COMM_INITIAL_IMPORT at 2008-09-18 07:11:38 PST, imported and tagged cvs.mozilla.org modules: mozilla/calendar mozilla/other-licenses/branding/sunbird/

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is mozilla.org code.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "nscore.h"
#include "nsImportEncodeScan.h"
#include "nsNetUtil.h"

#define  kBeginAppleSingle    0
#define  kBeginDataFork      1
#define  kBeginResourceFork    2
#define  kAddEntries        3
#define  kScanningDataFork    4
#define  kScanningRsrcFork    5
#define  kDoneWithFile      6

PRUint32  gAppleSingleHeader[6] = {0x00051600, 0x00020000, 0, 0, 0, 0};
#define kAppleSingleHeaderSize  (6 * sizeof( PRUint32))

#ifdef _MAC_IMPORT_CODE
#include "MoreFilesExtras.h"
#include "MoreDesktopMgr.h"

CInfoPBRec  gCatInfoPB;
U32      g2000Secs = 0;
long    gGMTDelta = 0;

long GetGmtDelta( void);
U32 Get2000Secs( void);


long GetGmtDelta( void)
{
  MachineLocation myLocation;
  ReadLocation( &myLocation);
  long  myDelta = BitAnd( myLocation.u.gmtDelta, 0x00FFFFFF);
  if (BitTst( &myDelta, 23))
    myDelta = BitOr( myDelta, 0xFF000000);
  return( myDelta);
}

U32 Get2000Secs( void)
{
  DateTimeRec  dr;
  dr.year = 2000;
  dr.month = 1;
  dr.day = 1;
  dr.hour = 0;
  dr.minute = 0;
  dr.second = 0;
  dr.dayOfWeek = 0;
  U32  result;
  DateToSeconds( &dr, &result);
  return( result);
}
#endif

nsImportEncodeScan::nsImportEncodeScan()
{
  m_isAppleSingle = PR_FALSE;
  m_encodeScanState = 0;
  m_resourceForkSize = 0;
  m_dataForkSize = 0;
}

nsImportEncodeScan::~nsImportEncodeScan()
{
}

PRBool nsImportEncodeScan::InitEncodeScan( PRBool appleSingleEncode, nsIFile *fileLoc, const char *pName, PRUint8 * pBuf, PRUint32 sz)
{
  CleanUpEncodeScan();
  m_isAppleSingle = appleSingleEncode;
  m_encodeScanState = kBeginAppleSingle;
  m_pInputFile = do_QueryInterface(fileLoc);
  m_useFileName = pName;
  m_pBuf = pBuf;
  m_bufSz = sz;
  if (!m_isAppleSingle)
        {
    if (!m_inputStream)
                {
                  nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(m_inputStream), m_pInputFile);
                  NS_ENSURE_SUCCESS(rv, PR_FALSE);
    }

    InitScan( m_inputStream, pBuf, sz);
  }
  else {
  #ifdef _MAC_IMPORT_CODE
    // Fill in the file sizes
    m_resourceForkSize = fileLoc.GetMacFileSize( UFileLocation::eResourceFork);
    m_dataForkSize = fileLoc.GetMacFileSize( UFileLocation::eDataFork);
  #endif
  }

  return( PR_TRUE);
}

void nsImportEncodeScan::CleanUpEncodeScan( void)
{
  m_pInputStream->Close();
  m_pInputStream = nsnull;
  m_pInputFile = nsnull;
}


// 26 + 12 per entry

void nsImportEncodeScan::FillInEntries( int numEntries)
{
#ifdef _MAC_IMPORT_CODE
  int    len = m_useFileName.GetLength();
  if (len < 32)
    len = 32;
  long  entry[3];
  long  fileOffset = 26 + (12 * numEntries);
  entry[0] = 3;
  entry[1] = fileOffset;
  entry[2] = m_useFileName.GetLength();
  fileOffset += len;
  MemCpy( m_pBuf + m_bytesInBuf, entry, 12);
  m_bytesInBuf += 12;


  Str255  comment;
  comment[0] = 0;
  OSErr err = FSpDTGetComment( m_inputFileLoc, comment);
  if (comment[0] > 200)
    comment[0] = 200;
  entry[0] = 4;
  entry[1] = fileOffset;
  entry[2] = comment[0];
  fileOffset += 200;
  MemCpy( m_pBuf + m_bytesInBuf, entry, 12);
  m_bytesInBuf += 12;


  entry[0] = 8;
  entry[1] = fileOffset;
  entry[2] = 16;
  fileOffset += 16;
  MemCpy( m_pBuf + m_bytesInBuf, entry, 12);
  m_bytesInBuf += 12;

  entry[0] = 9;
  entry[1] = fileOffset;
  entry[2] = 32;
  fileOffset += 32;
  MemCpy( m_pBuf + m_bytesInBuf, entry, 12);
  m_bytesInBuf += 12;


  entry[0] = 10;
  entry[1] = fileOffset;
  entry[2] = 4;
  fileOffset += 4;
  MemCpy( m_pBuf + m_bytesInBuf, entry, 12);
  m_bytesInBuf += 12;

  if (m_resourceForkSize) {
    entry[0] = 2;
    entry[1] = fileOffset;
    entry[2] = m_resourceForkSize;
    fileOffset += m_resourceForkSize;
    MemCpy( m_pBuf + m_bytesInBuf, entry, 12);
    m_bytesInBuf += 12;
  }

  if (m_dataForkSize) {
    entry[0] = 1;
    entry[1] = fileOffset;
    entry[2] = m_dataForkSize;
    fileOffset += m_dataForkSize;
    MemCpy( m_pBuf + m_bytesInBuf, entry, 12);
    m_bytesInBuf += 12;
  }

#endif
}

PRBool nsImportEncodeScan::AddEntries( void)
{
#ifdef _MAC_IMPORT_CODE
  if (!g2000Secs) {
    g2000Secs = Get2000Secs();
    gGMTDelta = GetGmtDelta();
  }
  MemCpy( m_pBuf + m_bytesInBuf, (PC_S8) m_useFileName, m_useFileName.GetLength());
  m_bytesInBuf += m_useFileName.GetLength();
  if (m_useFileName.GetLength() < 32) {
    int len = m_useFileName.GetLength();
    while (len < 32) {
      *((P_S8)m_pBuf + m_bytesInBuf) = 0;
      m_bytesInBuf++;
      len++;
    }
  }

  Str255  comment;
  comment[0] = 0;
  OSErr err = FSpDTGetComment( m_inputFileLoc, comment);
  comment[0] = 200;
  MemCpy( m_pBuf + m_bytesInBuf, &(comment[1]), comment[0]);
  m_bytesInBuf += comment[0];

  long  dates[4];
  dates[0] = gCatInfoPB.hFileInfo.ioFlCrDat;
  dates[1] = gCatInfoPB.hFileInfo.ioFlMdDat;
  dates[2] = gCatInfoPB.hFileInfo.ioFlBkDat;
  dates[3] = 0x80000000;
  for (short i = 0; i < 3; i++) {
    dates[i] -= g2000Secs;
    dates[i] += gGMTDelta;
  }
  MemCpy( m_pBuf + m_bytesInBuf, dates, 16);
  m_bytesInBuf += 16;


  FInfo  fInfo = gCatInfoPB.hFileInfo.ioFlFndrInfo;
  FXInfo  fxInfo = gCatInfoPB.hFileInfo.ioFlXFndrInfo;
  fInfo.fdFlags = 0;
  fInfo.fdLocation.h = 0;
  fInfo.fdLocation.v = 0;
  fInfo.fdFldr = 0;
  MemSet( &fxInfo, 0, sizeof( fxInfo));
  MemCpy( m_pBuf + m_bytesInBuf, &fInfo, 16);
  m_bytesInBuf += 16;
  MemCpy( m_pBuf + m_bytesInBuf, &fxInfo, 16);
  m_bytesInBuf += 16;


  dates[0] = 0;
  if ((gCatInfoPB.hFileInfo.ioFlAttrib & 1) != 0)
    dates[0] |= 1;
  MemCpy( m_pBuf + m_bytesInBuf, dates, 4);
  m_bytesInBuf += 4;


#endif
  return( PR_TRUE);
}

PRBool nsImportEncodeScan::Scan( PRBool *pDone)
{
  nsresult  rv;

  *pDone = PR_FALSE;
  if (m_isAppleSingle) {
    // Stuff the buffer with things needed to encode the file...
    // then just allow UScanFile to handle each fork, but be careful
    // when handling eof.
    switch( m_encodeScanState) {
      case kBeginAppleSingle: {
#ifdef _MAC_IMPORT_CODE
        OSErr err = GetCatInfoNoName( m_inputFileLoc.GetVRefNum(), m_inputFileLoc.GetParID(), m_inputFileLoc.GetFileNamePtr(), &gCatInfoPB);
        if (err != noErr)
          return( FALSE);
#endif
        m_eof = PR_FALSE;
        m_pos = 0;
        memcpy( m_pBuf, gAppleSingleHeader, kAppleSingleHeaderSize);
        m_bytesInBuf = kAppleSingleHeaderSize;
        int numEntries = 5;
        if (m_dataForkSize)
          numEntries++;
        if (m_resourceForkSize)
          numEntries++;
        memcpy( m_pBuf + m_bytesInBuf, &numEntries, sizeof( numEntries));
        m_bytesInBuf += sizeof( numEntries);
        FillInEntries( numEntries);
        m_encodeScanState = kAddEntries;
        return( ScanBuffer( pDone));
      }
      break;

      case kBeginDataFork: {
        if (!m_dataForkSize) {
          m_encodeScanState = kDoneWithFile;
          return( PR_TRUE);
        }
        // Initialize the scan of the data fork...
        if (!m_inputStream)
                                {
                                  rv = NS_NewLocalFileInputStream(getter_AddRefs(m_inputStream), m_pInputFile);
                                  NS_ENSURE_SUCCESS(rv, PR_FALSE);
                                }
        m_encodeScanState = kScanningDataFork;
        return( PR_TRUE);
      }
      break;

      case kScanningDataFork: {
        PRBool result = FillBufferFromFile();
        if (!result)
          return( PR_FALSE);
        if (m_eof) {
          m_eof = PR_FALSE;
          result = ScanBuffer( pDone);
          if (!result)
            return( PR_FALSE);
          m_inputStream->Close();
                                        m_inputStream = nsnull;
          m_encodeScanState = kDoneWithFile;
          return( PR_TRUE);
        }
        else
          return( ScanBuffer( pDone));
      }
      break;

      case kScanningRsrcFork: {
        PRBool result = FillBufferFromFile();
        if (!result)
          return( PR_FALSE);
        if (m_eof) {
          m_eof = PR_FALSE;
          result = ScanBuffer( pDone);
          if (!result)
            return( PR_FALSE);
          m_inputStream->Close();
                                        m_inputStream = nsnull;
          m_encodeScanState = kBeginDataFork;
          return( PR_TRUE);
        }
        else
          return( ScanBuffer( pDone));
      }
      break;

      case kBeginResourceFork: {
        if (!m_resourceForkSize) {
          m_encodeScanState = kBeginDataFork;
          return( PR_TRUE);
        }
        /*
        // FIXME: Open the resource fork on the Mac!!!
        m_fH = UFile::OpenRsrcFileRead( m_inputFileLoc);
        if (m_fH == TR_FILE_ERROR)
          return( FALSE);
        */
        m_encodeScanState = kScanningRsrcFork;
        return( PR_TRUE);
      }
      break;

      case kAddEntries: {
        ShiftBuffer();
        if (!AddEntries())
          return( PR_FALSE);
        m_encodeScanState = kBeginResourceFork;
        return( ScanBuffer( pDone));
      }
      break;

      case kDoneWithFile: {
        ShiftBuffer();
        m_eof = PR_TRUE;
        if (!ScanBuffer( pDone))
          return( PR_FALSE);
        *pDone = PR_TRUE;
        return( PR_TRUE);
      }
      break;
    }

  }
  else
    return( nsImportScanFile::Scan( pDone));

  return( PR_FALSE);
}