Logo Search packages:      
Sourcecode: harbour version File versions  Download package

bool CZipArchive::OpenNewFile ( CZipFileHeader header,
int  iLevel = Z_DEFAULT_COMPRESSION,
LPCTSTR  lpszFilePath = NULL,
DWORD  uInternal = 0 
)

Add a new file to the opened zip archive. The zip archive cannot be an existing disk spanning archive (existing at the moment of opening archive), because modifying such an archive is not possible (at least not with this version ).

Parameters:
header The structure that provides additional information about the added file. The following fields are valid:
  • m_uMethod - file compression method; can be 0 (storing) or Z_DEFLATE (deflating) otherwise Z_DEFLATE is assumed
  • m_uModDate, m_uModTime - Use CZipFileHeader::SetTime to set them. If lpszFilePath is not NULL this fields are overwritten and updated automatically. See CZipFileHeader::SetTime
  • m_uExternalAttr - Attributes of the file. If lpszFilePath is not NULL this field is overwritten and updated automatically. Use SetFileHeaderAttr to set them. See SetFileHeaderAttr.
  • m_szFileName - A filename (may be with path) to be stored inside archive to represent this file. See CZipFileHeader::SetFileName
  • m_szComment - A file comment. See CZipFileHeader::SetComment
  • m_pExtraField - LOCAL extra field, use SetExtraField after opening a new file, but before closing it to set the not local extra field in the header in the central directory. See SetExtraField
    Other fields are ignored - they are updated automatically. If the function returns true, system compatibility for this object is set to the correct value (the same as m_iArchiveSystCompatib), additionally if lpszFilePath was not NULL, the attributes and the time fields are filled with information retrieved from the file pointed by lpszFilePath.
iLevel The level of compression (-1, 0 - 9). The are several preset values for the compression level:
  • Z_DEFAULT_COMPRESSION : -1 (equals 6)
  • Z_NO_COMPRESSION : 0
  • Z_BEST_SPEED : 1
  • Z_BEST_COMPRESSION : 9
lpszFilePath The path to the file to retrieve date stamp and attributes from. These values are stored inside the archive.
uInternal for internal use only
Returns:
false in the following cases:
  • the lpszFilePath is not NULL and the file attributes and data was not correctly retrieved
  • a file is already opened for extraction or compression
  • archive is an existing disk span archive
  • maximum file count inside archive already reached (65536)
Note:
Throws exceptions.

Definition at line 518 of file ziparchive.cpp.

References CZipCentralDir::AddNewFile(), CheckForError(), compress, CZipCentralDir::ConvertFileName(), CryptCryptHeader(), CurrentFile(), CZipString::Format(), GetCount(), ZipPlatform::GetFileModTime(), CZipFileHeader::GetFileName(), CZipString::GetLength(), CZipFileHeader::GetSize(), CZipAutoBuffer::GetSize(), CZipArchive::CZipInternalInfo::Init(), IsClosed(), CZipFileHeader::IsDataDescr(), CZipFileHeader::IsDirectory(), CZipString::IsEmpty(), CZipFileHeader::IsEncrypted(), CZipPathComponent::IsSeparator(), CZipStorage::IsSpanMode(), CZipCentralDir::m_bConvertAfterOpen, m_centralDir, CZipPathComponent::m_cSeparator, m_iArchiveSystCompatib, m_iFileOpened, m_info, CZipArchive::CZipInternalInfo::m_pBuffer, CZipFileHeader::m_pszFileName, m_pszPassword, m_storage, CZipArchive::CZipInternalInfo::m_stream, CZipArchive::CZipInternalInfo::m_uComprLeft, CZipFileHeader::m_uMethod, CZipFileHeader::m_uModTime, MakeSpaceForReplace(), CZipFileHeader::PrepareData(), SetFileHeaderAttr(), CZipFileHeader::SetFileName(), CZipFileHeader::SetSystemCompatibility(), CZipFileHeader::SetTime(), ZipCompatibility::SlashBackslashChg(), ThrowError(), CZipException::tooLongFileName, CZipStorage::Write(), and CZipFileHeader::WriteLocal().

Referenced by AddNewFile().

{
      if (IsClosed())
      {
            TRACE(_T("%s(%i) : ZipArchive is closed.\n"),__FILE__,__LINE__);
            return false;
      }

      if (m_iFileOpened)
      {
            TRACE(_T("%s(%i) : A file already opened.\n"),__FILE__,__LINE__);
            return false;
      }

      if (m_storage.IsSpanMode() == -1)
      {
            TRACE(_T("%s(%i) : You cannot add files to the existing disk spannig archive.\n"),__FILE__,__LINE__);
            return false;
      }

      if (GetCount() ==(WORD)USHRT_MAX)
      {
            TRACE(_T("%s(%i) : Maximum file count inside archive reached.\n"),__FILE__,__LINE__);
            return false;
      }

      DWORD uAttr = 0; // ..compiler
      time_t ttime;
      if (lpszFilePath)
      {

            if (!ZipPlatform::GetFileAttr(lpszFilePath, uAttr))
                  // do not continue - if the file was a directory then not recognizing it will cause
                  // serious errors (need uAttr to recognize it)
                  return false;
            if (!ZipPlatform::GetFileModTime(lpszFilePath, ttime))
                  ttime = time(NULL);
      }

      m_info.Init();


      if (lpszFilePath)
      {
            header.SetTime(ttime);
            SetFileHeaderAttr(header, uAttr); // set system compatibility as well
      }
      else
            header.SetSystemCompatibility(m_iArchiveSystCompatib);

      CZipString szFileName = header.GetFileName();


      bool bIsDirectory = header.IsDirectory();
      if (bIsDirectory)
      {
            int iNameLen = szFileName.GetLength();
            if (!iNameLen || !CZipPathComponent::IsSeparator(szFileName[iNameLen-1]))
            {
                  szFileName += CZipPathComponent::m_cSeparator;
                  header.SetFileName(szFileName);
            }
      }

      if (szFileName.IsEmpty())
      {
            szFileName.Format(_T("file%i"), GetCount());
            header.SetFileName(szFileName);
      }

      // make sure that all slashes are correct (as the current system default)
      // because AddNewFile calls InsertFindFastElement if necessary and
      // the find array keeps all the files already converted to the current system standards
      // we do not perform Oem->Ansi here, because who would pass oem values here?
      //
      ZipCompatibility::SlashBackslashChg(header.m_pszFileName, true);

      bool bEncrypted = m_pszPassword.GetSize() != 0;

#ifdef _DEBUG
      if (bIsDirectory && bEncrypted)
      TRACE(_T("%s(%i) : Encrypting a directory. It's pointless.\n\
      Clear the password before adding a directory.\n"),__FILE__,__LINE__);
#endif



      int iReplaceIndex = -1;
      bool bReplace = (iLevel & 0xffff) == ZIP_COMPR_REPL_SIGN;
      if (bReplace)
      {
            int iMask = ZIP_COMPR_REPL_MASK;
            iReplaceIndex = (iLevel & iMask) >> 16;
            iLevel = (char)(iLevel & ~iMask);
            ASSERT(iLevel == 0);
      }
      else
            uInternal = 0;

      if (iLevel < -1 || iLevel > 9)
            iLevel = -1;

      if (!header.PrepareData(iLevel, m_storage.IsSpanMode() == 1, bEncrypted))
            ThrowError(CZipException::tooLongFileName);

      if (bReplace)
      {
            uInternal += header.GetSize(true);
            if (header.IsEncrypted())
                  uInternal += ZIPARCHIVE_ENCR_HEADER_LEN;
            if (header.IsDataDescr())
                  uInternal += ZIPARCHIVE_DATADESCRIPTOR_LEN + 4; // CZipCentralDir::CloseNewFile
      }
      m_centralDir.AddNewFile(header, iReplaceIndex);
      if (bReplace)
            MakeSpaceForReplace(iReplaceIndex, uInternal, szFileName);

      // this ensures the conversion will take place anyway (must take because we are going
      //    to write the local header in a moment
      m_centralDir.ConvertFileName(false, m_centralDir.m_bConvertAfterOpen);

      CurrentFile()->WriteLocal(m_storage);

      // we have written the local header, but if we keep filenames not converted
      // in memory , we have to restore the non-converted value
      if (m_centralDir.m_bConvertAfterOpen)
            CurrentFile()->SetFileName(szFileName);

      if (bEncrypted)
      {
            CZipAutoBuffer buf(ZIPARCHIVE_ENCR_HEADER_LEN);
            // use pseudo-crc since we don't know it yet
            CryptCryptHeader((long)header.m_uModTime << 16, buf);
            m_storage.Write(buf, ZIPARCHIVE_ENCR_HEADER_LEN, false);
      }


      m_info.m_uComprLeft = 0;
    m_info.m_stream.avail_in = (uInt)0;
    m_info.m_stream.avail_out = (uInt)m_info.m_pBuffer.GetSize();
    m_info.m_stream.next_out = (Bytef*)(char*)m_info.m_pBuffer;
    m_info.m_stream.total_in = 0;
    m_info.m_stream.total_out = 0;

      if (bIsDirectory && (CurrentFile()->m_uMethod != 0))
            CurrentFile()->m_uMethod = 0;

      if (CurrentFile()->m_uMethod == Z_DEFLATED)
    {
//        m_info.m_stream.opaque = m_bDetectZlibMemoryLeaks ? &m_list : 0;

        int err = deflateInit2(&m_info.m_stream, iLevel,
                  Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);

            CheckForError(err);
    }
      m_iFileOpened = compress;
      return true;
}


Generated by  Doxygen 1.6.0   Back to index