hbziparch

Top  Previous  Next

c:\harbour\contrib\hbziparch
hbxdirec.c
TypeFunctionSourceLine
STATIC VOIDhb_fsGrabDirectory( PHB_ITEM pDir, const char * szDirSpec, USHORT uiMask, PHB_FNAME fDirSpec, BOOL bFullPath, BOOL bDirOnly )
static void hb_fsGrabDirectory( PHB_ITEM pDir, const char * szDirSpec, USHORT uiMask, PHB_FNAME fDirSpec, BOOL bFullPath, BOOL bDirOnly )
{
   PHB_FFIND ffind;

   /* Get the file list */
   if( ( ffind = hb_fsFindFirst( szDirSpec, uiMask ) ) != NULL )
   {
      PHB_ITEM pSubarray;

      pSubarray = hb_itemNew( NULL );

      do
      {
         if( ( !bDirOnly || ( ffind->attr & HB_FA_DIRECTORY ) != 0 ) &&
             !( ( ( uiMask & HB_FA_HIDDEN    ) == 0 && ( ffind->attr & HB_FA_HIDDEN    ) != 0 ) ||
                ( ( uiMask & HB_FA_SYSTEM    ) == 0 && ( ffind->attr & HB_FA_SYSTEM    ) != 0 ) ||
                ( ( uiMask & HB_FA_LABEL     ) == 0 && ( ffind->attr & HB_FA_LABEL     ) != 0 ) ||
                ( ( uiMask & HB_FA_DIRECTORY ) == 0 && ( ffind->attr & HB_FA_DIRECTORY ) != 0 ) ) )
         {
            char buffer[ 32 ];

            hb_arrayNew( pSubarray, 5 );
            if( bFullPath )
            {
               char * szFullName = hb_xstrcpy( NULL, fDirSpec->szPath ? fDirSpec->szPath : "", ffind->szName, NULL );
               hb_itemPutC( hb_arrayGetItemPtr( pSubarray, F_NAME ), szFullName );
               hb_xfree( szFullName );
            }
            else
               hb_itemPutC( hb_arrayGetItemPtr( pSubarray, F_NAME), ffind->szName );

            hb_itemPutNInt( hb_arrayGetItemPtr( pSubarray, F_SIZE ), ffind->size );
            hb_itemPutDL( hb_arrayGetItemPtr( pSubarray, F_DATE ), ffind->lDate );
            hb_itemPutC( hb_arrayGetItemPtr( pSubarray, F_TIME ), ffind->szTime );
            hb_itemPutC( hb_arrayGetItemPtr( pSubarray, F_ATTR ), hb_fsAttrDecode( ffind->attr, buffer ) );

            if( !bDirOnly || ( ffind->attr & HB_FA_DIRECTORY ) != 0 )
               hb_arrayAddForward( pDir, pSubarray );
         }
      }
      while( hb_fsFindNext( ffind ) );

      hb_itemRelease( pSubarray );

      hb_fsFindClose( ffind );
   }
}
hbxdirec.c60
VOID HB_EXPORThb_fsDirectory( PHB_ITEM pDir, char * szSkleton, char * szAttributes, BOOL bDirOnly, BOOL bFullPath )
void HB_EXPORT hb_fsDirectory( PHB_ITEM pDir, char * szSkleton, char * szAttributes, BOOL bDirOnly, BOOL bFullPath )
{
   USHORT uiMask;
   USHORT uiMaskNoLabel;
   BYTE * szDirSpec;

/*
#if defined(__MINGW32__) || ( defined(_MSC_VER) && _MSC_VER >= 910 )
   PHB_ITEM pEightDotThree = hb_param( 3, HB_IT_LOGICAL );
   BOOL     bEightDotThree = pEightDotThree ? hb_itemGetL( pEightDotThree ) : FALSE; // Do we want 8.3 support?
#endif
*/

   PHB_FNAME pDirSpec = NULL;
   BOOL bAlloc = FALSE;

   /* Get the passed attributes and convert them to Harbour Flags */
   uiMask = HB_FA_ARCHIVE
          | HB_FA_READONLY
          | HB_FA_NORMAL
          | HB_FA_DEVICE
          | HB_FA_TEMPORARY
          | HB_FA_SPARSE
          | HB_FA_REPARSE
          | HB_FA_COMPRESSED
          | HB_FA_OFFLINE
          | HB_FA_NOTINDEXED
          | HB_FA_ENCRYPTED
          | HB_FA_VOLCOMP;

   uiMaskNoLabel = uiMask;

   hb_arrayNew( pDir, 0 );

   if( bDirOnly )
      szAttributes = "D";

   if( szAttributes && strlen( szAttributes ) > 0 )
   {
      if ( ( uiMask |= hb_fsAttrEncode( szAttributes ) ) & HB_FA_LABEL )
      {
         /* NOTE: This is Clipper Doc compatible. (not operationally) */
         uiMask = HB_FA_LABEL;
      }
   }

   if ( szSkleton && strlen( szSkleton ) > 0 )
      szDirSpec = hb_fsNameConv( ( BYTE * ) szSkleton, &bAlloc );
   else
      szDirSpec = ( BYTE * ) OS_FILE_MASK;

   if( bDirOnly || bFullPath )
   {
      if ( ( pDirSpec = hb_fsFNameSplit( ( char * ) szDirSpec ) ) !=NULL )
      {
         if( pDirSpec->szDrive )
            hb_fsChDrv( ( BYTE ) ( pDirSpec->szDrive[ 0 ] - 'A' ) );

         if( pDirSpec->szPath )
            hb_fsChDir( ( BYTE * ) pDirSpec->szPath );
      }
   }

   /* Get the file list */
   hb_fsGrabDirectory( pDir, ( const char * ) szDirSpec, uiMask, pDirSpec, bFullPath, bDirOnly );

   if( uiMask == HB_FA_LABEL )
   {
      uiMaskNoLabel |= hb_fsAttrEncode( szAttributes );
      uiMaskNoLabel &= ~HB_FA_LABEL;
      hb_fsGrabDirectory( pDir, ( const char * ) szDirSpec, uiMaskNoLabel, pDirSpec, bFullPath, bDirOnly );
   }

   if( pDirSpec )
      hb_xfree( pDirSpec );

   if( bAlloc )
      hb_xfree( szDirSpec );
}
hbxdirec.c108
hbziparc.c
TypeFunctionSourceLine
STATIC INTGetFileAttributes( char * szEntry )
static int GetFileAttributes( char * szEntry )
{
   struct stat sStat;
   stat( szEntry, &sStat );
   return ( int ) sStat.st_mode;
}
hbziparc.c87
STATIC VOIDSetFileAttributes( char * szEntry, ULONG ulAttr)
static void SetFileAttributes( char * szEntry, ULONG ulAttr)
{
   chmod( szEntry, ulAttr );
}
hbziparc.c94
STATIC VOIDResetAttribs( void )
static void ResetAttribs( void )
{
   ULONG ulAtt, ulZipLen = hb_arrayLen( s_FileToZip );

   for( ulAtt = 0; ulAtt < ulZipLen; ulAtt++ )
   {
      char * szFile = hb_arrayGetC( s_FileToZip, ulAtt + 1 );
      int iAttr = hb_arrayGetNI( s_FileAttribs, ulAtt + 1 );
      SetFileAttributes( szFile, iAttr );
      hb_xfree( szFile );
   }

   hb_itemRelease( s_FileAttribs );
   hb_itemRelease( s_FileToZip );
}
hbziparc.c101
STATIC VOIDUnzipCreateArray( char *szSkleton, int uiOption)
static void UnzipCreateArray( char *szSkleton, int uiOption)
{
   int ul;
   char * szEntry;
   PHB_ITEM pZipEntry;
   PHB_ITEM Temp;
   BOOL bOkAdd;
   int ulLen = hb_arrayLen(hbza_ZipArray);
   char sRegEx[ _POSIX_PATH_MAX + _POSIX_PATH_MAX + 1 ];

   for( ul = 0; ul < ulLen; ul++ )
   {
      bOkAdd = TRUE;
      pZipEntry = hb_arrayGetItemPtr( hbza_ZipArray, ul + 1 );
      szEntry = hb_arrayGetC( pZipEntry, 1 );

      if( szSkleton )
         bOkAdd = hb_strMatchFile( (const char *) szEntry, (const char *) sRegEx );

      if( !bOkAdd )
      {
         PHB_FNAME pFileName = hb_fsFNameSplit( szEntry );

         if( pFileName->szName )
         {
            char * szFile = ( char * ) hb_xgrab( _POSIX_PATH_MAX + 1 );
            pFileName->szPath = ( char * ) "";
            hb_fsFNameMerge( szFile, pFileName );
            bOkAdd = hb_stricmp( szSkleton, szFile ) == 0 ? 1 : 0;
            hb_xfree( szFile );

            if( ! bOkAdd )
               bOkAdd = hb_stricmp( szSkleton, szEntry ) == 0 ? 1 : 0;

         }

         hb_xfree( pFileName );
      }

      if( bOkAdd )
      {
         if( uiOption == 1 )
         {
            Temp = hb_itemNew( NULL ) ;
            hb_arrayAddForward( s_UnzipFiles, hb_itemPutC( Temp, szEntry ) );
            hb_itemRelease( Temp );
         }
         else
         {
            Temp = hb_itemNew( NULL ) ;
            hb_arrayAddForward( s_DelZip, hb_itemPutC( Temp, szEntry ) );
            hb_itemRelease( Temp );
         }
      }

      hb_xfree( szEntry );
   }
}
hbziparc.c117
STATIC BOOLZipTestExclude ( char *szEntry )
static BOOL ZipTestExclude ( char *szEntry )
{
   int uiEx;
   BOOL bNotFound = TRUE;
   int uiExLen = hb_arrayLen(s_ExcludeFile);

   for( uiEx = 0; uiEx < uiExLen; uiEx++ )
   {
      char * szExclude = hb_arrayGetC( s_ExcludeFile, uiEx + 1 );
      if( strcmp ( szExclude, hb_strupr( szEntry ) ) == 0 )
      {
         hb_xfree( szExclude );
         bNotFound = FALSE;
         break;
      }
      hb_xfree( szExclude );
   }

   return bNotFound;
}
hbziparc.c176
STATIC VOIDZipCreateExclude( PHB_ITEM pExclude )
static void ZipCreateExclude( PHB_ITEM pExclude )
{
   PHB_ITEM ExTmp;

   s_ExcludeFile = hb_itemArrayNew(0);

   if( pExclude == NULL )
      return;

   if( HB_IS_STRING( pExclude ) )
   {
      if( hb_itemGetCLen( pExclude ) == 0 )
         return;

      if( strchr( hb_itemGetCPtr( pExclude ), '*' ) != NULL || strchr( hb_itemGetCPtr( pExclude ), '?' ) != NULL )
      {
         PHB_ITEM WildFile;
         PHB_ITEM pDirEntry;
         int uiLen;
         int ui;

         WildFile = hb_itemNew( NULL );

         hb_fsDirectory( WildFile, hb_itemGetCPtr( pExclude ), NULL, 0, TRUE );
         uiLen = hb_arrayLen( WildFile );

         for( ui = 0; ui < uiLen; ui++ )
         {
            char * szEntry;
            pDirEntry = hb_arrayGetItemPtr( WildFile, ui + 1 );
            szEntry = hb_arrayGetC( pDirEntry, 1 );

            if( szEntry )
            {
               ExTmp = hb_itemPutC( NULL, hb_strupr( szEntry ) );
               hb_arrayAddForward( s_ExcludeFile, ExTmp );
               hb_xfree( szEntry );
               hb_itemRelease( ExTmp );
            }
         }

         hb_itemRelease( WildFile );
      }
      else
      {
         ExTmp = hb_itemPutC( NULL, hb_itemGetCPtr( pExclude ) );
         hb_arrayAddForward( s_ExcludeFile, ExTmp );
         hb_itemRelease( ExTmp ) ;
      }
   }
   else if( HB_IS_ARRAY( pExclude ) )
   {
      int ux;
      int ufx = hb_arrayLen( pExclude );
      char * szExclude;
      PHB_ITEM WildFile;
      PHB_ITEM pDirEntry;

      WildFile = hb_itemNew( NULL );

      if( ufx == 0 )
         return;

      for( ux = 0; ux < ufx; ux++ )
      {
         szExclude = hb_arrayGetC( pExclude, ux + 1 );

         if( szExclude )
         {
            if( strchr( szExclude, '*' ) != NULL || strchr( szExclude, '?' ) != NULL )
            {
               int uiW, uiWLen;
               char *szEntry;

               hb_fsDirectory( WildFile, szExclude, NULL, 0, TRUE );
               uiWLen = hb_arrayLen( WildFile );

               for( uiW = 0; uiW < uiWLen; uiW++ )
               {
                  pDirEntry = hb_arrayGetItemPtr( WildFile, uiW + 1 );
                  szEntry = hb_arrayGetC( pDirEntry, 1 );
                  ExTmp = hb_itemNew( NULL);
                  hb_arrayAddForward( s_ExcludeFile, hb_itemPutC( ExTmp, szEntry ));
                  hb_itemRelease( ExTmp );
                  hb_xfree( szEntry );
               }
            }
            else
            {
               ExTmp = hb_itemNew( NULL );
               hb_arrayAddForward( s_ExcludeFile, hb_itemPutC( ExTmp, szExclude ) );
               hb_itemRelease( ExTmp );
            }

            hb_xfree( szExclude );
         }
      }

      hb_itemRelease( WildFile );
   }
}
hbziparc.c197
STATIC VOIDZipCreateArray( PHB_ITEM pParam, BYTE *pCurDir, BOOL bFullPath )
static void ZipCreateArray( PHB_ITEM pParam, BYTE *pCurDir, BOOL bFullPath )    /* bFullPath by JGS */
{
   PHB_ITEM pDirEntry, Temp, TempArray;
   PHB_ITEM WildFile = hb_itemNew( NULL );
   int ul, ulLen, ulArr, ulLenArr;

   s_FileToZip = hb_itemArrayNew(0);
   s_FileAttribs = hb_itemArrayNew(0);

   if( HB_IS_STRING( pParam ) )
   {
      TempArray = hb_itemArrayNew( 0 );
      Temp = hb_itemPutC( NULL, hb_itemGetCPtr( pParam ) );
      hb_arrayAddForward( TempArray, Temp );
      hb_itemRelease( Temp );
   }
   else
   {
      TempArray = hb_arrayClone( pParam );
   }

   ulLenArr = hb_arrayLen( TempArray );

   for( ulArr = 0; ulArr < ulLenArr; ulArr++ )
   {
      char *szArrEntry = hb_arrayGetC( TempArray, ulArr + 1 );

      if( szArrEntry )
      {
         if( strchr( szArrEntry, '*' ) != NULL || strchr( szArrEntry, '?' ) != NULL )
         {
         #if defined(HB_WIN32_IO)
            /* by JGS if don't gave path or there is a relative path add current dir ! */
            PHB_FNAME fDirSpec = hb_fsFNameSplit( (char*) szArrEntry );

            if( ( pCurDir ) && ( fDirSpec != NULL ) &&
                 ! ( fDirSpec->szDrive ) && ( fDirSpec->szPath ) && ( fDirSpec->szPath[0] != OS_PATH_DELIMITER ) )
         #else
            /* if don't gave path add current dir ! */
            if( ( pCurDir ) && ( ! strchr( szArrEntry, OS_PATH_DELIMITER ) ) )
         #endif
            {
               char * szTemp = szArrEntry ;
               szArrEntry = hb_xstrcpy( NULL, (char *) pCurDir, OS_PATH_DELIMITER_STRING, szTemp, NULL );
               hb_xfree( szTemp );
            }

            hb_fsDirectory(WildFile,szArrEntry,NULL,0,bFullPath ); /* bFullPath by JGS */
            ulLen = hb_arrayLen(WildFile);

            for( ul = 0; ul < ulLen; ul++ )
            {
               char * szEntry;
               pDirEntry = hb_arrayGetItemPtr( WildFile, ul + 1 );
               szEntry = hb_arrayGetC( pDirEntry, 1 );

               /* by JGS */
               #if defined(HB_WIN32_IO)
                  if(! ( bFullPath ) && ( fDirSpec != NULL ) && ( fDirSpec->szPath ) )
                  {
                     char * szFile = szEntry;
                     szEntry = hb_xstrcpy( NULL, fDirSpec->szPath, szFile, NULL );
                     hb_xfree( szFile );
                  }
               #endif
               /* by JGS */

               if( ZipTestExclude ( szEntry ) )
               {
                  Temp= hb_itemNew(NULL);
                  hb_arrayAddForward( s_FileToZip, hb_itemPutC( Temp, szEntry ) );
                  hb_itemRelease( Temp ) ;
                  Temp= hb_itemNew(NULL);
                  hb_arrayAddForward( s_FileAttribs, hb_itemPutNI( Temp, GetFileAttributes( szEntry ) ) );
                  hb_itemRelease( Temp ) ;
                  #if defined(HB_OS_LINUX)
                  SetFileAttributes( szEntry, 0777 );
                  #else
                  SetFileAttributes( szEntry, FA_ARCH );
                  #endif
               }

               if( szEntry )
               {
                  hb_xfree( szEntry );
               }
            }

            /* by JGS */
            #if defined(HB_WIN32_IO)
               if( fDirSpec )
               {
                  hb_xfree( fDirSpec );
               }
            #endif

            hb_itemClear( WildFile );
            /* by JGS */
         }
         else
         {
            Temp = hb_itemPutC( NULL, szArrEntry ) ;
            hb_arrayAddForward( s_FileToZip, Temp );
            hb_itemRelease( Temp ) ;
            Temp = hb_itemPutNI( NULL, GetFileAttributes( szArrEntry ) );
            hb_arrayAddForward( s_FileAttribs, Temp );
            hb_itemRelease( Temp ) ;

                  #if defined(HB_OS_LINUX)
                  SetFileAttributes( szArrEntry, 0777 );
                  #else
                  SetFileAttributes( szArrEntry, FA_ARCH );
                  #endif
         }

         hb_xfree( szArrEntry );
      }
   }

   hb_itemRelease( WildFile );
   hb_itemRelease( TempArray );
}

hbziparc.c299
HB_FUNCHB_ZIPFILE(void)
HB_FUNC( HB_ZIPFILE )
{
   BOOL bRet = FALSE;

   if( ISCHAR( 1 ) )
   {
      PHB_ITEM pParam = hb_param( 2, HB_IT_STRING | HB_IT_ARRAY );

      if( pParam )
      {
         char szFile[ _POSIX_PATH_MAX + 1 ];
         PHB_ITEM pExclude = hb_param( 10, HB_IT_STRING | HB_IT_ARRAY );
         BYTE *pCurDir;
         char *szZipFileName;

         /* by JGS */
         BOOL bFullPath = TRUE;
         #if defined(HB_WIN32_IO)
            if( ISLOG( 11 ) )
            {
               bFullPath = hb_parl( 11 );
            }
         #endif
         /* by JGS */

         if( ! ISNIL( 4 ) && ! ISBLOCK( 4 ) )
         {
            hb_errRT_BASE_SubstR( EG_ARG, 2017, "Invalid Codeblock ","hb_zipfile",
                                  4 ,hb_paramError( 1 ),
                                  hb_paramError( 2 ),
                                  hb_paramError( 3 ),
                                  hb_paramError( 4 ) );
            return;
         }

         pCurDir = ( BYTE * ) hb_xstrcpy( NULL, OS_PATH_DELIMITER_STRING, ( const char * )hb_fsCurDir( 0 ) , NULL );

         /* Always needs to create an array */
         ZipCreateExclude( pExclude );

         ZipCreateArray( pParam, pCurDir, bFullPath );  /* bFullPath by JGS */

         hb_fsChDir( pCurDir ) ;

         if( ! strchr( hb_parc( 1 ), OS_PATH_DELIMITER ) )
         {
            hb_strncpy( szFile, (char *) pCurDir, sizeof( szFile ) - 1 );
            hb_strncat( szFile, OS_PATH_DELIMITER_STRING, sizeof( szFile ) - 1 );
            hb_strncat( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );
         }
         else
            hb_strncpy( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );

         hb_xfree( pCurDir) ;
         szZipFileName = hb___CheckFile( szFile );

         if( hb_arrayLen(s_FileToZip) > 0 )
         {
            PHB_ITEM pProgress = ISBLOCK( 9 ) ? hb_itemNew( hb_param( 9, HB_IT_BLOCK ) ) : hb_itemNew( NULL );
            bRet = hb_CompressFile( szZipFileName,
                                    s_FileToZip,
                                    ISNUM( 3 ) ? hb_parni( 3 ) : ( -1 ),
                                    hb_param( 4, HB_IT_BLOCK ),
                                    ISLOG( 5 ) ? hb_parl( 5 ) : FALSE,
                                    ISCHAR( 6 ) ? hb_parc( 6 ) : NULL,
                                    ISLOG( 7 ) ? hb_parl( 7 ) : FALSE,
                                    ISLOG( 8 ) ? hb_parl( 8 ) : FALSE,
                                    pProgress );
            ResetAttribs();
            hb_itemRelease( pProgress );
         }

         hb_xfree( szZipFileName );
         hb_itemRelease(s_ExcludeFile);
      }
   }

   hb_retl( bRet );
}
hbziparc.c520
HB_FUNCHB_GETFILESINZIP(void)
HB_FUNC( HB_GETFILESINZIP )
{
   if( ISCHAR( 1 ) )
   {
      char szFile[ _POSIX_PATH_MAX + 1 ];
      char *szZipFileName;
      PHB_ITEM pArray;

      hb_strncpy( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );

      szZipFileName = hb___CheckFile( szFile );

      pArray = hb___GetFileNamesFromZip( szZipFileName,
                                ISLOG( 2 ) ? hb_parl( 2 ) : FALSE );

      hb_itemReturn( pArray );
      hb_itemRelease( pArray ) ;
      hb_xfree( szZipFileName );
   }
}
hbziparc.c600
HB_FUNCHB_ZIPWITHPASSWORD(void)
HB_FUNC( HB_ZIPWITHPASSWORD )
{
   hb_retl( hb_IsPassWord( hb_parc( 1 ) ) );
}
hbziparc.c621
HB_FUNCHB_GETFILECOUNT(void)
HB_FUNC( HB_GETFILECOUNT )
{
   int iRet = 0;

   if( ISCHAR( 1 ) )
   {
      char szFile[ _POSIX_PATH_MAX + 1 ];
      char * szZipFileName;

      hb_strncpy( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );

      szZipFileName = hb___CheckFile( szFile );

      iRet = hb___GetNumberofFilestoUnzip( szZipFileName );

      hb_xfree( szZipFileName );
   }

   hb_retni( iRet );
}

hbziparc.c626
HB_FUNCHB_ZIPFILEBYTDSPAN(void)
HB_FUNC( HB_ZIPFILEBYTDSPAN )
{
   BOOL bRet = FALSE;

   if( ISCHAR( 1 ) )
   {
      PHB_ITEM pParam = hb_param( 2, HB_IT_STRING | HB_IT_ARRAY );

      if( pParam )
      {
         char szFile[ _POSIX_PATH_MAX + 1 ];
         PHB_ITEM pExclude = hb_param( 11, HB_IT_STRING | HB_IT_ARRAY );
         char *szZipFileName;
         BYTE *pCurDir;

         /* by JGS */
         BOOL bFullPath = TRUE;
         #if defined(HB_WIN32_IO)
            if( ISLOG( 12 ) )
            {
               bFullPath = hb_parl( 12 );
            }
         #endif
         /* by JGS */

         pCurDir = ( BYTE * )hb_xstrcpy( NULL, OS_PATH_DELIMITER_STRING, ( const char * )hb_fsCurDir( 0 ) , NULL );

         ZipCreateExclude( pExclude );

         ZipCreateArray( pParam, pCurDir, bFullPath );  /* bFullPath by JGS */

         hb_fsChDir( pCurDir );
         /* by JGS, wait until adding the directory to the file name if not specified
         hb_xfree( pCurDir );
         */
         if( ! strchr( szFile, OS_PATH_DELIMITER ) )
         {
            hb_strncpy( szFile, (char *) pCurDir, sizeof( szFile ) - 1 );
            hb_strncat( szFile, OS_PATH_DELIMITER_STRING, sizeof( szFile ) - 1 );
            hb_strncat( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );
         }
         else
            hb_strncpy( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );

         hb_xfree( pCurDir ); /* by JGS */
         szZipFileName = hb___CheckFile( szFile );

         if( hb_arrayLen(s_FileToZip) > 0 )
         {
            PHB_ITEM pProgress = ISBLOCK( 10 ) ? hb_itemNew( hb_param( 10, HB_IT_BLOCK ) ) : hb_itemNew( NULL );
            bRet = hb_CmpTdSpan( szZipFileName,
                                 s_FileToZip,
                                 ISNUM( 3 ) ? hb_parni( 3 ) : ( -1 ),
                                 hb_param( 4, HB_IT_BLOCK ),
                                 ISLOG( 5 ) ? hb_parl( 5 ) : FALSE,
                                 ISCHAR( 6 ) ? hb_parc( 6 ) : NULL,
                                 ISNUM( 7 ) ? hb_parni( 7 ) : 0,
                                 ISLOG( 8 ) ? hb_parl( 8 ) : FALSE,
                                 ISLOG( 9 ) ? hb_parl( 9 ) : FALSE,
                                 pProgress );
            ResetAttribs();
            hb_itemRelease( pProgress );
         }

         hb_xfree( szZipFileName );
         hb_itemRelease(s_ExcludeFile);
      }
   }

   hb_retl( bRet );
}

hbziparc.c743
HB_FUNCHB_ZIPFILEBYPKSPAN(void)
HB_FUNC( HB_ZIPFILEBYPKSPAN )
{
   BOOL bRet = FALSE;

   if( ISCHAR( 1 ) )
   {
      PHB_ITEM pParam = hb_param( 2, HB_IT_STRING | HB_IT_ARRAY );

      if( pParam )
      {
         char szFile[ _POSIX_PATH_MAX + 1 ];
         PHB_ITEM pExclude = hb_param( 10, HB_IT_STRING | HB_IT_ARRAY );
         char *szZipFileName;
         BYTE * pCurDir ;

         /* by JGS */
         BOOL bFullPath = TRUE;
         #if defined(HB_WIN32_IO)
            if( ISLOG( 11 ) )
            {
               bFullPath = hb_parl( 11 );
            }
         #endif
         /* by JGS */

         pCurDir = ( BYTE * )hb_xstrcpy( NULL, OS_PATH_DELIMITER_STRING, ( const char * )hb_fsCurDir( 0 ) , NULL );

         ZipCreateExclude( pExclude );

         ZipCreateArray( pParam, pCurDir, bFullPath );  /* bFullPath by JGS */

         hb_fsChDir( pCurDir ) ;
         /* by JGS, wait until adding the directory to the file name if not specified
         hb_xfree( pCurDir ) ;
         hb_strncpy( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );
         */
         if( ! strchr( szFile, OS_PATH_DELIMITER ) )
         {
            hb_strncpy( szFile, (char *) pCurDir, sizeof( szFile ) - 1 );
            hb_strncat( szFile, OS_PATH_DELIMITER_STRING, sizeof( szFile ) - 1 );
            hb_strncat( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );
         }
         else
            hb_strncpy( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );

         hb_xfree( pCurDir );
         /* by JGS */
         szZipFileName = hb___CheckFile( szFile );

         if( hb_arrayLen(s_FileToZip) > 0 )
         {
            PHB_ITEM pProgress = ISBLOCK( 9 ) ? hb_itemNew( hb_param( 9, HB_IT_BLOCK ) ) : hb_itemNew( NULL );
            bRet = hb_CmpPkSpan( szZipFileName,
                                 s_FileToZip,
                                 ISNUM( 3 ) ? hb_parni( 3 ) : ( -1 ),
                                 hb_param( 4, HB_IT_BLOCK ),
                                 ISLOG( 5 ) ? hb_parl( 5 ) : FALSE,
                                 ISCHAR( 6 ) ? hb_parc( 6 ) : NULL,
                                 ISLOG( 7 ) ? hb_parl( 7 ) : FALSE,
                                 ISLOG( 8 ) ? hb_parl( 8 ) : FALSE,
                                 pProgress );
            ResetAttribs();
            hb_itemRelease( pProgress );
         }

         hb_xfree( szZipFileName );
         hb_itemRelease(s_ExcludeFile);
      }
   }

   hb_retl( bRet );
}

hbziparc.c919
HB_FUNCHB_UNZIPFILE(void)
HB_FUNC( HB_UNZIPFILE )
{
   BOOL bRet = FALSE;

   if( ISCHAR( 1 ) && ( ISARRAY( 6 ) || ISCHAR( 6 ) ) )
   {
      char szFile[ _POSIX_PATH_MAX + 1 ];
      PHB_ITEM pUnzip = hb_param( 6, HB_IT_ANY );
      char *szZipFileName;
      BYTE *pCurDir;

      pCurDir = ( BYTE * ) hb_xstrcpy( NULL, OS_PATH_DELIMITER_STRING, ( const char * ) hb_fsCurDir( 0 ) , NULL );

      hb_strncpy( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );

      szZipFileName = hb___CheckFile( szFile );

      s_UnzipFiles = hb_itemArrayNew( 0 );

      if( hb_TestForPKS( szZipFileName ) <= 0 )
      {
         hb___GetFileNamesFromZip( szZipFileName, TRUE );

      if( pUnzip )
      {
         if( HB_IS_STRING( pUnzip ) )
         {
            UnzipCreateArray( hb_itemGetCPtr( pUnzip ), 1 );
         }
         else if( HB_IS_ARRAY( pUnzip ) )
         {
            int uiZ, uiZLen = hb_arrayLen(pUnzip);
            char *szUnzip;

            for( uiZ = 0; uiZ < uiZLen; uiZ++ )
            {
               szUnzip = hb_arrayGetC( pUnzip, uiZ + 1 );

               if( szUnzip )
               {
                  UnzipCreateArray( szUnzip, 1 );
                  hb_xfree( szUnzip );
               }
            }
         }
      }
      else
      {
//s.r. change "*.*" to "*" because file without extension were ignored
         UnzipCreateArray( (char*) "*", 1 );
      }

      if( hb_arrayLen(s_UnzipFiles) > 0 )
      {
         PHB_ITEM pProgress = ISBLOCK( 7 ) ? hb_itemNew( hb_param( 7 , HB_IT_BLOCK ) ) : hb_itemNew( NULL );
         bRet = hb_UnzipSel( szZipFileName,
                             hb_param( 2, HB_IT_BLOCK ),
                             ISLOG( 3 ) ? hb_parl( 3 ) : FALSE,
                             ISCHAR( 4 ) ? hb_parc( 4 ) : NULL,
                             ISCHAR( 5 ) ? hb_parc( 5 ) : ".\\",
                             s_UnzipFiles,
                             pProgress );
         hb_itemRelease( pProgress );
      }

      hb_xfree( szZipFileName );
      hb_itemRelease( s_UnzipFiles );
      hb_fsChDir( pCurDir ) ;
      hb_xfree( pCurDir ) ;
      hb_itemClear( hbza_ZipArray );
      hb_itemRelease( hbza_ZipArray );
    }
   }

   hb_retl( bRet );
}

hbziparc.c1060
HB_FUNCHB_SETDISKZIP(void)
HB_FUNC( HB_SETDISKZIP )
{
   hb_retl( hb___SetCallbackFunc( hb_param( 1, HB_IT_BLOCK ) ) );
}

hbziparc.c1169
HB_FUNCHB_ZIPDELETEFILES(void)
HB_FUNC( HB_ZIPDELETEFILES )
{
   BOOL bRet = FALSE;

   if( ISCHAR( 1 ) )
   {
      PHB_ITEM pDelZip = hb_param( 2, HB_IT_STRING | HB_IT_ARRAY | HB_IT_NUMERIC );

      s_DelZip = hb_itemArrayNew(0);

      if( pDelZip )
      {
         char szFile[ _POSIX_PATH_MAX + 1 ];
         char *szZipFileName;
         int ulLen;

         hb_strncpy( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );
         szZipFileName = hb___CheckFile( szFile );

         hb___GetFileNamesFromZip( szZipFileName, TRUE );
         ulLen = hb_arrayLen(hbza_ZipArray);

         if( !ulLen )
         {
            hb_xfree( szZipFileName );
            hb_itemClear( hbza_ZipArray );
            hb_itemRelease( hbza_ZipArray );
            hb_retl ( bRet );
            return;
         }

         if( HB_IS_STRING( pDelZip ) )
         {
            if( hb_itemGetCLen( pDelZip ) > 0 )
            {
               UnzipCreateArray( hb_itemGetCPtr( pDelZip ), 2 );
            }
         }
         else if( HB_IS_ARRAY( pDelZip ) )
         {
            int uiInLen = hb_arrayLen(pDelZip);

            if( uiInLen > 0 )
            {
               int uiIn;
               char * szInput;

               for( uiIn = 0; uiIn < uiInLen; uiIn++ )
               {
                  szInput = hb_arrayGetC( pDelZip, uiIn + 1 );

                  if( szInput )
                  {
                     UnzipCreateArray( szInput, 2 );
                     hb_xfree( szInput );
                  }
               }

            }
         }
         else if( HB_IS_NUMERIC( pDelZip ) )
         {
            int iIndex = hb_itemGetNI( pDelZip );
            PHB_ITEM Temp;

            if( iIndex > 0 && iIndex <= ulLen )
            {
               PHB_ITEM pZipEntry = hb_arrayGetItemPtr( hbza_ZipArray, iIndex );
               char* szEntry = hb_arrayGetC( pZipEntry, 1 );
               Temp = hb_itemNew(NULL);
               hb_arrayAddForward( s_DelZip, hb_itemPutC( Temp, szEntry ) );
               hb_xfree( szEntry );
               hb_itemRelease( Temp );
            }
         }

         if( hb_arrayLen(s_DelZip) > 0 )
         {
            bRet = hb_DeleteSel( szZipFileName,
                                 s_DelZip,
                                 ISLOG( 3 ) ? hb_parl( 3 ) : FALSE );
         }

         hb_xfree(szZipFileName);
         hb_itemClear( hbza_ZipArray );
         hb_itemRelease( hbza_ZipArray );
      }

      hb_itemRelease( s_DelZip );
   }

   hb_retl( bRet );
}

hbziparc.c1210
HB_FUNCHB_ZIPTESTPK(void)
HB_FUNC( HB_ZIPTESTPK )
{
   char szFile[ _POSIX_PATH_MAX + 1 ];
   char * szZipFileName;

   hb_strncpy( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );
   szZipFileName = hb___CheckFile( szFile );

   hb_retni( hb_TestForPKS( szZipFileName ) );

   hb_xfree(szZipFileName);
}

hbziparc.c1346
HB_FUNCHB_SETBUFFER(void)
HB_FUNC( HB_SETBUFFER )
{
   hb_SetZipBuff( hb_parni( 1 ), hb_parni( 2 ), hb_parni( 3 ) );
}

hbziparc.c1399
HB_FUNCHB_SETZIPCOMMENT(void)
HB_FUNC( HB_SETZIPCOMMENT )
{
   hb_SetZipComment( hb_parc( 1 ) );
}

hbziparc.c1434
HB_FUNCHB_GETZIPCOMMENT(void)
HB_FUNC( HB_GETZIPCOMMENT )
{
   hb_retc_buffer( ( char * ) hb_GetZipComment( hb_parc( 1 ) ) );
}

hbziparc.c1468
HB_FUNCHB_UNZIPFILEINDEX(void)
HB_FUNC( HB_UNZIPFILEINDEX )
{
   BOOL bRet = FALSE;

   if( ISCHAR( 1 ) )
   {
      PHB_ITEM pDelZip = hb_param( 6, HB_IT_NUMERIC | HB_IT_ARRAY );

      if( pDelZip )
      {
         char szFile[ _POSIX_PATH_MAX + 1 ];
         PHB_ITEM Temp,DelZip;
         char* szZipFileName;
         int ulLen;

         DelZip = hb_itemArrayNew(0);

         hb_strncpy( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );
         szZipFileName = hb___CheckFile( szFile );

         hb___GetFileNamesFromZip( szZipFileName, TRUE );
         ulLen = hb_arrayLen(hbza_ZipArray);

         if( HB_IS_NUMERIC( pDelZip ) )
         {
            int iIndex = hb_itemGetNI( pDelZip );

            if( iIndex > 0 && iIndex <= ulLen )
            {
               Temp = hb_itemNew(NULL);
               hb_arrayAddForward( DelZip, hb_itemPutNI( Temp, iIndex ) );
               hb_itemRelease( Temp );
            }
         }
         else
         {
            int ui, iIndex;

            for( ui = 0; ui < ulLen; ui++ )
            {
               iIndex = hb_arrayGetNI( pDelZip, ui + 1 );
               if( iIndex && iIndex > 0 && iIndex <= ulLen )
               {
                  Temp = hb_itemNew( NULL );
                  hb_arrayAddForward( DelZip, hb_itemPutNI( Temp, iIndex ) );
                  hb_itemRelease( Temp );
               }
            }
         }

         if( hb_arrayLen( DelZip ) > 0 )
         {
            PHB_ITEM pProgress = ISBLOCK( 7 ) ? hb_itemNew( hb_param( 7 , HB_IT_BLOCK ) ) : hb_itemNew( NULL );
            bRet = hb_UnzipSelIndex( szZipFileName,
                                     hb_param( 2, HB_IT_BLOCK ),
                                     ISLOG( 3 ) ? hb_parl( 3 ) : FALSE,
                                     ISCHAR( 4 ) ? hb_parc( 4 ) : NULL,
                                     hb_parc( 5 ),
                                     DelZip,
                                     pProgress );
            hb_itemRelease( pProgress );
         }

         hb_itemRelease( DelZip );
         hb_xfree( szZipFileName );
         hb_itemClear( hbza_ZipArray );
         hb_itemRelease( hbza_ZipArray );

      }
   }

   hb_retl( bRet );
}

hbziparc.c1540
HB_FUNCTRANSFERFROMZIP(void)
HB_FUNC( TRANSFERFROMZIP )
{
   hb_retl( hb_TransferFilesFromzip( hb_parc( 1 ),
                                     hb_parc( 2 ),
                                     hb_param( 3, HB_IT_ARRAY ) ) );
}
hbziparc.c1626
HB_FUNCSETZIPREADONLY(void)
HB_FUNC( SETZIPREADONLY )
{
   hb_SetZipReadOnly( hb_parl( 1 ) );
}
hbziparc.c1633
HB_FUNCHB_UNZIPALLFILE(void)
HB_FUNC(HB_UNZIPALLFILE)
{
    if( ! ISCHAR( 6 ) && ! ISARRAY( 6 ) )
    {
        char szFile[ _POSIX_PATH_MAX + 1 ];
        char * szZipFile;
        PHB_ITEM pProgress = ISBLOCK( 7 ) ? hb_itemNew( hb_param( 7, HB_IT_BLOCK ) ) : hb_itemNew( NULL );
        hb_strncpy( szFile, hb_parc( 1 ), sizeof( szFile ) - 1 );
        szZipFile = hb___CheckFile( szFile );
        hb_retl( hb_UnzipAll( szZipFile,
                              hb_param( 2, HB_IT_BLOCK ),
                              ISLOG( 3 ) ? hb_parl( 3 ) : FALSE,
                              hb_parc( 4 ),
                              hb_parc( 5 ),
                              hb_param( 6, HB_IT_BLOCK ),
                              pProgress ) );
        hb_xfree( szZipFile );
        hb_itemRelease( pProgress );
    }
}
hbziparc.c1638
ZipArchive.cpp
TypeFunctionSourceLine
VOID CZIPADDNEWFILEINFO:Defaults()
void CZipAddNewFileInfo::Defaults()
{
	m_iSmartLevel =  CZipArchive::zipsmSafeSmart;
	m_uReplaceIndex = ZIP_FILE_INDEX_UNSPECIFIED;
	m_nBufSize = 65536;
	m_iComprLevel = -1; // default
}
ZipArchive.cpp29
CZIPARCHIVE::CZipArchive()
 CZipArchive:: CZipArchive()
{
	Initialize();
}
ZipArchive.cpp39
VOID CZIPARCHIVE:Initialize()
void  CZipArchive::Initialize()
{
	m_bRemoveDriveLetter = true;
	m_bExhaustiveRead = false;
	m_bAutoFlush = false;
	m_iFileOpened = nothing;
	SetCaseSensitivity(ZipPlatform::GetSystemCaseSensitivity());
	m_uCompressionMethod = CZipCompressor::methodDeflate;
	m_iEncryptionMethod = CZipCryptograph::encStandard;	
	m_pCryptograph = NULL;
	m_pCompressor = NULL;
	m_iBufferSize = 65536;
}
ZipArchive.cpp44
CZIPARCHIVE::~CZipArchive()
 CZipArchive::~ CZipArchive()
{
	// 	Close(); // cannot be here: if an exception is thrown strange things can happen	
	ClearCompressor();
	ClearCryptograph();	
}
ZipArchive.cpp59
BOOL CZIPARCHIVE:Open(LPCTSTR szPathName, int iMode, ZIP_SIZE_TYPE uVolumeSize)
bool  CZipArchive::Open(LPCTSTR szPathName, int iMode, ZIP_SIZE_TYPE uVolumeSize)
{
	if (!IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive already opened.\n");
		return false;
	}
	m_storage.Open(szPathName, iMode, uVolumeSize);
	OpenInternal(iMode);
	return true;
}
ZipArchive.cpp66
BOOL CZIPARCHIVE:Open(CZipAbstractFile& af, int iMode)
bool  CZipArchive::Open(CZipAbstractFile& af, int iMode)
{
	if (!IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is already opened.\n");
		return false;
	}
	if (iMode != zipOpen && iMode != zipOpenReadOnly && iMode != zipCreate && iMode != zipCreateAppend)
	{
		ZIPTRACE("%s(%i) : Mode is not supported.\n");
		return false; 
	}
	m_storage.Open(af, iMode);
	OpenInternal(iMode);
	return true;
}
ZipArchive.cpp78
BOOL CZIPARCHIVE:OpenFrom( CZipArchive& zip)
bool  CZipArchive::OpenFrom( CZipArchive& zip)
{
	if (zip.IsClosed())
	{
		ZIPTRACE("%s(%i) : The source archive must be opened.\n");
		return false; 
	}
	if (!zip.IsReadOnly())
	{
		ZIPTRACE("%s(%i) : The source archive must be opened in the read-only mode.\n");
		return false; 
	}
	if (zip.m_storage.m_bInMemory)
	{
		ZIPTRACE("%s(%i) : ZipArchive cannot share an archive in memory.\n");
		return false; 
	}

	m_storage.Open(zip.GetArchivePath(),  CZipArchive::zipOpenReadOnly, zip.m_storage.IsSplit() ? 1 : 0);
	InitOnOpen(zip.GetSystemCompatibility(), &zip.m_centralDir);	

	return true;
}
ZipArchive.cpp95
VOID CZIPARCHIVE:InitOnOpen(int iArchiveSystCompatib, CZipCentralDir* pSource)
void  CZipArchive::InitOnOpen(int iArchiveSystCompatib, CZipCentralDir* pSource)
{
	m_pszPassword.Release();
	m_iFileOpened = nothing;
	m_szRootPath.Empty();
	m_centralDir.Init(&m_storage, &m_callbacks, &m_stringSettings, pSource);	
	m_iArchiveSystCompatib = iArchiveSystCompatib;
}
ZipArchive.cpp119
VOID CZIPARCHIVE:OpenInternal(int iMode)
void  CZipArchive::OpenInternal(int iMode)
{
	InitOnOpen(ZipPlatform::GetSystemID());		
	if ((iMode == zipOpen) ||(iMode == zipOpenReadOnly))
	{
		m_centralDir.Read(m_bExhaustiveRead);
		// if there is at least one file, get system comp. from the first one
		if (m_centralDir.IsValidIndex(0))
		{			
			int iSystemComp = m_centralDir[0]->GetSystemCompatibility();
			if (ZipCompatibility::IsPlatformSupported(iSystemComp))
				m_iArchiveSystCompatib = iSystemComp;
		}
	}
}
ZipArchive.cpp128
VOID CZIPARCHIVE:ThrowError(int err)
void  CZipArchive::ThrowError(int err)
{
	CZipException::Throw(err, IsClosed() ? _T("") : (LPCTSTR)m_storage.m_pFile->GetFilePath());
}

bool  CZipArchive::GetFileInfo(CZipFileHeader & fhInfo, ZIP_INDEX_TYPE uIndex) const
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}
	
	if (!m_centralDir.IsValidIndex(uIndex))
		return false;
	
	fhInfo = *(m_centralDir[uIndex]);
	return true;
}
ZipArchive.cpp144
CZIPFILEHEADER* CZIPARCHIVE:GetFileInfo(ZIP_INDEX_TYPE uIndex)
CZipFileHeader*  CZipArchive::GetFileInfo(ZIP_INDEX_TYPE uIndex)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return NULL;
	}
	
	if (!m_centralDir.IsValidIndex(uIndex))
		return NULL;	
	return m_centralDir[uIndex];
}

const CZipFileHeader*  CZipArchive::GetFileInfo(ZIP_INDEX_TYPE uIndex) const
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return NULL;
	}
	
	if (!m_centralDir.IsValidIndex(uIndex))
		return NULL;
	return m_centralDir[uIndex];
}
ZipArchive.cpp164
ZIP_INDEX_TYPE CZIPARCHIVE:FindFile(LPCTSTR lpszFileName, int iCaseSensitive, bool bFileNameOnly)
ZIP_INDEX_TYPE  CZipArchive::FindFile(LPCTSTR lpszFileName, int iCaseSensitive, bool bFileNameOnly)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return ZIP_FILE_INDEX_NOT_FOUND;
	}
	bool bCS;
	bool bSporadically;
	switch (iCaseSensitive)
	{
	case ffCaseSens:
		bCS = true;
		bSporadically = true;
		break;
	case ffNoCaseSens:
		bCS = false;
		bSporadically = true;
		break;
	default:
		bCS = m_bCaseSensitive;
		bSporadically = false;
	}
	return m_centralDir.FindFile(lpszFileName, bCS, bSporadically, bFileNameOnly);
}
ZipArchive.cpp192
BOOL CZIPARCHIVE:OpenFile(ZIP_INDEX_TYPE uIndex)
bool  CZipArchive::OpenFile(ZIP_INDEX_TYPE uIndex)
{	
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}

	if (!m_centralDir.IsValidIndex(uIndex))
	{
		ASSERT(FALSE);
		return false;
	}
	if (m_storage.IsSegmented() == 1)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot extract from a segmented archive in creation.\n");
		return false;
	}	
	
	if (m_iFileOpened)
	{
		ZIPTRACE("%s(%i) : A file already opened.\n");
		return false;
	}
	
	m_centralDir.OpenFile(uIndex);

	// check it now, not when reading central to allow reading information
	// but disallow extraction now - unsupported method
	if (!CZipCompressor::IsCompressionSupported(CurrentFile()->m_uMethod))
	{		
		m_centralDir.CloseFile(true);
		ZIPTRACE("%s(%i) : The compression method is not supported.\n");
		return false;
	}

	if (CurrentFile()->IsEncrypted())
	{		
		if (m_pszPassword.GetSize() == 0)
		{
			ZIPTRACE("%s(%i) : Password not set for the encrypted file.\n");
				ThrowError(CZipException::badPassword);
		}
		CreateCryptograph(CurrentFile()->m_uEncryptionMethod);
		if (!m_pCryptograph->InitDecode(m_pszPassword, *CurrentFile(), m_storage))
			ThrowError(CZipException::badPassword); 

	}
	else
	{
		ClearCryptograph();
		if (m_pszPassword.GetSize() != 0)
		{
			ZIPTRACE("%s(%i) : Password set for a not encrypted file. Ignoring password.\n");
		}
	}
	
	CreateCompressor(CurrentFile()->m_uMethod);
	m_pCompressor->InitDecompression(CurrentFile(), m_pCryptograph);
	
	m_iFileOpened = extract;
	return true;
}
ZipArchive.cpp218
CZIPFILEHEADER* CZIPARCHIVE:CurrentFile()
CZipFileHeader*  CZipArchive::CurrentFile()
{
	ASSERT(m_centralDir.m_pOpenedFile);
	return m_centralDir.m_pOpenedFile;
}
ZipArchive.cpp282
DWORD CZIPARCHIVE:ReadFile(void *pBuf, DWORD uSize)
DWORD  CZipArchive::ReadFile(void *pBuf, DWORD uSize)
{
	if (m_iFileOpened != extract)
	{
		ZIPTRACE("%s(%i) : Current file must be opened.\n");
		return 0;
	}
	
	if (!pBuf || !uSize)
		return 0;

	return m_pCompressor->Decompress(pBuf, uSize);
}
ZipArchive.cpp288
VOID CZIPARCHIVE:Close(int iAfterException, bool bUpdateTimeStamp)
void  CZipArchive::Close(int iAfterException, bool bUpdateTimeStamp)
{
	// if after an exception - the archive may be closed, but the file may be opened
	if (IsClosed() && (!iAfterException || IsClosed(false)))
	{
		ZIPTRACE("%s(%i) : ZipArchive is already closed.\n");
		return;
	}

	if (m_iFileOpened == extract)
		CloseFile(NULL, iAfterException != afNoException);

	if (m_iFileOpened == compress)
		CloseNewFile(iAfterException != afNoException);

	bool bWrite = iAfterException != afAfterException && !IsClosed(false);// in segmented archive when user aborts 

	if (bWrite) 
		WriteCentralDirectory(false);  // we will flush in CZipStorage::Close

	time_t tNewestTime = 0;

	if (bUpdateTimeStamp)
	{
		ZIP_INDEX_TYPE iSize = (ZIP_INDEX_TYPE)m_centralDir.GetCount();
		for (ZIP_INDEX_TYPE i = 0; i < iSize; i++)
		{
			time_t tFileInZipTime = m_centralDir[i]->GetTime();
			if (tFileInZipTime > tNewestTime)
				tNewestTime = tFileInZipTime;
		}
	}
	m_centralDir.Close();
	m_stringSettings.Reset();
	CZipString szFileName = m_storage.Close(!bWrite);
	if (bUpdateTimeStamp && !szFileName.IsEmpty())
		ZipPlatform::SetFileModTime(szFileName, tNewestTime);
}
ZipArchive.cpp303
VOID CZIPARCHIVE:WriteCentralDirectory(bool bFlush)
void  CZipArchive::WriteCentralDirectory(bool bFlush)
{
	m_centralDir.Write();
	if (bFlush)
		m_storage.Flush();
}
ZipArchive.cpp342
VOID CZIPARCHIVE:SetAdvanced(int iWriteBuffer, int iGeneralBuffer, int iSearchBuffer)
void  CZipArchive::SetAdvanced(int iWriteBuffer, int iGeneralBuffer, int iSearchBuffer)
{
	if (!IsClosed())
	{
		ZIPTRACE("%s(%i) : Set these options before opening the archive.\n");
		return;
	}
	
	m_storage.m_iWriteBufferSize = iWriteBuffer < 1024 ? 1024 : iWriteBuffer;
	m_iBufferSize = iGeneralBuffer < 1024 ? 1024 : iGeneralBuffer;
	m_storage.m_iLocateBufferSize = iSearchBuffer < 1024 ? 1024 : iSearchBuffer;
}
ZipArchive.cpp349
INT CZIPARCHIVE:CloseFile(CZipFile &file)
int  CZipArchive::CloseFile(CZipFile &file)
{
	CZipString temp = file.GetFilePath();
	file.Close();
	return CloseFile(temp);
}
ZipArchive.cpp362
INT CZIPARCHIVE:CloseFile(LPCTSTR lpszFilePath, bool bAfterException)
int  CZipArchive::CloseFile(LPCTSTR lpszFilePath, bool bAfterException)
{
	if (m_iFileOpened != extract)
	{
		ZIPTRACE("%s(%i) : No opened file.\n");
		return 0;
	}

	int iRet = 1;
	if (bAfterException)
		m_pCompressor->FinishDecompression(true);
	else
	{
		if (m_pCompressor->m_uUncomprLeft == 0)
		{
			if (m_centralDir.IsConsistencyCheckOn(checkCRC)
				&& !CurrentFile()->m_bIgnoreCrc32
				&& m_pCompressor->m_uCrc32 != CurrentFile()->m_uCrc32)
					ThrowError(CZipException::badCrc);
		}
		else
			iRet = -1;

		m_pCompressor->FinishDecompression(false);
		
		if (lpszFilePath)
		{			
			if (!ZipPlatform::SetFileModTime(lpszFilePath, CurrentFile()->GetTime())
				||!ZipPlatform::SetFileAttr(lpszFilePath, CurrentFile()->GetSystemAttr()))
					iRet = -2;
		}
		if (m_pCryptograph)
			m_pCryptograph->FinishDecode(*CurrentFile(), m_storage);
	}

	m_centralDir.CloseFile(bAfterException);
		
	m_iFileOpened = nothing;	
	ClearCryptograph();	
	return iRet;
}
ZipArchive.cpp369
BOOL CZIPARCHIVE:OpenNewFile(CZipFileHeader & header, int iLevel, LPCTSTR lpszFilePath, ZIP_INDEX_TYPE uReplaceIndex)
bool  CZipArchive::OpenNewFile(CZipFileHeader & header, int iLevel, LPCTSTR lpszFilePath,
							  ZIP_INDEX_TYPE uReplaceIndex)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}
	
	if (m_iFileOpened)
	{
		ZIPTRACE("%s(%i) : A file already opened.\n");
		return false;
	}
	
	if (m_storage.IsSegmented() == -1)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot add files to an existing segmented archive.\n");
		return false;
	}

	if (GetCount() ==(WORD)USHRT_MAX)
	{
		ZIPTRACE("%s(%i) : Maximum file count inside archive reached.\n");
		return false;
	}
	
	DWORD uAttr = 0;
	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;
		ZipPlatform::GetFileModTime(lpszFilePath, ttime);
	}
	
	if (lpszFilePath)
	{
		header.SetTime(ttime);
		SetFileHeaderAttr(header, uAttr); // set system compatibility as well
	}
	else
	{
		header.SetSystemCompatibility(m_iArchiveSystCompatib);
		if (!header.HasTime())
			header.SetTime(time(NULL));
	}

	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%u"), GetCount());
		header.SetFileName(szFileName);
	}

	bool bEncrypted = WillEncryptNextFile();

#if defined _DEBUG && !defined NOZIPTRACE
	if (bIsDirectory && bEncrypted)
		ZIPTRACE("%s(%i) : Encrypting a directory. You may want to consider clearing the password before adding a directory.\n");
#endif		
	
	bool bReplace = uReplaceIndex != ZIP_FILE_INDEX_UNSPECIFIED;

	if (iLevel < -1 || iLevel > 9)
		iLevel = -1;
	
	if (bEncrypted)
	{
		header.m_uEncryptionMethod = (BYTE)m_iEncryptionMethod;
		CreateCryptograph(m_iEncryptionMethod);
	}
	else
	{
		header.m_uEncryptionMethod = CZipCryptograph::encNone;
		ClearCryptograph();
	}

	if (iLevel == 0 || bIsDirectory)
		header.m_uMethod = CZipCompressor::methodStore;
	else
		header.m_uMethod = m_uCompressionMethod;

	CreateCompressor(header.m_uMethod);	
	CZipFileHeader* pHeader = m_centralDir.AddNewFile(header, uReplaceIndex, iLevel);	

	// replace can happen only from AddNewFile and the compressed size is already known and set (the file is stored, not compressed)
	if (bReplace)
	{
		// this will be used in GetLocalSize and WriteLocal
		pHeader->PrepareFileName();
		// we use the local size, because the real does not exist yet
		ZIP_SIZE_TYPE uFileSize = pHeader->GetDataSize(true, false) + pHeader->GetLocalSize(false) + pHeader->GetDataDescriptorSize(&m_storage);
		InitBuffer();
		MakeSpaceForReplace(uReplaceIndex, uFileSize, szFileName);
		ReleaseBuffer();
	}

	CurrentFile()->WriteLocal(&m_storage);

	if (m_pCryptograph)
		m_pCryptograph->InitEncode(m_pszPassword, *pHeader, m_storage);

	m_pCompressor->InitCompression(iLevel, CurrentFile(), m_pCryptograph);
		
	m_iFileOpened = compress;
	return true;
}
ZipArchive.cpp411
BOOL CZIPARCHIVE:ExtractFile(ZIP_INDEX_TYPE uIndex, LPCTSTR lpszPath, bool bFullPath, LPCTSTR lpszNewName, DWORD nBufSize)
bool  CZipArchive::ExtractFile(ZIP_INDEX_TYPE uIndex,                  
                              LPCTSTR lpszPath,             
                              bool bFullPath,              
                              LPCTSTR lpszNewName,  
                              DWORD nBufSize)
{
	
	if (!nBufSize && !lpszPath)
		return false;
	
	CZipFileHeader* pHeader = (*this)[uIndex];	
	CZipString szFileNameInZip = pHeader->GetFileName();
	CZipString szFile = PredictExtractedFileName(szFileNameInZip, lpszPath, bFullPath, lpszNewName);
	CZipActionCallback* pCallback = GetCallback(CZipActionCallback::cbExtract);
	if (pCallback)
		pCallback->Init(szFileNameInZip, szFile);
	

	if (pHeader->IsDirectory())
	{
		if (pCallback)
			pCallback->SetTotal(0); // in case of calling LeftToProcess() afterwards

		ZipPlatform::ForceDirectory(szFile);
		ZipPlatform::SetFileAttr(szFile, pHeader->GetSystemAttr());

		if (pCallback)
			pCallback->CallbackEnd();
		return true;
	}
	else
	{
		if (!OpenFile(uIndex))
			return false;
		if (pCallback)
			pCallback->SetTotal(pHeader->m_uUncomprSize);

		CZipPathComponent zpc(szFile);
		ZipPlatform::ForceDirectory(zpc.GetFilePath());
		CZipFile f(szFile, CZipFile::modeWrite | 
			CZipFile::modeCreate | CZipFile::shareDenyWrite);
		DWORD iRead;
		CZipAutoBuffer buf(nBufSize);
		int iAborted = 0;
		for(;;)
		{
			iRead = ReadFile(buf, buf.GetSize());
			if (!iRead)
			{
				if (pCallback && !pCallback->RequestLastCallback())
					iAborted = CZipException::abortedSafely;
				break;
			}
			f.Write(buf, iRead);
			if (pCallback && !pCallback->RequestCallback(iRead))
			{
				if (iRead == buf.GetSize() && ReadFile(buf, 1) != 0) // test one byte if there is something left
					iAborted = CZipException::abortedAction; 
				else
					iAborted = CZipException::abortedSafely;
				break;
			}
		}

		if (pCallback)
		{
			if (!iAborted)
			{
				bool bRet = CloseFile(f) == 1;
				pCallback->CallbackEnd();
				return bRet;
			}
			else
			{
				if (iAborted == CZipException::abortedAction)
					CloseFile(NULL, true);
				else
				{
					bool bRet;
					try
					{
						bRet = CloseFile(f) == 1;
					}
					// if any exception was thrown, then we are not successful
					// catch all exceptions to throw aborted exception only
#ifdef ZIP_ARCHIVE_MFC
					catch(CException* e)
					{
						e->Delete();
						bRet = false;
					}
#endif
					catch(...)
					{
						bRet = false;
					}
					if (!bRet)
					{
						CloseFile(NULL, true);
						iAborted = CZipException::abortedAction;
					}
				}

				pCallback->CallbackEnd();
				CZipException::Throw(iAborted, szFile);
				return false; // for the compiler
			}
		}
		else
			return CloseFile(f) == 1;		
	}	
}
ZipArchive.cpp536
BOOL CZIPARCHIVE:ExtractFile(ZIP_INDEX_TYPE uIndex, CZipMemFile& mf, bool bRewind, DWORD nBufSize)
bool  CZipArchive::ExtractFile(ZIP_INDEX_TYPE uIndex,                  
                              CZipMemFile& mf,
							  bool bRewind,
                              DWORD nBufSize)
{
	if (!nBufSize)
		return false;
	
	CZipFileHeader* pHeader = (*this)[uIndex];
	CZipActionCallback* pCallback = GetCallback(CZipActionCallback::cbExtract);
	if (pCallback)
		pCallback->Init(pHeader->GetFileName());

	if (pHeader->IsDirectory() || !OpenFile(uIndex))
		return false;

	if (pCallback)
		pCallback->SetTotal(pHeader->m_uUncomprSize);


	CZipAutoBuffer buf(nBufSize);
	//mf.SeekToEnd();
	ZIP_FILE_USIZE oldPos = 0;

	if (bRewind)
		oldPos = mf.GetPosition();

	DWORD iRead;
	int iAborted = 0;
	for(;;)
	{
		iRead = ReadFile(buf, buf.GetSize());
		if (!iRead)
		{
			if (pCallback && !pCallback->RequestLastCallback())
				iAborted = CZipException::abortedSafely;
			break;
		}
		mf.Write(buf, iRead);
		if (pCallback && !pCallback->RequestCallback(iRead))
		{
			if (iRead == buf.GetSize() && ReadFile(buf, 1) != 0) // test one byte if there is something left
				iAborted = CZipException::abortedAction; 
			else
				iAborted = CZipException::abortedSafely; // we did it!
			break;
		}
	}

	bool bRet;
	if (pCallback)
	{
		if (!iAborted)
		{
			bRet = CloseFile() == 1;
			pCallback->CallbackEnd();			
		}
		else
		{
			if (iAborted == CZipException::abortedAction)
				CloseFile(NULL, true);
			else
			{
				bRet = false;
				try
				{
					bRet = CloseFile() == 1;
				}
				// if any exception was thrown, then we are not successful
				// catch all exceptions to thrown aborted exception only
	#ifdef ZIP_ARCHIVE_MFC
				catch(CException* e)
				{
					e->Delete();
					bRet = false;
				}
	#endif
				catch(...)
				{
					bRet = false;
				}
				if (!bRet)
				{
					CloseFile(NULL, true);
					iAborted = CZipException::abortedAction;
				}
			}
			
			pCallback->CallbackEnd();
			if (bRewind)
				mf.Seek(oldPos, CZipMemFile::begin);
			CZipException::Throw(iAborted);
			return false; // for the compiler
		}
	}
	else
		bRet = CloseFile() == 1;

	if (bRewind)
		mf.Seek(oldPos, CZipMemFile::begin);
	return bRet;
}
ZipArchive.cpp649
BOOL CZIPARCHIVE:WriteNewFile(const void *pBuf, DWORD uSize)
bool  CZipArchive::WriteNewFile(const void *pBuf, DWORD uSize)
{
	if (m_iFileOpened != compress)
	{
		ZIPTRACE("%s(%i) : A new file must be opened.\n");
		return false;
	}
	
	m_pCompressor->Compress(pBuf, uSize);	
	return true;
}
ZipArchive.cpp753
BOOL CZIPARCHIVE:CloseNewFile(bool bAfterException)
bool  CZipArchive::CloseNewFile(bool bAfterException)
{
	if (m_iFileOpened != compress)
	{
		ZIPTRACE("%s(%i) : A new file must be opened.\n");
		return false;
	}
	    
	m_pCompressor->FinishCompression(bAfterException);
    if (bAfterException)
		m_centralDir.m_pOpenedFile = NULL;
	else
	{
		if (m_pCryptograph)
			m_pCryptograph->FinishEncode(*CurrentFile(), m_storage);
		
		m_centralDir.CloseNewFile();
	}	
	m_iFileOpened = nothing;
	ClearCryptograph();
	if (m_bAutoFlush && !bAfterException)
		Flush();

	return true;
}
ZipArchive.cpp765
BOOL CZIPARCHIVE:RemoveFile(ZIP_INDEX_TYPE uIndex)
bool  CZipArchive::RemoveFile(ZIP_INDEX_TYPE uIndex)
{
	CZipIndexesArray indexes;
	indexes.Add(uIndex);
	return RemoveFiles(indexes);
}
ZipArchive.cpp791
VOID CZIPARCHIVE:GetIndexes(const CZipStringArray &aNames, CZipIndexesArray& aIndexes)
void  CZipArchive::GetIndexes(const CZipStringArray &aNames, CZipIndexesArray& aIndexes)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return;
	}
	ZIP_INDEX_TYPE uSize = (ZIP_INDEX_TYPE)aNames.GetSize();
	for (ZIP_INDEX_TYPE i = 0; i < uSize; i++)
		aIndexes.Add(FindFile(aNames[(ZIP_ARRAY_SIZE_TYPE)i], ffDefault, false));			
}
ZipArchive.cpp798
BOOL CZIPARCHIVE:RemoveFiles(const CZipStringArray &aNames)
bool  CZipArchive::RemoveFiles(const CZipStringArray &aNames)
{
	CZipIndexesArray indexes;
	GetIndexes(aNames, indexes);
	return RemoveFiles(indexes);
}

struct CZipDeleteInfo
{
	CZipDeleteInfo(){m_pHeader = NULL; m_bDelete = false;}
	CZipDeleteInfo(CZipFileHeader* pHeader, bool bDelete)
		:m_pHeader(pHeader), m_bDelete (bDelete){}
	CZipFileHeader* m_pHeader;	
	bool m_bDelete;
};
ZipArchive.cpp810
BOOL CZIPARCHIVE:RemoveFiles(CZipIndexesArray &aIndexes)
bool  CZipArchive::RemoveFiles(CZipIndexesArray &aIndexes)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}
	
	if (m_storage.IsSegmented())
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot delete files from a segmented archive.\n");
		return false;
	}
	
	if (m_iFileOpened)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot delete files if there is a file opened.\n");
		return false;
	}

	if (GetCount() == 0)
	{
		ZIPTRACE("%s(%i) : There is nothing to delete: the archive is empty.\n");
		return false;
	}
	
	ZIP_INDEX_TYPE uSize = (ZIP_INDEX_TYPE)aIndexes.GetSize();
	if (!uSize)
	{
		ZIPTRACE("%s(%i) : The indexes array is empty.\n");
		return true;
	}
	
	aIndexes.Sort(true);
	// remove all - that's easy so don't waste the time
	if (uSize == GetCount())
	{		
		// check that the indexes are correct
		bool allIncluded = true;
		// iterate all indexes, if all are sorted then the condition should always be true
		for (ZIP_INDEX_TYPE i = 0; i < uSize; i++)
			if (aIndexes[(ZIP_ARRAY_SIZE_TYPE)i] != i)
			{
				allIncluded = false;
				break;
			}

		if (allIncluded)
		{
			CZipActionCallback* pCallback = GetCallback(CZipActionCallback::cbDelete);
			if (pCallback)
			{
				// do it right and sent the notification
				pCallback->Init();
				pCallback->SetTotal(uSize);
			}

			m_centralDir.RemoveFromDisk();
			m_storage.m_pFile->SetLength((ZIP_FILE_USIZE) m_storage.m_uBytesBeforeZip);
			m_centralDir.RemoveAll();
			if (m_bAutoFlush)
				Flush();
			if (pCallback)
				pCallback->CallbackEnd();
			return true;
		}
	}
	else
	{
		for (ZIP_INDEX_TYPE i = 0; i < uSize; i++)
			if (!m_centralDir.IsValidIndex(aIndexes[(ZIP_ARRAY_SIZE_TYPE)i]))
				return false;
	}

	ZIP_INDEX_TYPE i;

	CZipArray aInfo;
	
	CZipActionCallback* pCallback = GetCallback(CZipActionCallback::cbDeleteCnt);
	if (pCallback)
	{
		pCallback->Init();
		pCallback->SetTotal(GetCount());
	}
	
	ZIP_INDEX_TYPE uDelIndex = 0;
	ZIP_INDEX_TYPE uMaxDelIndex = aIndexes[(ZIP_ARRAY_SIZE_TYPE)(uSize - 1)];
	i = aIndexes[0];
	// GetCount() is greater than 0 (checked before) and when it is unsigned we do not cause overflow
	ZIP_INDEX_TYPE uLastPosition = (ZIP_INDEX_TYPE)(GetCount() - 1);
	bool bAborted = false;
	if (i <= uLastPosition) 
		for(;;)
		{
			CZipFileHeader* pHeader = m_centralDir[i];
			bool bDelete;
			if (i <= uMaxDelIndex && i == aIndexes[(ZIP_ARRAY_SIZE_TYPE)uDelIndex])
			{
				uDelIndex++;
				bDelete = true;
			}
			else
				bDelete = false;
			aInfo.Add(CZipDeleteInfo(pHeader, bDelete));
			if (i == uLastPosition)
			{
				if (pCallback && !pCallback->RequestLastCallback(1))
					bAborted = true;
				break;
			}
			else
			{				
				if (pCallback && !pCallback->RequestCallback())
				{
					bAborted = true;
					break;
				}
				i++;
			}
		}

	ASSERT(uDelIndex == uSize);

	if (pCallback)
	{
		pCallback->CallbackEnd();
		if (bAborted)
			ThrowError(CZipException::abortedSafely);
	}

	uSize = (ZIP_INDEX_TYPE)aInfo.GetSize();
	if (!uSize) // it is possible
		return true;

	// they should already be sorted after reading the in CZipCentralDir::ReadHeaders and when replacing, the index is placed at the same place as the old one
	//aInfo.Sort(true); // sort by offsets (when operators uncommented in CZipDeleteInfo)
	
	// now we start deleting (not safe to break)
	pCallback = GetCallback(CZipActionCallback::cbDelete);
	if (pCallback)
		pCallback->Init();
	
	m_centralDir.RemoveFromDisk();

	ZIP_SIZE_TYPE uTotalToMoveBytes = 0, uLastOffset = m_storage.GetLastDataOffset();
	// count the number of bytes to move
	i = uSize;
	while(i > 0)
	{
		i--;
		// cannot use a decreasing loop because i is unsigned and instead negative at the end of the loop it will be maximum positive
		const CZipDeleteInfo& di = aInfo[(ZIP_ARRAY_SIZE_TYPE)i];
		if (!di.m_bDelete)
			uTotalToMoveBytes += uLastOffset - di.m_pHeader->m_uOffset;
		uLastOffset = di.m_pHeader->m_uOffset;
	}
	
	if (pCallback)
		pCallback->SetTotal(uTotalToMoveBytes);

	
	InitBuffer();

	ZIP_SIZE_TYPE uMoveBy = 0, uOffsetStart = 0;
	for (i = 0; i < uSize; i++)
	{
		const CZipDeleteInfo& di = aInfo[(ZIP_ARRAY_SIZE_TYPE)i];
		
		if (di.m_bDelete)
		{
			// next hole
			ZIP_SIZE_TYPE uTemp = di.m_pHeader->m_uOffset;
			m_centralDir.RemoveFile(di.m_pHeader); // first remove
			if (uOffsetStart)
			{
				// copy the files over a previous holes
				MovePackedFiles(uOffsetStart, uTemp, uMoveBy, pCallback, false, false);
				uOffsetStart = 0;  // never be at the beginning, because the first file is always to be deleted
			}
			if (i == uSize - 1)
				uTemp = (m_storage.GetLastDataOffset()) - uTemp;
			else
				uTemp = aInfo[(ZIP_ARRAY_SIZE_TYPE)(i + 1)].m_pHeader->m_uOffset - uTemp;

			uMoveBy += uTemp;
			
		}
		else
		{
			if (uOffsetStart == 0) // find continuous area to move
				uOffsetStart = di.m_pHeader->m_uOffset;
			di.m_pHeader->m_uOffset -= uMoveBy;
		}
	}

	if (uOffsetStart)
	{
		// will call the last callback, if necessary
		MovePackedFiles(uOffsetStart, m_storage.GetLastDataOffset(), uMoveBy, pCallback); 
	}
	else
	{
		// call last callback (it was not called in the MovePackedFiles calls in the loop)
		if (pCallback && !pCallback->RequestLastCallback())
		{
			pCallback->CallbackEnd();
			ThrowError(CZipException::abortedAction);
		}
	}

	ReleaseBuffer();
	if (uMoveBy) // just in case
		m_storage.m_pFile->SetLength((ZIP_FILE_USIZE)(m_storage.m_pFile->GetLength() - uMoveBy));

	if (pCallback)
		pCallback->CallbackEnd();

	if (m_bAutoFlush)
		Flush();
	return true;
}
ZipArchive.cpp826
BOOL CZIPARCHIVE:ShiftData(ZIP_SIZE_TYPE uOffset)
bool  CZipArchive::ShiftData(ZIP_SIZE_TYPE uOffset)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive should be opened first.\n");
		return false; 
	}

	if (m_storage.IsSegmented() != 0)
	{
		ZIPTRACE("%s(%i) : Cannot shift data for a segmented archive.\n");
		return false;
	}

	if (m_iFileOpened)
	{
		ZIPTRACE("%s(%i) : A file should not be opened.\n");
		return false;
	}

	if (m_storage.m_uBytesBeforeZip != 0)
	{
		ZIPTRACE("%s(%i) : Bytes before zip file must not be present.\n");
		return false;
	}

	if (uOffset == 0)
		return true;

	m_centralDir.RemoveFromDisk();  // does m_storage.Flush();
	InitBuffer();
	
	ZIP_SIZE_TYPE uFileLen = (ZIP_SIZE_TYPE)m_storage.m_pFile->GetLength();
	CZipActionCallback* pCallback = GetCallback(CZipActionCallback::cbMoveData);
	if (pCallback)
	{
		pCallback->Init(NULL, GetArchivePath());
		pCallback->SetTotal(uFileLen);
	}			

	m_storage.m_pFile->SetLength((ZIP_FILE_USIZE)(uFileLen + uOffset)); // ensure the seek is correct

	MovePackedFiles(0, uFileLen, uOffset, pCallback, true);
	
	ZIP_INDEX_TYPE uSize = GetCount();
	for (ZIP_INDEX_TYPE i = 0; i < uSize; i++)
		m_centralDir[i]->m_uOffset += uOffset;

	if (pCallback)
		pCallback->CallbackEnd();			

	return true;
}
ZipArchive.cpp1050
BOOL CZIPARCHIVE:PrependData(LPCTSTR lpszFilePath, LPCTSTR lpszNewExt)
bool  CZipArchive::PrependData(LPCTSTR lpszFilePath, LPCTSTR lpszNewExt)
{
	CZipFile file(lpszFilePath, CZipFile::modeRead | CZipFile::shareDenyNone);
	return PrependData(file, lpszNewExt);
}
ZipArchive.cpp1104
BOOL CZIPARCHIVE:PrependData(CZipAbstractFile& file, LPCTSTR lpszNewExt)
bool  CZipArchive::PrependData(CZipAbstractFile& file, LPCTSTR lpszNewExt)
{
	if (file.IsClosed())
	{
		ZIPTRACE("%s(%i) : File to prepend should be opened.\n");
		return false;
	}

	ZIP_SIZE_TYPE uOffset = (ZIP_SIZE_TYPE)file.GetLength();
	if (uOffset == 0)
		return true;

	if (!ShiftData(uOffset))
		return false;
	file.SeekToBegin();
	// do not use callback - self-extracting stubs should be small
	m_storage.Seek(0);

	char* buf = (char*)m_pBuffer;

	ZIP_SIZE_TYPE uTotalToMove = uOffset;
	ZIP_SIZE_TYPE uToRead;
	UINT uSizeRead;
	bool bBreak = false;
	DWORD bufSize = m_pBuffer.GetSize();
	do
	{
		uToRead = uTotalToMove > bufSize ? bufSize : uTotalToMove;
		uSizeRead = (UINT)file.Read(buf, (UINT)uToRead);
		if (!uSizeRead)
			break;
		uTotalToMove -= uSizeRead;
		if (uTotalToMove == 0)
			bBreak = true;			
		m_storage.m_pFile->Write(buf, uSizeRead);
	}
	while (!bBreak);

	if (m_storage.m_bInMemory || lpszNewExt == NULL)
		return true;

	CZipString szInitialPath = m_storage.m_pFile->GetFilePath();
	// must close to rename
	Close();
	CZipPathComponent zpc(szInitialPath);
	zpc.SetExtension(lpszNewExt);
	CZipString szNewPath = zpc.GetFullPath();
	if (!ZipPlatform::RenameFile(szInitialPath, szNewPath, false))
		return false;
#ifdef ZIP_ARCHIVE_LNX
	return ZipPlatform::SetExeAttr(szNewPath);
#else
	return true;
#endif	
}
ZipArchive.cpp1110
BOOL CZIPARCHIVE:AddNewFile(LPCTSTR lpszFilePath, int iComprLevel, bool bFullPath, int iSmartLevel, unsigned long nBufSize)
bool  CZipArchive::AddNewFile(LPCTSTR lpszFilePath,
                             int iComprLevel,          
                             bool bFullPath,
							 int iSmartLevel,
                             unsigned long nBufSize)
{
	
	CZipAddNewFileInfo zanfi (lpszFilePath, bFullPath);
	zanfi.m_iComprLevel = iComprLevel;
	zanfi.m_iSmartLevel = iSmartLevel;
	zanfi.m_nBufSize = nBufSize;
	return AddNewFile(zanfi);	
}
ZipArchive.cpp1166
BOOL CZIPARCHIVE:AddNewFile(LPCTSTR lpszFilePath, LPCTSTR lpszFileNameInZip, int iComprLevel, int iSmartLevel, unsigned long nBufSize)
bool  CZipArchive::AddNewFile(LPCTSTR lpszFilePath,
							 LPCTSTR lpszFileNameInZip,
                             int iComprLevel,                                       
							 int iSmartLevel,
                             unsigned long nBufSize)
{
	CZipAddNewFileInfo zanfi(lpszFilePath, lpszFileNameInZip);
	zanfi.m_iComprLevel = iComprLevel;
	zanfi.m_iSmartLevel = iSmartLevel;
	zanfi.m_nBufSize = nBufSize;
	return AddNewFile(zanfi);	
}
ZipArchive.cpp1180
BOOL CZIPARCHIVE:AddNewFile(CZipMemFile& mf, LPCTSTR lpszFileNameInZip, int iComprLevel, int iSmartLevel, unsigned long nBufSize)
bool  CZipArchive::AddNewFile(CZipMemFile& mf,
							 LPCTSTR lpszFileNameInZip,
                             int iComprLevel,                                       
							 int iSmartLevel,
                             unsigned long nBufSize)
{
	CZipAddNewFileInfo zanfi(&mf, lpszFileNameInZip);
	zanfi.m_iComprLevel = iComprLevel;
	zanfi.m_iSmartLevel = iSmartLevel;
	zanfi.m_nBufSize = nBufSize;
	return AddNewFile(zanfi);
}

/**
	A structure for the internal use only. Clears the password if necessary and
	restores it later (also in case of an exception).
*/
struct CZipSmClrPass
{
	CZipSmClrPass()
	{
		m_pZip = NULL;
	}

	void ClearPasswordSmartly( CZipArchive* pZip)
	{
		m_pZip = pZip;
		m_szPass = pZip->GetPassword();
		if (!m_szPass.IsEmpty())
			pZip->SetPassword();
	}

	~CZipSmClrPass()
	{
		if (!m_szPass.IsEmpty())
			m_pZip->SetPassword(m_szPass);
	}
private:
	CZipString m_szPass;
	 CZipArchive* m_pZip;
};
ZipArchive.cpp1193
BOOL CZIPARCHIVE:AddNewFile(CZipAddNewFileInfo& info)
bool  CZipArchive::AddNewFile(CZipAddNewFileInfo& info)
{
	// no need for ASSERT and TRACE here - it will be done by OpenNewFile
	
	if (!m_iBufferSize)
		return false;

	if (info.m_pFile)
		info.m_szFilePath = info.m_pFile->GetFilePath();
	else
	{
		CZipPathComponent::RemoveSeparators(info.m_szFilePath);
		if (info.m_szFilePath.IsEmpty())
			return false;	
	}

	bool bSegm = GetSegmMode() != 0;

	// checking the replace index
	if (!UpdateReplaceIndex(info.m_uReplaceIndex))
		return false;

	bool bReplace = info.m_uReplaceIndex != ZIP_FILE_INDEX_UNSPECIFIED;
	
	DWORD uAttr;
	time_t ttime;
	if (info.m_pFile)
	{
		uAttr = ZipPlatform::GetDefaultAttributes();
		ttime = time(NULL);
	}
	else
	{
		if (!ZipPlatform::GetFileAttr(info.m_szFilePath, uAttr))
			return false; // we don't know whether it is a file or a directory
		ZipPlatform::GetFileModTime(info.m_szFilePath, ttime);
	}
	CZipFileHeader header;		
	SetFileHeaderAttr(header, uAttr);
	if (info.m_szFileNameInZip.IsEmpty())
		info.m_szFileNameInZip = PredictFileNameInZip(info.m_szFilePath, info.m_bFullPath, header.IsDirectory() ? prDir : prFile);
	header.SetFileName(info.m_szFileNameInZip);
	header.SetTime(ttime);
	bool bInternal = (info.m_iSmartLevel & zipsmInternal01) != 0;
	
	if (header.IsDirectory()) // will never be when m_pFile is not NULL, so we don't check it
	{
		ASSERT(!info.m_pFile); // should never happened
		ASSERT(!bInternal);

		CZipActionCallback* pCallback = GetCallback(CZipActionCallback::cbAdd); 

		if (pCallback)
		{
			pCallback->Init(info.m_szFileNameInZip, info.m_szFilePath);
			pCallback->SetTotal(0); // in case of calling LeftToProcess() afterwards		
		}

		// clear password for a directory
		CZipSmClrPass smcp;
		if (info.m_iSmartLevel & zipsmCPassDir)
			smcp.ClearPasswordSmartly(this);

		bool bRet = OpenNewFile(header, CZipCompressor::levelStore, NULL, info.m_uReplaceIndex);
		
		CloseNewFile();
		if (pCallback)
			pCallback->CallbackEnd();
		
		return bRet;		
	}
	
	CZipSmClrPass smcp;
	bool bIsCompression = info.m_iComprLevel != 0;
	bool bEff = (info.m_iSmartLevel & zipsmCheckForEff)&& bIsCompression;
	bool bCheckForZeroSized = (info.m_iSmartLevel & zipsmCPFile0) && WillEncryptNextFile();
	bool bCheckForSmallFiles = (info.m_iSmartLevel & zipsmNotCompSmall) && bIsCompression;
	ZIP_SIZE_TYPE uFileSize = ZIP_SIZE_TYPE(-1);
	bool bNeedTempArchive = (bEff && bSegm) || (bReplace && bIsCompression);
	if (bCheckForSmallFiles || bCheckForZeroSized || bNeedTempArchive)
	{
		
		if (info.m_pFile)
			uFileSize = (ZIP_SIZE_TYPE)info.m_pFile->GetLength();
		else
		{
			if (!ZipPlatform::GetFileSize(info.m_szFilePath, uFileSize) && bEff)
				bEff = false; // the file size is needed only when efficient in a segmented archive
		}

		if (uFileSize !=  ZIP_SIZE_TYPE(-1))
		{
			if (bCheckForZeroSized && uFileSize == 0)
				smcp.ClearPasswordSmartly(this);			
			if (bCheckForSmallFiles && uFileSize < 5)
				info.m_iComprLevel = 0;			
		}
	}
	bool bEffInMem = bEff && (info.m_iSmartLevel & zipsmMemoryFlag);
	CZipString szTempFileName;
	if (bNeedTempArchive && (bEffInMem || 
		!(szTempFileName = ZipPlatform::GetTmpFileName(
			m_szTempPath.IsEmpty() ? NULL : (LPCTSTR)m_szTempPath, uFileSize)
		).IsEmpty()))
	{
		CZipMemFile* pmf = NULL;
		 CZipArchive zip;
		try
		{
			// compress first to a temporary file, if ok - copy the data, if not - add storing
			
			if (bEffInMem)
			{
				pmf = new CZipMemFile;
				zip.Open(*pmf, zipCreate);
			}
			else
				zip.Open(szTempFileName, zipCreate);
			zip.SetRootPath(m_szRootPath);
			zip.SetPassword(GetPassword());
			zip.SetEncryptionMethod(m_iEncryptionMethod);
			zip.SetSystemCompatibility(m_iArchiveSystCompatib);
			zip.SetCallback(GetCallback(CZipActionCallback::cbAdd), CZipActionCallback::cbAdd);
			// create a temporary file
			ZIP_INDEX_TYPE uTempReplaceIndex = info.m_uReplaceIndex;
			info.m_iSmartLevel = zipsmLazy;
			info.m_uReplaceIndex = ZIP_FILE_INDEX_UNSPECIFIED;
			if (!zip.AddNewFile(info))
				throw false;
			info.m_uReplaceIndex = uTempReplaceIndex;

			// this may also happen when bReplace, but not in a segmented archive
			if (bEff)
			{
				if (!zip[0]->CompressionEfficient())
				{
					info.m_iComprLevel = 0;
					info.m_iSmartLevel = zipsmInternal01;
					// compression is not efficient, store instead
					throw AddNewFile(info);
				}
			}
			zip.m_storage.Flush();
			InitBuffer();
			throw GetFromArchive(zip, 0, NULL, info.m_uReplaceIndex, true, GetCallback(CZipActionCallback::cbAddTmp));
		}
		catch (bool bRet)
		{
			zip.Close(!bRet); // that doesn't really matter how it will be closed
			if (pmf)
				delete pmf;
			if (!bEffInMem)
				ZipPlatform::RemoveFile(szTempFileName, false);
			ReleaseBuffer();
			return bRet;
		}
		catch (...)
		{
			zip.Close(true);
			if (pmf)
				delete pmf;
			if (!bEffInMem)
				ZipPlatform::RemoveFile(szTempFileName, false);
			ReleaseBuffer();
			throw;
		}
	}

	// try to open before adding
	CZipFile f;
	CZipAbstractFile *pf;
	if (info.m_pFile)
	{
		pf = info.m_pFile;
		pf->SeekToBegin();
	}
	else
	{
		// cannot be shareDenyWrite		
		// If you specify the GENERIC_READ and GENERIC_WRITE access modes along with the FILE_SHARE_READ and FILE_SHARE_WRITE sharing modes in your first call to CreateFile. If you specify the GENERIC_READ and GENERIC_WRITE access modes and the FILE_SHARE_READ sharing mode only in your second call to CreateFile, the function will fail with a sharing violation because the read-only sharing mode specified in the second call conflicts with the read/write access that has been granted in the first call.
		// Original information was here (but not any longer): http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/creating_and_opening_files.asp
		if (!f.Open(info.m_szFilePath, CZipFile::modeRead | CZipFile::shareDenyNone, false))
			return false;
		pf = &f;
	}

	ASSERT(pf);
	// call init before opening (in case of exception we have the names)
	uFileSize = (ZIP_SIZE_TYPE)pf->GetLength();
	
	// predict sizes in local header, so that zip64 can write extra header if needed
	header.m_uLocalUncomprSize = uFileSize;	
	if (!bIsCompression)
		header.m_uLocalComprSize = uFileSize;

	bool bRet;	
	if (bReplace)
	{
		ASSERT(!bIsCompression);		
		bRet = OpenNewFile(header, CZipCompressor::levelStore, NULL, info.m_uReplaceIndex);
	}
	else
		bRet = OpenNewFile(header, info.m_iComprLevel);
	if (!bRet)
		return false;

	// we do it here, because if in OpenNewFile is replacing 
	// then we get called cbMoveData callback before and it would 
	// overwrite callback information written in pCallback->Init()
	CZipActionCallback* pCallback =  GetCallback(bInternal ? CZipActionCallback::cbAddStore : CZipActionCallback::cbAdd);

	if (pCallback)
	{
		// Init cbAdd here as well - after smart add - to avoid double initiation when
		// temporary archive is used - it would init cbAdd again
		pCallback->Init(info.m_szFileNameInZip, info.m_szFilePath);
		pCallback->SetTotal(uFileSize);
	}

	CZipAutoBuffer buf(info.m_nBufSize);
	DWORD iRead;
	int iAborted = 0;
	do
	{
		iRead = pf->Read(buf, info.m_nBufSize);
		if (iRead)
		{
			WriteNewFile(buf, iRead);
			if (pCallback && !pCallback->RequestCallback(iRead))
			{
				if (iRead == buf.GetSize() && pf->Read(buf, 1) != 0) // test one byte if there is something left
				{						
					if (!m_storage.IsSegmented() && !bReplace)
					{
						RemoveLast(true);														
						iAborted = CZipException::abortedSafely;
					}
					else
						iAborted = CZipException::abortedAction;
					// close new file with bException set to true, even if abortedSafely, 
					// because in that case we have removed the last file - there is nothing to close
					CloseNewFile(true);
				}
				else
					// temporary value - possible safe abort
					iAborted = CZipException::aborted;				
				break;
			}				
		}		
	}
	while (iRead == buf.GetSize());

	if (pCallback)
	{
		if (!iAborted && !pCallback->RequestLastCallback())	  
			// temporaty value - safe abort
			iAborted = CZipException::aborted;

		if (!iAborted)
		{
			CloseNewFile();
			pCallback->CallbackEnd();
		}
		else
		{
			// possible safe abort
			if (iAborted == CZipException::aborted)
			{
				bool bRet;
				try
				{
					bRet = CloseNewFile();
				}
#ifdef ZIP_ARCHIVE_MFC
				catch(CException* e)
				{
					e->Delete();
					bRet = false;
				}
#endif
				catch(...)
				{
					bRet = false;
				}
				if (bRet)
					iAborted = CZipException::abortedSafely;
				else
				{
					CloseNewFile(true);
					iAborted = CZipException::abortedAction;
				}
			}
			pCallback->CallbackEnd();	
			CZipException::Throw(iAborted); // throw to distinguish from other return codes
		}
	}
	else
		CloseNewFile();
	
	if (bEff)
	{
		// remove the last file and add it without the compression if needed
		if (!info.m_pFile)
			f.Close();

		buf.Release();
		if (RemoveLast())
		{
			info.m_iComprLevel = 0;
			info.m_iSmartLevel = zipsmInternal01;
			return AddNewFile(info);
		}
	}
	return true;		
}
ZipArchive.cpp1235
BOOL CZIPARCHIVE:RemoveLast(bool bRemoveAnyway)
bool  CZipArchive::RemoveLast(bool bRemoveAnyway)
{
	if (GetCount() == 0)
		return false;
	ZIP_INDEX_TYPE uIndex = (ZIP_INDEX_TYPE)(GetCount() - 1);
	CZipFileHeader* pHeader = m_centralDir[uIndex];

	if (!bRemoveAnyway && pHeader->CompressionEfficient())
		return false;

	m_centralDir.RemoveLastFile(pHeader, uIndex);
	return true;
}

class CZipRootPathRestorer
{
	CZipString m_szOldRootPath;
	 CZipArchive* m_pZip;
public:	
	CZipRootPathRestorer()
	{
		m_pZip = NULL;
	}
	void SetNewRootPath( CZipArchive* pZip, LPCTSTR lpszNewRoot)
	{
		m_pZip = pZip;
		m_szOldRootPath = m_pZip->GetRootPath();
		m_pZip->SetRootPath(lpszNewRoot);
	}
	~CZipRootPathRestorer()
	{
		if (m_pZip)
			m_pZip->SetRootPath(m_szOldRootPath);
	}
};

class CCalculateAddFilesEnumerator : public ZipArchiveLib::CDirEnumerator
{
	CZipActionCallback* m_pCallback;
public:		
	ZIP_FILE_USIZE m_uTotalBytes;
	ZIP_FILE_USIZE m_uTotalFiles;
	CCalculateAddFilesEnumerator(LPCTSTR lpszDirectory, bool bRecursive, CZipActionCallback* pCallback)
		:ZipArchiveLib::CDirEnumerator(lpszDirectory, bRecursive)
	{
		m_pCallback = pCallback;
		m_uTotalFiles = m_uTotalBytes = 0;
	}
protected:
	void OnEnumerationBegin()
	{
		if (m_pCallback)
			m_pCallback->Init();
	}

	bool Process(LPCTSTR, const ZipArchiveLib::CFileInfo& info)
	{
		m_uTotalFiles++;
		m_uTotalBytes += info.m_uSize;
		if (m_pCallback && !m_pCallback->RequestCallback())
			return false;
		else
			return true;
	}

	void OnEnumerationEnd(bool bResult)
	{
		if (m_pCallback)
		{
			if (bResult)
				bResult = m_pCallback->RequestLastCallback();
			m_pCallback->CallbackEnd();
			// can be false only, if the callback returns false
			if (!bResult)
				CZipException::Throw(CZipException::abortedSafely);
		}
	}
};

class CAddFilesEnumerator : public ZipArchiveLib::CDirEnumerator
{
	 CZipArchive* m_pZip;
	CZipActionCallback* m_pMultiCallback;
	int m_iComprLevel;
	int m_iSmartLevel;
	unsigned long m_nBufSize;
public:
	CAddFilesEnumerator(LPCTSTR lpszDirectory, 
			bool bRecursive, 
			 CZipArchive* pZip, 
			int iComprLevel, 
			int iSmartLevel, 
			unsigned long nBufSize,
			CZipActionCallback* pMultiCallback)
		:ZipArchiveLib::CDirEnumerator(lpszDirectory, bRecursive), m_pZip(pZip)
	{
		m_iComprLevel = iComprLevel;
		m_nBufSize = nBufSize;
		m_iSmartLevel = iSmartLevel;
		m_pMultiCallback = pMultiCallback;
	}
protected:
	bool Process(LPCTSTR lpszPath, const ZipArchiveLib::CFileInfo&)
	{
		bool ret = m_pZip->AddNewFile(lpszPath, m_iComprLevel, m_pZip->GetRootPath().IsEmpty() != 0, m_iSmartLevel, m_nBufSize);
		if (ret && m_pMultiCallback)
			if (!m_pMultiCallback->MultiActionsNext())
				CZipException::Throw(CZipException::abortedSafely);
		return ret;
	}
};
ZipArchive.cpp1551
BOOL CZIPARCHIVE:AddNewFiles(LPCTSTR lpszPath, CFileFilter& filter, bool bRecursive, int iComprLevel, bool bSkipInitialPath, int iSmartLevel, unsigned long nBufSize)
bool  CZipArchive::AddNewFiles(LPCTSTR lpszPath,
								CFileFilter& filter,
								bool bRecursive,
								int iComprLevel,
								bool bSkipInitialPath,
								int iSmartLevel,
								unsigned long nBufSize)
{
	CZipRootPathRestorer restorer;
	if (bSkipInitialPath)
		restorer.SetNewRootPath(this, lpszPath);

	CZipActionCallback* pMultiCallback = GetCallback(CZipActionCallback::cbMultiAdd);
	if (pMultiCallback)
	{		
		// if multi callback is set, calculate total data to process
		// call cbCalculateForMulti in the meantime
		CCalculateAddFilesEnumerator calculateEnumerator(lpszPath, bRecursive, GetCallback(CZipActionCallback::cbCalculateForMulti));
		if (!calculateEnumerator.Start(filter))
			return false;
		if (pMultiCallback->m_iType != CZipActionCallback::cbMultiAdd)
			// may happen, if it is the same as calculate
			pMultiCallback->m_iType = CZipActionCallback::cbMultiAdd;
		pMultiCallback->MultiActionsInit((ZIP_SIZE_TYPE)calculateEnumerator.m_uTotalFiles, (ZIP_SIZE_TYPE)calculateEnumerator.m_uTotalBytes, CZipActionCallback::cbAdd);
	}

	try
	{
		CAddFilesEnumerator addFilesEnumerator(lpszPath, bRecursive, this, iComprLevel, iSmartLevel, nBufSize, pMultiCallback);
		bool ret = addFilesEnumerator.Start(filter);
		if (pMultiCallback)
			pMultiCallback->MultiActionsEnd();
		return ret;
	}
	catch(...)
	{
		if (pMultiCallback)
			pMultiCallback->MultiActionsEnd();
		throw;
	}
}


CZipString  CZipArchive::GetArchivePath() const
{
	if (IsClosed(false))
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return _T("");
	}
	return m_storage.m_pFile->GetFilePath();
}

CZipString  CZipArchive::GetGlobalComment() const
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return _T("");
	}
	CZipString temp;
	m_centralDir.GetComment(temp);
	return temp;
}
ZipArchive.cpp1663
BOOL CZIPARCHIVE:SetGlobalComment(LPCTSTR lpszComment)
bool  CZipArchive::SetGlobalComment(LPCTSTR lpszComment)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}
	if (m_storage.IsSegmented() == -1)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot modify the global comment of an existing segmented archive.\n");
		return false;
	}

	m_centralDir.SetComment(lpszComment);
	if (m_bAutoFlush)
		Flush();

	return true;
}



ZIP_VOLUME_TYPE  CZipArchive::GetCurrentVolume() const 
{
	return (ZIP_VOLUME_TYPE)(m_storage.GetCurrentVolume() + 1);
}
ZipArchive.cpp1728
BOOL CZIPARCHIVE:SetFileComment(ZIP_INDEX_TYPE uIndex, LPCTSTR lpszComment)
bool  CZipArchive::SetFileComment(ZIP_INDEX_TYPE uIndex, LPCTSTR lpszComment)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}
	if (m_storage.IsSegmented() == -1)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot modify the file comment in an existing segmented archive.\n");
		return false;
	}
	
	m_centralDir.SetFileComment(uIndex, lpszComment);
	if (m_bAutoFlush)
		Flush();
	return true;
}
ZipArchive.cpp1755
BOOL CZIPARCHIVE:SetPassword(LPCTSTR lpszPassword)
bool  CZipArchive::SetPassword(LPCTSTR lpszPassword)
{
	if (m_iFileOpened != nothing)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot change the password when a file is opened.\n");
		return false; // it's important not to change the password when the file inside archive is opened
	}
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : Setting the password for a closed archive has no effect.\n");
	}
	if (lpszPassword)
		ZipCompatibility::ConvertStringToBuffer(lpszPassword, m_pszPassword, CP_ACP);
	else
		m_pszPassword.Release();
	return true;
}
ZipArchive.cpp1774
BOOL CZIPARCHIVE:SetEncryptionMethod(int iEncryptionMethod)
bool  CZipArchive::SetEncryptionMethod(int iEncryptionMethod)
{
	if (m_iFileOpened == compress)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot change the encryption method when there is a file opened for compression.\n");
		return false;
	}	
	
	if (iEncryptionMethod != CZipCryptograph::encNone && !CZipCryptograph::IsEncryptionSupported(iEncryptionMethod))
		return false;
	m_iEncryptionMethod = iEncryptionMethod;
	return true;
}

struct CZipEncryptFileInfo
{
	CZipEncryptFileInfo()
	{
		m_pHeader = NULL;
		m_uLocalSizeDiff = 0;
		m_uDescriptorSizeDiff = 0;
		m_uIndex = 0;
	}
	CZipEncryptFileInfo(CZipFileHeader* pHeader, DWORD uLocalSizeDiff, 
		DWORD uDescriptorSizeDiff, ZIP_INDEX_TYPE uIndex, ZIP_SIZE_TYPE uDataOffset)
		:m_pHeader(pHeader), m_uLocalSizeDiff(uLocalSizeDiff), 
		m_uDescriptorSizeDiff(uDescriptorSizeDiff), m_uIndex(uIndex), m_uUncompressedOffset(uDataOffset)
	{		
	}

	CZipFileHeader* m_pHeader;
	DWORD m_uLocalSizeDiff;
	DWORD m_uDescriptorSizeDiff;
	ZIP_INDEX_TYPE m_uIndex;
	ZIP_SIZE_TYPE m_uUncompressedOffset;
	ZIP_SIZE_TYPE GetLastDataOffset()
	{
		return m_uUncompressedOffset + m_pHeader->m_uOffset;
	}
};
ZipArchive.cpp1792
BOOL CZIPARCHIVE:EncryptFilesInternal(CZipIndexesArray* pIndexes)
bool  CZipArchive::EncryptFilesInternal(CZipIndexesArray* pIndexes)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}
	
	if (m_storage.IsSegmented())
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot encrypt existing files in a segmented archive.\n");
		return false;
	}

	if (m_storage.m_bReadOnly)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot encrypt files in a read-only archive.\n");
		return false;
	}
	
	if (m_iFileOpened)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot encrypt files if there is a file opened.\n");
		return false;
	}

	if (GetCount() == 0)
	{
		ZIPTRACE("%s(%i) : There is nothing to encrypt: the archive is empty.\n");
		return false;
	}

	if (!WillEncryptNextFile())
	{
		ZIPTRACE("%s(%i) : An encryption method and a password must be set.\n");
		return false;
	}

	bool bAll;
	ZIP_ARRAY_SIZE_TYPE i;
	if (pIndexes == NULL)
	{
		bAll = true;
		i = (ZIP_ARRAY_SIZE_TYPE)GetCount();
	}
	else
	{
		bAll = false;
		pIndexes->Sort(true);
		i = pIndexes->GetSize();	
	}	

	CZipActionCallback* pCallback = GetCallback(CZipActionCallback::cbEncryptPrepare);
	if (pCallback)
	{
		pCallback->Init();
		pCallback->SetTotal((ZIP_SIZE_TYPE)i);
	}
	bool bAborted = false;

	CZipArray infos;
	ZIP_SIZE_TYPE uExtraData = 0;		
    while (i > 0)
    {
        i--;
		ZIP_INDEX_TYPE idx;
		if (bAll)
			idx = (ZIP_INDEX_TYPE)i;
		else
		{
			idx = pIndexes->GetAt(i);
			if (!m_centralDir.IsValidIndex(idx))
			{
				if (pCallback && !pCallback->RequestCallback())				
				{
					bAborted = true;
					break;
				}
				continue;
			}
		}		
		CZipFileHeader* pHeader = GetFileInfo(idx);

        if (pHeader->IsEncrypted())
		{
			if (pCallback && !pCallback->RequestCallback())				
			{
				bAborted = true;
				break;
			}
			continue;
		}

		ReadLocalHeaderInternal(idx);
		DWORD uOrigSize = pHeader->GetLocalSize(true);
		DWORD uOrigDescriptorSize = pHeader->GetDataDescriptorSize(&m_storage);
		
		pHeader->m_uEncryptionMethod = (BYTE)m_iEncryptionMethod;	
		pHeader->UpdateFlag(m_storage.IsSegmented() != 0);
		
		// needed for GetLocalSize
		pHeader->PrepareFileName();
		DWORD uLocalDiff = pHeader->GetLocalSize(false) - uOrigSize;
		DWORD uDescriptorDiff = pHeader->GetDataDescriptorSize(&m_storage) - uOrigDescriptorSize;
		uExtraData += uLocalDiff + uDescriptorDiff;
		infos.Add(CZipEncryptFileInfo(pHeader, uLocalDiff, uDescriptorDiff, idx, pHeader->m_uOffset + uOrigSize));
		if (pCallback && !pCallback->RequestCallback())				
		{
			bAborted = true;
			break;
		}
    }    

	if (pCallback)
	{
		if (!bAborted && !pCallback->RequestLastCallback())
			bAborted = true;
		pCallback->CallbackEnd();
		if (bAborted)
			CZipException::Throw(CZipException::abortedAction);
	}

	ZIP_ARRAY_SIZE_TYPE uSize = infos.GetSize();
	if (!uSize)
	{
		ZIPTRACE("%s(%i) : There are no files to encrypt.\n");
		return true;
	}	

	m_centralDir.RemoveFromDisk();

	CZipActionCallback* pMultiCallback = GetCallback(CZipActionCallback::cbMultiEncrypt);

	ZIP_ARRAY_SIZE_TYPE idxIdx;
	ZIP_INDEX_TYPE idx;	

	if (pMultiCallback)
	{	
		ZIP_SIZE_TYPE uTotalToMove = 0;
		ZIP_SIZE_TYPE uTotalToEncrypt = 0;
	
		// move files
		idxIdx = 0;
		// infos array has data from largest index to the smallest	
		CZipEncryptFileInfo info = infos[0];		
		idx = GetCount();
		
		ZIP_SIZE_TYPE uLastOffset = m_storage.GetLastDataOffset();		
		ZIP_INDEX_TYPE lastNormalIdx = ZIP_FILE_INDEX_UNSPECIFIED;
		while (idx > 0)
		{
			idx--;
			if (idx == info.m_uIndex)
			{				
				if (lastNormalIdx != ZIP_FILE_INDEX_UNSPECIFIED)
				{
					// compensate changed offset
					uTotalToMove += uLastOffset - GetFileInfo(lastNormalIdx)->m_uOffset;										
					lastNormalIdx = ZIP_FILE_INDEX_UNSPECIFIED;
				}
				uTotalToMove += info.m_pHeader->m_uComprSize;
				uTotalToEncrypt += info.m_pHeader->m_uComprSize;
				
				// no more files to encrypt
				if (++idxIdx == uSize)
					break;				
				uLastOffset = info.m_pHeader->m_uOffset;
				info = infos[idxIdx];
			}
			else
				lastNormalIdx = idx;
		}
		pMultiCallback->MultiActionsInit((ZIP_SIZE_TYPE)uSize, uTotalToMove + uTotalToEncrypt, CZipActionCallback::cbEncryptMoveData);
	}
	

	try
	{
		// move files
		idxIdx = 0;
		// infos array has data from largest index to the smallest	
		CZipEncryptFileInfo info = infos[0];		
		idx = GetCount();
		
		DWORD uExtraBefore = CZipCryptograph::GetEncryptedInfoSizeBeforeData(m_iEncryptionMethod);
		DWORD uExtraAfter = CZipCryptograph::GetEncryptedInfoSizeAfterData(m_iEncryptionMethod);
		// the total amount of extra data
		uExtraData += ((uExtraBefore + uExtraAfter) * infos.GetSize());
				
		ZIP_SIZE_TYPE uLastOffset = m_storage.GetLastDataOffset();		
		ZIP_INDEX_TYPE lastNormalIdx = ZIP_FILE_INDEX_UNSPECIFIED;
		InitBuffer();
		pCallback = GetCallback(CZipActionCallback::cbEncryptMoveData);
		while (idx > 0)
		{
			idx--;
			if (idx == info.m_uIndex)
			{				
				if (lastNormalIdx != ZIP_FILE_INDEX_UNSPECIFIED)
				{
					// compensate changed offset
					ZIP_SIZE_TYPE uStartOffset = GetFileInfo(lastNormalIdx)->m_uOffset - uExtraData; 					
					if (pCallback)
					{
						pCallback->Init();
						pCallback->SetTotal(uLastOffset - uStartOffset);
					}					
					MovePackedFiles(uStartOffset, uLastOffset, uExtraData, pCallback, true);
					if (pCallback)
						pCallback->CallbackEnd();
					lastNormalIdx = ZIP_FILE_INDEX_UNSPECIFIED;
				}
				uExtraData -= (uExtraAfter + info.m_uDescriptorSizeDiff);
				if (pCallback)
				{
					pCallback->Init();
					pCallback->SetTotal(info.m_pHeader->m_uComprSize);
				}					
				MovePackedFiles(info.m_uUncompressedOffset, info.m_uUncompressedOffset + info.m_pHeader->m_uComprSize, uExtraData, pCallback, true);
				if (pCallback)
					pCallback->CallbackEnd();

				// no more files to encrypt
				if (++idxIdx == uSize)
					break;

				uExtraData -= (uExtraBefore + info.m_uLocalSizeDiff);
				// use original offsett
				uLastOffset = info.m_pHeader->m_uOffset;
				// now change the offset (not counting expanded local header - it changed the offset of data, not the offset of local header)
				info.m_pHeader->m_uOffset += uExtraData;			
							
				info = infos[idxIdx];
			}
			else
			{
				lastNormalIdx = idx;
				GetFileInfo(idx)->m_uOffset += uExtraData;
			}
		}
		bAborted = false;
		ZIP_SIZE_TYPE uToEncrypt = 0;
		i = uSize;
		// now encrypt the files (starting from the first one in the archive - this way the general direction of data copying is kept
		CreateCryptograph(m_iEncryptionMethod);
		if (pMultiCallback)
			pMultiCallback->SetReactType(CZipActionCallback::cbEncrypt);
		pCallback = GetCallback(CZipActionCallback::cbEncrypt);
		while (i > 0)
		{	
			i--;
			CZipEncryptFileInfo inf = infos[i];
			CZipFileHeader* pHeader = inf.m_pHeader;
			uToEncrypt = pHeader->m_uComprSize;
			if (pCallback)
			{
				pCallback->Init(pHeader->GetFileName());
				pCallback->SetTotal(uToEncrypt);
			}	

			m_storage.Seek(pHeader->m_uOffset);
			pHeader->WriteLocal(&m_storage);		
			// take the number of bytes to encode, before m_uComprSize is modified			
			m_pCryptograph->InitEncode(m_pszPassword, *pHeader, m_storage);
			m_storage.Flush();

			if (uToEncrypt)
			{
				DWORD bufSize = m_pBuffer.GetSize();
				char* buf = (char*)m_pBuffer;
				ZIP_SIZE_TYPE uToRead;
				UINT uSizeRead;				
				bool bBreak = false;
				CZipAbstractFile* pFile = m_storage.m_pFile;
				ZIP_FILE_USIZE uPosition = pFile->GetPosition();
				// the file pointer should be already positioned on the data
				do
				{
					uToRead = uToEncrypt > bufSize ? bufSize : uToEncrypt;
					uSizeRead = (UINT)pFile->Read(buf, (UINT)uToRead);
					if (!uSizeRead)
						break;
					uToEncrypt -= uSizeRead;
					if (uToEncrypt == 0)
						bBreak = true;
					
					m_pCryptograph->Encode(buf, uSizeRead);
					pFile->Seek(uPosition);
					pFile->Write(buf, uSizeRead);
					uPosition += uSizeRead;

					if (pCallback && !pCallback->RequestCallback(uSizeRead))
					{
						bAborted = true;
						break;
					}
					if (pMultiCallback)
						pMultiCallback->MultiActionsNext();
				}
				while (!bBreak);			
			}

			// copying from a not segmented to a segmented archive so add the data descriptor

			// we want write the additional data only if everything is all right, but we don't want to flush the storage before 
			// (and we want to flush the storage before throwing an exception, if something is wrong)
			if (uToEncrypt == 0)
			{
				m_pCryptograph->FinishEncode(*pHeader, m_storage);
				// it will be written only if needed
				pHeader->WriteDataDescriptor(&m_storage);
				m_storage.Flush();
			}

			if (pCallback)
			{
				if (!bAborted && !pCallback->RequestLastCallback())
					bAborted = true;
								
				if (bAborted)
				{
					pCallback->CallbackEnd();
					CZipException::Throw(CZipException::abortedAction);
				}
			}

			if (uToEncrypt > 0)
				ThrowError(CZipException::badZipFile);

			if (pCallback)
				pCallback->CallbackEnd();
		}
		
		m_storage.FlushFile();
		ClearCryptograph();	

	}
	catch(...)
	{
		if (pMultiCallback)
			pMultiCallback->MultiActionsEnd();
		throw;
	}

	if (pMultiCallback)
		pMultiCallback->MultiActionsEnd();
	return true;

}
ZipArchive.cpp1833
BOOL CZIPARCHIVE:SetCompressionMethod(WORD uCompressionMethod)
bool  CZipArchive::SetCompressionMethod(WORD uCompressionMethod)
{
	if (m_iFileOpened == compress)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot change the compression method when there is a file opened for compression.\n");
		return false; 
	}
	if (uCompressionMethod == CZipCompressor::methodStore)
	{
		ZIPTRACE("%s(%i) : Use the compression level CZipCompressor::levelStore when compressing files instead.\n");
		return false; 
	}

	if (!CZipCompressor::IsCompressionSupported(uCompressionMethod))
	{
		ZIPTRACE("%s(%i) : The compression method is not supported.\n");
		return false; 
	}

	m_uCompressionMethod = uCompressionMethod;
	return true;
}

CZipString  CZipArchive::GetPassword()const 
{
	CZipString temp;
	ZipCompatibility::ConvertBufferToString(temp, m_pszPassword, CP_ACP);
	return temp;
}
ZipArchive.cpp2184
BOOL CZIPARCHIVE:TestFile(ZIP_INDEX_TYPE uIndex, DWORD uBufSize)
bool  CZipArchive::TestFile(ZIP_INDEX_TYPE uIndex, DWORD uBufSize)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}

	if (m_storage.IsSegmented() == 1)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot test a segmented archive in creation.\n");
		return false;
	}
	if (!uBufSize)
		return false;
	
	CZipFileHeader* pHeader = m_centralDir[uIndex];
	CZipActionCallback* pCallback = GetCallback(CZipActionCallback::cbTest);
	if (pCallback)
	{
		pCallback->Init(pHeader->GetFileName());
	}

	if (pHeader->IsDirectory())
	{
		if (pCallback)
			pCallback->SetTotal(0);

		// we do not test whether the password for the encrypted directory
		// is correct, since it seems to be senseless (anyway password 
		// encrypted directories should be avoided - it adds 12 bytes)
		ZIP_SIZE_TYPE uSize = pHeader->m_uComprSize;
		if ((uSize != 0 || uSize != pHeader->m_uUncomprSize)
			// different treating compressed directories
			&& !(pHeader->IsEncrypted() && uSize == 12 && !pHeader->m_uUncomprSize))
			CZipException::Throw(CZipException::dirWithSize);

		if (pCallback)
			pCallback->CallbackEnd();

		return true;
	}
	else
	{
		try
		{			
			if (pCallback)
				pCallback->SetTotal(pHeader->m_uUncomprSize);
			
			if (!OpenFile(uIndex))
				return false;
			CZipAutoBuffer buf(uBufSize);
			DWORD iRead;
			int iAborted = 0;
			for(;;)
			{	
				iRead = ReadFile(buf, buf.GetSize());
				if (!iRead)
				{
					if (pCallback && !pCallback->RequestLastCallback())
						iAborted = CZipException::abortedSafely;
					break;
				}
				if (pCallback && !pCallback->RequestCallback(iRead))
				{
					if (iRead == buf.GetSize() && ReadFile(buf, 1) != 0) // test one byte if there is something left
						iAborted = CZipException::abortedAction; 
					else
						iAborted = CZipException::abortedSafely; // we did it!
					break;
				}
			}

			if (!iAborted)
			{
				if (CloseFile() == 1)
				{
					if (pCallback)
						pCallback->CallbackEnd();
					return true;
				}
				else
					CZipException::Throw(CZipException::badZipFile);
			}
			else
			{
				if (iAborted == CZipException::abortedAction)
					CloseFile(NULL, true);
				else
				{
					bool bRet;
					try
					{
						bRet = CloseFile() == 1;
					}
					// if any exception was thrown, then we are not successful
					// catch all exceptions to thrown aborted exception only
#ifdef ZIP_ARCHIVE_MFC
					catch(CException* e)
					{
						e->Delete();
						bRet = false;
					}
#endif
					catch(...)
					{
						bRet = false;
					}
					if (!bRet)
					{
						CloseFile(NULL, true);
						iAborted = CZipException::abortedAction;
					}
				}

				pCallback->CallbackEnd();
				CZipException::Throw(iAborted);
			}
			return false; // to satisfy some compilers (some will complain)...
		}
		catch(...)
		{
			CloseFile(NULL, true);
			throw;
		}
	}
}

void  CZipArchive::SetFileHeaderAttr(CZipFileHeader& header, DWORD uAttr)const
{
	header.SetSystemCompatibility(m_iArchiveSystCompatib);
	header.SetSystemAttr(uAttr);
}
ZipArchive.cpp2214
VOID CZIPARCHIVE:EnableFindFast(bool bEnable)
void  CZipArchive::EnableFindFast(bool bEnable)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : Set it after opening the archive.\n");
		return;
	}
	m_centralDir.EnableFindFast(bEnable, m_bCaseSensitive);
}
ZipArchive.cpp2348
BOOL CZIPARCHIVE:SetSystemCompatibility(int iSystemComp)
bool  CZipArchive::SetSystemCompatibility(int iSystemComp)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : Set it after opening the archive.\n");
		return false;
	}

	if (m_iFileOpened == compress)
	{
		ZIPTRACE("%s(%i) : Set it before opening a file inside archive.\n");
		return false;
	}

	if (!ZipCompatibility::IsPlatformSupported(iSystemComp))
		return false;
	// change the name coding page, if it was not changed before
	if (m_stringSettings.IsStandardNameCodePage(m_iArchiveSystCompatib))
		m_stringSettings.SetDefaultNameCodePage(iSystemComp);	
	m_iArchiveSystCompatib = iSystemComp;
	
	return true;
}
ZipArchive.cpp2358
VOID CZIPARCHIVE:SetRootPath(LPCTSTR szPath)
void  CZipArchive::SetRootPath(LPCTSTR szPath)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : Set it after opening the archive.\n");
		return;
	}

	if (m_iFileOpened != nothing)
	{
		ZIPTRACE("%s(%i) : Set it before opening a file inside archive.\n");
		return;
	}

	if (szPath)
	{
		m_szRootPath = szPath;
		CZipPathComponent::RemoveSeparators(m_szRootPath);
	}
	else
		m_szRootPath.Empty();
}

CZipString  CZipArchive::TrimRootPath(CZipPathComponent &zpc)const 
{
	if (m_szRootPath.IsEmpty())
		return zpc.GetFileName();
	CZipString szPath = zpc.GetFullPath();
	return RemovePathBeginning(m_szRootPath, szPath, m_pZipCompare) ? szPath : zpc.GetFileName();
}
ZipArchive.cpp2382
BOOL CZIPARCHIVE:RemovePathBeginning(LPCTSTR lpszBeginning, CZipString& szPath, ZIPSTRINGCOMPARE pCompareFunction)
bool  CZipArchive::RemovePathBeginning(LPCTSTR lpszBeginning, CZipString& szPath, ZIPSTRINGCOMPARE pCompareFunction)
{
	CZipString szBeginning(lpszBeginning);
	CZipPathComponent::RemoveSeparators(szBeginning);
	int iRootPathLength = szBeginning.GetLength();
	if (iRootPathLength && szPath.GetLength() >= iRootPathLength &&
		(szPath.Left(iRootPathLength).*pCompareFunction)(szBeginning) == 0)
	{		
		// the beginning is the same
		if (szPath.GetLength() == iRootPathLength)
		{
			szPath.Empty();
			return true;
		}
		// is the end of m_szPathRoot only a beginning of a directory name? 
		// check for a separator
		// we know the length is larger, so we can write:
		if (CZipPathComponent::IsSeparator(szPath[iRootPathLength]))
		{			
			szPath = szPath.Mid(iRootPathLength);
			CZipPathComponent::RemoveSeparatorsLeft(szPath);
			return true;
		}
	}
	return false;
}
ZipArchive.cpp2413
VOID CZIPARCHIVE:SetTempPath(LPCTSTR lpszPath, bool bForce)
void  CZipArchive::SetTempPath(LPCTSTR lpszPath, bool bForce)
{
	m_szTempPath = lpszPath;
	if (lpszPath && bForce)
		ZipPlatform::ForceDirectory(lpszPath);
	CZipPathComponent::RemoveSeparators(m_szTempPath);
}

CZipString  CZipArchive::PredictFileNameInZip(LPCTSTR lpszFilePath, 
						 bool bFullPath, int iWhat)const 
{
	CZipString sz = lpszFilePath;
	if (sz.IsEmpty())
		return _T("");
	bool bAppend;
	switch (iWhat)
	{
	case prFile:
		bAppend = false;
		break;
	case prDir:
		bAppend = true;
		break;
	default:
		bAppend = CZipPathComponent::IsSeparator(sz[sz.GetLength() - 1]);
	}
	
	// remove for CZipPathComponent treating last name as a file even if dir
	CZipPathComponent::RemoveSeparators(sz);
	// it may be empty after removing separators, e.g.: "/"
	if (sz.IsEmpty())
		return _T("");
	CZipPathComponent zpc(sz);

	if (bFullPath)
	{
		if (m_bRemoveDriveLetter)
			sz = zpc.GetNoDrive();
	}
	else
		sz = TrimRootPath(zpc);

	if (bAppend && !sz.IsEmpty())
		CZipPathComponent::AppendSeparator(sz);
	return sz;	
}

CZipString  CZipArchive::PredictExtractedFileName(LPCTSTR lpszFileNameInZip, LPCTSTR lpszPath, bool bFullPath, LPCTSTR lpszNewName)const 
{
	CZipString szFile = lpszPath;
	CZipString sz = lpszNewName ? lpszNewName : lpszFileNameInZip;
	if (sz.IsEmpty())
		return szFile;
	if (!szFile.IsEmpty())
		CZipPathComponent::AppendSeparator(szFile);
	
	
	// remove for CZipPathComponent treating last name as a file even if dir
	CZipPathComponent::RemoveSeparators(sz);
	CZipPathComponent zpc(sz);
	szFile += bFullPath ? (m_bRemoveDriveLetter ? zpc.GetNoDrive() : sz) 
						  : TrimRootPath(zpc);	
	return szFile;
}

ZIP_SIZE_TYPE  CZipArchive::PredictMaximumFileSizeInArchive(LPCTSTR lpszFilePath, bool bFullPath) const
{
	DWORD attr;
	if (!ZipPlatform::GetFileAttr(lpszFilePath, attr))
		return 0;		
	CZipFileHeader fh;		
	SetFileHeaderAttr(fh, attr);
	if (!fh.IsDirectory())
		if (!ZipPlatform::GetFileSize(lpszFilePath, fh.m_uUncomprSize))
			return 0;	
	fh.SetFileName(PredictFileNameInZip(lpszFilePath, bFullPath, fh.IsDirectory() ? prDir  : prFile));
	return PredictMaximumFileSizeInArchive(fh);
}

ZIP_SIZE_TYPE  CZipArchive::PredictMaximumFileSizeInArchive(CZipFileHeader& fh) const
{
	fh.m_stringSettings = m_stringSettings;
	fh.m_uEncryptionMethod = WillEncryptNextFile() ? (BYTE)m_iEncryptionMethod : (BYTE)CZipCryptograph::encNone;
	fh.m_uMethod = CZipCompressor::methodStore;
	fh.PrepareData(CZipCompressor::levelStore, m_storage.IsSegmented() != 0);
	DWORD uLocalSize = fh.GetLocalSize(true);
	return fh.GetSize() + uLocalSize + fh.GetDataSize(true, false) + fh.GetDataDescriptorSize(&m_storage);
}
ZipArchive.cpp2440
VOID CZIPARCHIVE:SetAutoFlush(bool bAutoFlush)
void  CZipArchive::SetAutoFlush(bool bAutoFlush)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive should be opened first.\n");
		return;
	}
	if (m_storage.IsSegmented() != 0)
	{
		ZIPTRACE("%s(%i) : Cannot set auto-flush for a segmented archive.\n");
		return;
	}
	m_bAutoFlush = bAutoFlush;
}
ZipArchive.cpp2529
VOID CZIPARCHIVE:Flush()
void  CZipArchive::Flush()
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive should be opened first.\n");
		return;
	}

	if (m_storage.IsSegmented() < 0)
	{
		ZIPTRACE("%s(%i) : Cannot flush an existing segmented archive.\n");
		return;
	}
	WriteCentralDirectory();
	m_storage.FlushFile();
	if (m_storage.IsSegmented() > 0) // try to finalize a segmented archive without closing it
		m_storage.FinalizeSegm();
}


void  CZipArchive::GetCentralDirInfo(CZipCentralDir::CInfo& info)const
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive should be opened first.\n");
		return;
		
	}
	m_centralDir.GetInfo(info);
	if (GetSegmMode() > 0)
		info.m_uLastVolume = m_storage.GetCurrentVolume();
}
ZipArchive.cpp2544
VOID CZIPARCHIVE:FindMatches(LPCTSTR lpszPattern, CZipIndexesArray &ar, bool bFullPath)
void  CZipArchive::FindMatches(LPCTSTR lpszPattern, CZipIndexesArray &ar, bool bFullPath)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return;
	}

	//	ar.RemoveAll(); don't do this
	ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)GetCount();
	CWildcard wc(lpszPattern, m_bCaseSensitive);
	for (ZIP_INDEX_TYPE i = 0; i < uCount; i++)
	{
		CZipString sz = m_centralDir[i]->GetFileName();
		if (!bFullPath)
		{
			CZipPathComponent::RemoveSeparators(sz);
			CZipPathComponent zpc(sz);			
			sz = zpc.GetFileName();
		}
		if (wc.IsMatch(sz))
			ar.Add(i);
	}
}
ZipArchive.cpp2577
ZIP_INDEX_TYPE CZIPARCHIVE:WillBeDuplicated(LPCTSTR lpszFilePath, bool bFullPath, bool bFileNameOnly , int iWhat)
ZIP_INDEX_TYPE  CZipArchive::WillBeDuplicated(LPCTSTR lpszFilePath, bool bFullPath, bool bFileNameOnly , int iWhat)
{
	CZipString szFile;
	if (bFileNameOnly)
	{
		CZipPathComponent zpc(lpszFilePath);
		szFile = PredictFileNameInZip(zpc.GetFileName(), false, iWhat); 
	}
	else
		szFile = PredictFileNameInZip(lpszFilePath, bFullPath, iWhat);
	return FindFile(szFile, ffDefault, bFileNameOnly);
}
ZipArchive.cpp2602
BOOL CZIPARCHIVE:GetFromArchive( CZipArchive& zip, ZIP_INDEX_TYPE uIndex, LPCTSTR lpszNewFileName, ZIP_INDEX_TYPE uReplaceIndex, bool bKeepSystComp, CZipActionCallback* pCallback)
bool  CZipArchive::GetFromArchive( CZipArchive& zip, ZIP_INDEX_TYPE uIndex, LPCTSTR lpszNewFileName, ZIP_INDEX_TYPE uReplaceIndex, bool bKeepSystComp, CZipActionCallback* pCallback)
{
	if (this == &zip)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot get files from the same archive.\n");
		return false;
	}

	if (IsClosed() || zip.IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}
	
	if (m_iFileOpened || zip.m_iFileOpened)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot get files from another archive if there is a file opened.\n");
		return false;
	}
	
	if (m_storage.IsSegmented() == -1)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot add files to an existing segmented archive.\n");
		return false;
	}

	ASSERT(m_pBuffer.GetSize() > 0);

	bool bSegm = m_storage.IsSegmented() == 1;

	if (!zip.m_centralDir.IsValidIndex(uIndex))
		return false;

	zip.ReadLocalHeaderInternal(uIndex);

	CZipFileHeader originalHeader;
	// we need a copy - we are going to modify this
	if (!zip.GetFileInfo(originalHeader, uIndex))
		return false;
	if (zip.m_storage.IsSegmented() != 0 && originalHeader.m_uLocalComprSize == 0)
		// we must compensate for adding the encrypted info size to m_uLocalComprSize at the beginning of CZipFileHeader::WriteLocal()
		originalHeader.m_uLocalComprSize = originalHeader.m_uComprSize - originalHeader.GetEncryptedInfoSize();
	bool bConvertSystem = !bKeepSystComp && originalHeader.GetSystemCompatibility() != m_iArchiveSystCompatib;
	CZipString szFileName;
	if (lpszNewFileName != NULL)
	{
		szFileName = lpszNewFileName;
		originalHeader.SetFileName(lpszNewFileName);
	}
	else
		szFileName = originalHeader.GetFileName(); // empty

	if (bConvertSystem)
	{
		DWORD uAttr = originalHeader.GetSystemAttr();
		originalHeader.SetSystemCompatibility(m_iArchiveSystCompatib);
		originalHeader.SetSystemAttr(uAttr);
	}
	
	if (!UpdateReplaceIndex(uReplaceIndex))
		return false;

	bool bReplace = uReplaceIndex != ZIP_FILE_INDEX_UNSPECIFIED;
	if (bReplace && bSegm)
		return false;

	int iCallbackType = 0;
	if (pCallback)
		iCallbackType = pCallback->m_iType;

	if (!originalHeader.IsEncrypted() && WillEncryptNextFile())
	{
		originalHeader.m_uEncryptionMethod = (BYTE)m_iEncryptionMethod;
		CreateCryptograph(m_iEncryptionMethod);
	}
	else
		ClearCryptograph();

	// if the same callback is applied to cbMoveData, then the previous information about the type will be lost
	// we restore it later
	CZipFileHeader* pHeader = m_centralDir.AddNewFile(originalHeader, uReplaceIndex, originalHeader.GetCompressionLevel(), true);
	pHeader->m_stringSettings.m_uCommentCodePage = originalHeader.m_stringSettings.m_uCommentCodePage;
	
	// prepare this here: it will be used for GetLocalSize and WriteLocal
	pHeader->PrepareFileName();

	ZIP_SIZE_TYPE uTotalToMove = pHeader->m_uComprSize;

	if (bReplace)
	{
		ZIP_SIZE_TYPE uDataSize;
		if (m_pCryptograph)
			// the file will be encrypted and have not yet increased pHeader->m_uComprSize (in m_pCryptograph->InitEncode)
			uDataSize = pHeader->GetDataSize(false, false);
		else
			uDataSize = uTotalToMove;
		MakeSpaceForReplace(uReplaceIndex, uDataSize + pHeader->GetLocalSize(false) + pHeader->GetDataDescriptorSize(&m_storage), szFileName);
	}

	if (pCallback)
	{
		// must be set before Init()
		pCallback->m_iType = iCallbackType;
		pCallback->Init(szFileName, zip.GetArchivePath());
		pCallback->SetTotal(pHeader->m_uComprSize);
	}

	// must be written as not converted
	pHeader->WriteLocal(&m_storage); 
	if (m_pCryptograph)
		m_pCryptograph->InitEncode(m_pszPassword, *pHeader, m_storage);


	char* buf = (char*)m_pBuffer;

	ZIP_SIZE_TYPE uToRead;
	DWORD uSizeRead;	
	int iAborted = 0;
	bool bBreak = false;
	if (uTotalToMove)
	{
		DWORD bufSize = m_pBuffer.GetSize();
		do
		{
			uToRead = uTotalToMove > bufSize ? bufSize : uTotalToMove;
			uSizeRead = (UINT)zip.m_storage.Read(buf, (UINT)uToRead, false);
			if (!uSizeRead)
				break;
			uTotalToMove -= uSizeRead;
			if (uTotalToMove == 0)
				bBreak = true;
			
			if (m_pCryptograph)
				m_pCryptograph->Encode(m_pBuffer, uSizeRead);

			m_storage.Write(buf, uSizeRead, false);
			if (pCallback && !pCallback->RequestCallback(uSizeRead))
			{												
				if (uTotalToMove != 0) 
				{							
					if (!bSegm && !bReplace)
					{							
						m_centralDir.RemoveLastFile();
						iAborted = CZipException::abortedSafely;
					}
					else
						iAborted = CZipException::abortedAction; 
				}
				else
					iAborted = CZipException::abortedSafely;
				break;
				
			}
		}
		while (!bBreak);

		if (pCallback)
		{
			if (!iAborted && !pCallback->RequestLastCallback())
				iAborted = CZipException::abortedSafely;
			
			if (iAborted)
			{
				// when no exception, CallbackEnd() called later
				pCallback->CallbackEnd();
				CZipException::Throw(iAborted); // throw to distinguish from other return codes					
			}
		}
	}

	m_centralDir.m_pOpenedFile = NULL;
	// copying from a not segmented to a segmented archive so add the data descriptor

	// we want write the additional data only if everything is all right, but we don't want to flush the storage before 
	// (and we want to flush the storage before throwing an exception, if something is wrong)
	if (uTotalToMove == 0)
	{
		if (m_pCryptograph)
			m_pCryptograph->FinishEncode(*pHeader, m_storage);
		// it will be written only if needed
		pHeader->WriteDataDescriptor(&m_storage);
	}

	m_storage.Flush();
	if (uTotalToMove > 0)
		ThrowError(CZipException::badZipFile);

	if (pCallback)
		pCallback->CallbackEnd();

	ClearCryptograph();				
	return true;
}
ZipArchive.cpp2616
BOOL CZIPARCHIVE:GetFromArchive( CZipArchive& zip, CZipIndexesArray &aIndexes, bool bKeepSystComp)
bool  CZipArchive::GetFromArchive( CZipArchive& zip, CZipIndexesArray &aIndexes, bool bKeepSystComp)
{
	aIndexes.Sort(true);
	ZIP_INDEX_TYPE uFiles = (ZIP_INDEX_TYPE)aIndexes.GetSize();		
	InitBuffer();
	try
	{
		for (ZIP_INDEX_TYPE i = 0; i < uFiles; i++)
		{
			ZIP_INDEX_TYPE uFileIndex = aIndexes[(ZIP_ARRAY_SIZE_TYPE)i];
			if (!GetFromArchive(zip, uFileIndex, NULL, ZIP_FILE_INDEX_UNSPECIFIED, bKeepSystComp, GetCallback(CZipActionCallback::cbGet)))
			{
				ReleaseBuffer();
				return false;
			}
		}
	}
	catch (...)
	{
		ReleaseBuffer();
		throw;
	}
	ReleaseBuffer();
	if (m_bAutoFlush)
		Flush();
	return true;
}
ZipArchive.cpp2810
BOOL CZIPARCHIVE:RenameFile(ZIP_INDEX_TYPE uIndex, LPCTSTR lpszNewName)
bool  CZipArchive::RenameFile(ZIP_INDEX_TYPE uIndex, LPCTSTR lpszNewName)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}
	
	if (m_storage.IsSegmented())
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot rename files in a segmented archive.\n");
		return false;
	}
	
	if (m_iFileOpened)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot rename a file if there is a file opened.\n");
		return false;
	}
	CZipFileHeader* pHeader = (*this)[uIndex];
	if (pHeader == NULL)
		return false;

	CZipString szNewName(lpszNewName);
	if (pHeader->IsDirectory())
		CZipPathComponent::AppendSeparator(szNewName);
	else
		CZipPathComponent::RemoveSeparators(szNewName);
	CZipString szPreviousFileName = pHeader->GetFileName();
	if (szPreviousFileName.Collate(szNewName) == 0)
		return true;
	
	// don't copy the comment code page, it already could have been set using it's own code page (set CD CP, change comment, change CD CP)
	pHeader->m_stringSettings.m_bStoreNameInExtraData = m_stringSettings.m_bStoreNameInExtraData;
	pHeader->m_stringSettings.m_uNameCodePage = m_stringSettings.m_uNameCodePage;
	pHeader->SetFileName(szNewName);

	m_centralDir.RemoveFromDisk(); // does m_storage.Flush();
	// read local data - it may differ from central data
	char localInfo[4];
	m_storage.Seek(pHeader->m_uOffset + 26);
	m_storage.m_pFile->Read(localInfo, 4); // read at once
	WORD uFileNameLen, uExtraFieldSize;
	CBytesWriter::ReadBytes(uFileNameLen, localInfo);
	// skip endian issues - the variable will not be used, but written back as it is
	memcpy(&uExtraFieldSize, localInfo + 2, 2);
	
	// filename buffer already cleared (GetFileName), the conversion will take place
	pHeader->PrepareFileName();
	ASSERT(pHeader->m_pszFileNameBuffer.IsAllocated());
	WORD uNewFileNameLen = (WORD)pHeader->m_pszFileNameBuffer.GetSize();
	int iDelta = uNewFileNameLen - uFileNameLen;
	int iOffset = 0;
	CZipAutoBuffer buf, *pBuf;
	
	if (iDelta != 0)
	{
		// we need to make more or less space		
		InitBuffer();
		ZIP_SIZE_TYPE uStartOffset = pHeader->m_uOffset + 30 + uFileNameLen;
		ZIP_SIZE_TYPE uFileLen = (ZIP_SIZE_TYPE)m_storage.m_pFile->GetLength();
		ZIP_SIZE_TYPE uEndOffset = uFileLen - m_storage.m_uBytesBeforeZip;
		CZipActionCallback* pCallback = GetCallback(CZipActionCallback::cbRename);
		if (pCallback)
		{
			// do it right and sent the notification
			pCallback->Init(szPreviousFileName, GetArchivePath());
			pCallback->SetTotal(uEndOffset - uStartOffset);
		}
		bool bForward = iDelta > 0;
		if (bForward)
			m_storage.m_pFile->SetLength((ZIP_FILE_USIZE)(uFileLen + iDelta)); // ensure the seek is correct

		MovePackedFiles(uStartOffset, uEndOffset, abs(iDelta), pCallback, bForward);
		if (pCallback)
			pCallback->CallbackEnd();

		if (!bForward)
			m_storage.m_pFile->SetLength((ZIP_FILE_USIZE)(uFileLen + iDelta)); // delta < 0; shrink the file

		ReleaseBuffer();	

		ZIP_INDEX_TYPE uSize = (ZIP_INDEX_TYPE)GetCount();
		for (ZIP_INDEX_TYPE i = (ZIP_INDEX_TYPE)(uIndex + 1); i < uSize; i++)
			m_centralDir[i]->m_uOffset += iDelta;
		buf.Allocate(4 + uNewFileNameLen);
		CBytesWriter::WriteBytes(buf, uNewFileNameLen);
		// the variable was not used - we write it back as it was (no endian issues)
		// to write everything at once
		memcpy((char*)buf + 2, &uExtraFieldSize, 2);
		memcpy((char*)buf + 4, pHeader->m_pszFileNameBuffer, uNewFileNameLen);
		pBuf = &buf;
		iOffset = -4;
	}
	else
		pBuf = &pHeader->m_pszFileNameBuffer;
	
	m_storage.Seek(pHeader->m_uOffset + 30 + iOffset);
	m_storage.m_pFile->Write(*pBuf, pBuf->GetSize());
	m_centralDir.RebuildFindFastArray();
	if (m_bAutoFlush)
		Flush();
	
	return true;
}
ZipArchive.cpp2837
BOOL CZIPARCHIVE:UpdateReplaceIndex(ZIP_INDEX_TYPE& uReplaceIndex)
bool  CZipArchive::UpdateReplaceIndex(ZIP_INDEX_TYPE& uReplaceIndex)
{
	if (uReplaceIndex == ZIP_FILE_INDEX_UNSPECIFIED)
		return true;

	if (GetSegmMode() != 0)
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot replace files in a segmented archive.\n");		
		return false;
	}
	
	if (!m_centralDir.IsValidIndex(uReplaceIndex))
	{
		ZIPTRACE("%s(%i) : Not valid replace index.\n");
		return false;
	}
	if (uReplaceIndex == GetCount() - 1) // replacing last file in the archive
	{
		RemoveLast(true);
		uReplaceIndex = ZIP_FILE_INDEX_UNSPECIFIED;
	}
	return true;	
}
ZipArchive.cpp2943
VOID CZIPARCHIVE:MakeSpaceForReplace(ZIP_INDEX_TYPE uReplaceIndex, ZIP_SIZE_TYPE uTotal, LPCTSTR lpszFileName)
void  CZipArchive::MakeSpaceForReplace(ZIP_INDEX_TYPE uReplaceIndex, ZIP_SIZE_TYPE uTotal, LPCTSTR lpszFileName)
{		
	ASSERT(uReplaceIndex < GetCount() - 1);
	// we can't use the offset from the central directory here, because the header is already replaced
	ZIP_SIZE_TYPE uReplaceStart = (ZIP_SIZE_TYPE)m_storage.m_pFile->GetPosition() - m_storage.m_uBytesBeforeZip;
	
	// find the next offset (files in the central directory may not necessarily be ordered by offset)
	ZIP_SIZE_TYPE uReplaceEnd = ZIP_SIZE_TYPE(-1);
	ZIP_INDEX_TYPE i;
	for (i = 0; i < (ZIP_INDEX_TYPE)m_centralDir.GetCount(); i++)
		if (i != uReplaceIndex)
		{
			ZIP_SIZE_TYPE uOffset = m_centralDir[i]->m_uOffset;
			if (uOffset > uReplaceStart && uOffset < uReplaceEnd)
				uReplaceEnd = uOffset;
		}
		
	ZIP_SIZE_TYPE uReplaceTotal = uReplaceEnd - uReplaceStart;
	if (uTotal == uReplaceTotal)
		return;

	bool bForward = uTotal > uReplaceTotal;
	ZIP_SIZE_TYPE uDelta;
	if (bForward)
		uDelta = uTotal - uReplaceTotal;
	else
		uDelta = uReplaceTotal - uTotal;
	
	
	//	InitBuffer(); don't - the calling functions will
	CZipActionCallback* pCallback = GetCallback(CZipActionCallback::cbMoveData);
	ZIP_SIZE_TYPE uFileLen = (ZIP_SIZE_TYPE)m_storage.m_pFile->GetLength();
	ZIP_SIZE_TYPE uUpperLimit = uFileLen - m_storage.m_uBytesBeforeZip; // will be added in m_storage.Seek
	if (pCallback)
	{
		pCallback->Init(lpszFileName, GetArchivePath());
		pCallback->SetTotal(uUpperLimit - uReplaceEnd);
	}			
		
	if (bForward)
		m_storage.m_pFile->SetLength((ZIP_FILE_USIZE)(uFileLen + uDelta)); // ensure the seek is correct

	MovePackedFiles(uReplaceEnd, uUpperLimit, uDelta, pCallback, bForward);

	if (!bForward)
		m_storage.m_pFile->SetLength((ZIP_FILE_USIZE)(uFileLen - uDelta));

	m_storage.Seek(uReplaceStart);
	ZIP_INDEX_TYPE uSize = GetCount();
	for (i = (ZIP_INDEX_TYPE)(uReplaceIndex + 1); i < uSize; i++)
	{
		ZIP_SIZE_TYPE uOffset = m_centralDir[i]->m_uOffset;
		m_centralDir[i]->m_uOffset = bForward ? uOffset + uDelta : uOffset - uDelta;
	}
	if (pCallback)
		pCallback->CallbackEnd();			
}
ZipArchive.cpp2967
VOID CZIPARCHIVE:MovePackedFiles(ZIP_SIZE_TYPE uStartOffset, ZIP_SIZE_TYPE uEndOffset, ZIP_SIZE_TYPE uMoveBy, CZipActionCallback* pCallback, bool bForward, bool bLastCall)
void  CZipArchive::MovePackedFiles(ZIP_SIZE_TYPE uStartOffset, ZIP_SIZE_TYPE uEndOffset, ZIP_SIZE_TYPE uMoveBy, 
								  CZipActionCallback* pCallback, bool bForward, bool bLastCall)
{
	ASSERT(m_pBuffer.GetSize() > 0);
	
	ZIP_SIZE_TYPE uTotalToMove = uEndOffset - uStartOffset;
	ZIP_SIZE_TYPE uPack = uTotalToMove > m_pBuffer.GetSize() ? m_pBuffer.GetSize() : uTotalToMove;
	char* buf = (char*)m_pBuffer;
	
	
	UINT uSizeRead;
	bool bBreak = false;
	bool bAborted = false;
	do
	{
		if (uEndOffset - uStartOffset < uPack)
		{
			uPack = uEndOffset - uStartOffset;
			if (!uPack)
				break;
			bBreak = true;
			
		}
		ZIP_SIZE_TYPE uPosition = bForward ? uEndOffset - uPack : uStartOffset;
		
		m_storage.Seek(uPosition);
		uSizeRead = m_storage.m_pFile->Read(buf, (UINT)uPack);
		if (!uSizeRead)
			break;
		
		if (bForward)
			uPosition += uMoveBy;
		else
			uPosition -= uMoveBy;
		m_storage.Seek(uPosition);
		m_storage.m_pFile->Write(buf, uSizeRead);
		if (bForward)
			uEndOffset -= uSizeRead;
		else
			uStartOffset += uSizeRead;
		if (pCallback && !pCallback->RequestCallback(uSizeRead))
		{
			bAborted = true;
			break;			
		}
	}
	while (!bBreak);

	if (pCallback)
	{
		if (!bAborted && bLastCall && !pCallback->RequestLastCallback())
			bAborted = true;
		// do not call here - it will be called in the calling method
		//pCallback->CallbackEnd();
		if (bAborted)
		{
			// call here before throwing the the aborted exception
			pCallback->CallbackEnd();
			ThrowError(CZipException::abortedAction);
		}
	}
	
	if (uEndOffset != uStartOffset)
		ThrowError(CZipException::internalError);
	
}
ZipArchive.cpp3025
BOOL CZIPARCHIVE:RemoveCentralDirectoryFromArchive()
bool  CZipArchive::RemoveCentralDirectoryFromArchive()
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}

	if (m_storage.IsSegmented())
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot remove the central directory from a segmented archive.\n");
		return false;
	}
	m_centralDir.RemoveFromDisk();
	return true;
}
ZipArchive.cpp3093
BOOL CZIPARCHIVE:OverwriteLocalHeader(ZIP_INDEX_TYPE uIndex)
bool  CZipArchive::OverwriteLocalHeader(ZIP_INDEX_TYPE uIndex)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}

	if (m_storage.IsSegmented())
	{
		ZIPTRACE("%s(%i) : ZipArchive Library cannot overwrite local header in a segmented archive.\n");
		return false;
	}	
	
	CZipFileHeader* pHeader = GetFileInfo(uIndex);
	m_storage.Seek(pHeader->m_uOffset);
	pHeader->WriteLocal(&m_storage);
	return true;
}
ZipArchive.cpp3110
BOOL CZIPARCHIVE:ReadLocalHeader(ZIP_INDEX_TYPE uIndex)
bool  CZipArchive::ReadLocalHeader(ZIP_INDEX_TYPE uIndex)
{
	if (IsClosed())
	{
		ZIPTRACE("%s(%i) : ZipArchive is closed.\n");
		return false;
	}
	if (m_iFileOpened)
	{
		ZIPTRACE("%s(%i) : A file is already opened.\n");
		return false;
	}
	ReadLocalHeaderInternal(uIndex);
	return true;
}
ZipArchive.cpp3130
VOID CZIPARCHIVE:SetSegmCallback(CZipSegmCallback* pCallback, int callbackType)
void  CZipArchive::SetSegmCallback(CZipSegmCallback* pCallback, int callbackType)
{
	if ((callbackType & scSpan) != 0)
		m_storage.m_pSpanChangeVolumeFunc = pCallback;
	if ((callbackType & scSplit) != 0)
		m_storage.m_pSplitChangeVolumeFunc = pCallback;
}
ZipArchive.cpp3146
ZipAutoBuffer.cpp
TypeFunctionSourceLine
CZIPAUTOBUFFER:CZipAutoBuffer()
CZipAutoBuffer::CZipAutoBuffer()
{
	m_iSize = 0;
	m_pBuffer = NULL;	
}
ZipAutoBuffer.cpp19
CZIPAUTOBUFFER::CZIPAUTOBUFFER(DWORDiSize, bool bZeroMemory)
CZipAutoBuffer::CZipAutoBuffer(DWORD iSize, bool bZeroMemory)
{
	m_iSize = 0;
	m_pBuffer = NULL;
	Allocate(iSize, bZeroMemory);
}
ZipAutoBuffer.cpp25
CZIPAUTOBUFFER::CZipAutoBuffer()
CZipAutoBuffer::~CZipAutoBuffer()
{
	Release();
}
ZipAutoBuffer.cpp32
VOID CZIPAUTOBUFFER:Release()
void CZipAutoBuffer::Release()
{
	if (m_pBuffer)
	{
		delete [] m_pBuffer;
		m_iSize = 0;
		m_pBuffer = NULL;
	}
}
ZipAutoBuffer.cpp38
CHAR* CZIPAUTOBUFFER:Allocate(DWORD iSize, bool bZeroMemory)
char* CZipAutoBuffer::Allocate(DWORD iSize, bool bZeroMemory)
{
	if (iSize != m_iSize)
		Release();
	else
	{
		if (bZeroMemory)
			memset(m_pBuffer, 0, iSize); // zerowanie bufora
		return m_pBuffer;
	}

	if (iSize > 0)
	{
			m_pBuffer = new char [iSize];
			if (bZeroMemory)
				memset(m_pBuffer, 0, iSize); // zerowanie bufora
			m_iSize = iSize;
	}
	else 
		m_pBuffer = NULL;

	return m_pBuffer;
}
ZipAutoBuffer.cpp48
CZIPAUTOBUFFER::CZIPAUTOBUFFER(CONSTCZipAutoBuffer& buffer)
CZipAutoBuffer::CZipAutoBuffer(const CZipAutoBuffer& buffer)
{
	m_pBuffer = NULL;
	m_iSize = 0;

	if (buffer.m_pBuffer)
	{
		Allocate(buffer.m_iSize);
		memcpy(m_pBuffer, buffer.m_pBuffer, buffer.m_iSize);
	}	
}
ZipAutoBuffer.cpp73
CZIPAUTOBUFFER& CZIPAUTOBUFFER::OPERATOR(const CZipAutoBuffer& buffer)
CZipAutoBuffer& CZipAutoBuffer::operator=(const CZipAutoBuffer& buffer)
{
	if (this == &buffer)
		return *this;
	Release();
	if (buffer.m_pBuffer)
	{
		Allocate(buffer.m_iSize);
		memcpy(m_pBuffer, buffer.m_pBuffer, buffer.m_iSize);
	}
	return *this;
}
ZipAutoBuffer.cpp84
ZipCentralDir.cpp
TypeFunctionSourceLine
CZIPCENTRALDIR:CZipCentralDir()
CZipCentralDir::CZipCentralDir()
{
	m_pInfo = NULL;
	m_pHeaders = NULL;
	m_pFindArray = NULL;
	m_pStorage = NULL;
	m_pOpenedFile = NULL;
	m_iIgnoredChecks = 0;
	m_pCallbacks = NULL;
}
ZipCentralDir.cpp35
VOID CZIPCENTRALDIR:Init(CZipStorage* pStorage, ZipArchiveLib::CZipCallbackProvider* pCallbacks, CZipStringStoreSettings* pStringSettings, CZipCentralDir* pSource)
void CZipCentralDir::Init(CZipStorage* pStorage, ZipArchiveLib::CZipCallbackProvider* pCallbacks, CZipStringStoreSettings* pStringSettings, CZipCentralDir* pSource)
{	
	m_pStorage = pStorage;
	m_pCallbacks = pCallbacks;
	m_pStringSettings = pStringSettings;
	m_pOpenedFile = NULL;	
	m_iIgnoredChecks = CZipArchive::checkIgnoredByDefault;
	// just in case
	DestroySharedData();
	if (pSource != NULL)
	{	
#ifdef ZIP_ARCHIVE_USE_LOCKING
		pSource->LockAccess();
#endif
		m_pInfo = pSource->m_pInfo;
		m_pInfo->m_iReference++;
		m_pHeaders = pSource->m_pHeaders;
		m_pFindArray = pSource->m_pFindArray;				
#ifdef ZIP_ARCHIVE_USE_LOCKING
		// points to the same object now
		UnlockAccess();
#endif

		m_pStorage->UpdateSegmMode(m_pInfo->m_uLastVolume);
		m_pStorage->m_uBytesBeforeZip = pSource->m_pStorage->m_uBytesBeforeZip;
		
	}
	else
		CreateSharedData();
}
ZipCentralDir.cpp46
CZIPCENTRALDIR::CZipCentralDir()
CZipCentralDir::~CZipCentralDir()
{
	DestroySharedData();
}
ZipCentralDir.cpp77
VOID CZIPCENTRALDIR:Read(bool bExhaustiveRead)
void CZipCentralDir::Read(bool bExhaustiveRead)
{
	if (!m_pStorage)
	{
		ASSERT(FALSE);
		return;
	}
	m_pStorage->m_pFile->SeekToEnd();
	
	// maximum size of end of central dir record	
	m_pInfo->m_uEndOffset = (ZIP_SIZE_TYPE)m_pStorage->LocateSignature(m_gszSignature, 0xFFFF + CENTRAL_DIR_END_SIZE);	
	
	if (m_pInfo->m_uEndOffset == CZipStorage::SignatureNotFound)	
		ThrowError(CZipException::cdirNotFound);
		
	m_pStorage->m_pFile->Seek((ZIP_FILE_USIZE)(m_pInfo->m_uEndOffset + 4));
	CZipAutoBuffer buf(CENTRAL_DIR_END_SIZE);

	// we can skip the signature, we already know it is good - it was found 
	int uRead = m_pStorage->m_pFile->Read(buf, CENTRAL_DIR_END_SIZE - 4);
	if (uRead != CENTRAL_DIR_END_SIZE - 4)
		ThrowError(CZipException::badZipFile);	

	WORD uCommentSize;
	CBytesWriter::ReadBytes(m_pInfo->m_uLastVolume,		buf, 2);
	CBytesWriter::ReadBytes(m_pInfo->m_uVolumeWithCD,	buf + 2, 2);
	CBytesWriter::ReadBytes(m_pInfo->m_uVolumeEntriesNo,buf + 4, 2);
	CBytesWriter::ReadBytes(m_pInfo->m_uEntriesNumber,buf + 6, 2);
	CBytesWriter::ReadBytes(m_pInfo->m_uSize,			buf + 8, 4);
	CBytesWriter::ReadBytes(m_pInfo->m_uOffset,		buf + 12, 4);
	CBytesWriter::ReadBytes(uCommentSize,			buf + 16);
	buf.Release();		

	if (uCommentSize)
	{
		m_pInfo->m_pszComment.Allocate(uCommentSize);
		uRead = m_pStorage->m_pFile->Read(m_pInfo->m_pszComment, uCommentSize);
		if (uRead != uCommentSize)
			ThrowError(CZipException::badZipFile);
	}

	if ( m_pInfo->NeedsZip64() )
	{
		m_pStorage->m_pFile->Seek((ZIP_FILE_USIZE)(m_pInfo->m_uEndOffset));
		ULONGLONG uPosition = m_pStorage->LocateSignature(m_gszSignature64Locator, ZIP_SIZE_TYPE(-1));				
		if (uPosition != CZipStorage::SignatureNotFound)
			ThrowError(CZipException::noZip64);
		// when the zip64 locator is not found, try to treat this archive as normal
	}
	
	// if m_uLastVolume is not zero, it is enough to say that it is a multi-volume archive
	ASSERT((!m_pInfo->m_uLastVolume && (m_pInfo->m_uEntriesNumber == m_pInfo->m_uVolumeEntriesNo) && !m_pInfo->m_uVolumeWithCD) || m_pInfo->m_uLastVolume);

		m_pStorage->UpdateSegmMode(m_pInfo->m_uLastVolume);

	if (!m_pStorage->IsSegmented() && !m_pInfo->CheckIfOK_1())
		ThrowError(CZipException::badZipFile);

	if (m_pStorage->m_uBytesBeforeZip == 0 && m_pInfo->m_uLastVolume == 0)
		m_pStorage->m_uBytesBeforeZip = m_pInfo->CalculateBytesBeforeZip();

	if (!m_pInfo->CheckIfOK_2())
		ThrowError(CZipException::badZipFile);

	m_pInfo->m_bInArchive = true;
	m_pStorage->ChangeVolume(m_pInfo->m_uVolumeWithCD);

	if (!m_pInfo->m_uSize)
		return;

	ReadHeaders(bExhaustiveRead);
}


void CZipCentralDir::ThrowError(int err) const
{
	CZipException::Throw(err, m_pStorage->m_pFile->GetFilePath());
}
ZipCentralDir.cpp82
VOID CZIPCENTRALDIR:ReadHeaders(bool bExhaustiveRead)
void CZipCentralDir::ReadHeaders(bool bExhaustiveRead)
{
	m_pStorage->Seek(m_pInfo->m_uOffset);
	RemoveHeaders(); //just in case
	for (ZIP_INDEX_TYPE i = 0; i < m_pInfo->m_uEntriesNumber; i++)
	{
		CZipFileHeader* pHeader = new CZipFileHeader;
		m_pHeaders->Add(pHeader);

		if (!pHeader->Read(*this, true))
			ThrowError(CZipException::badZipFile);
	}

	if (bExhaustiveRead)
		{
			ZIP_FILE_USIZE uPosition = m_pStorage->m_pFile->GetPosition();
			// different offset, or different parts
			if (uPosition != m_pInfo->m_uEndOffset || m_pStorage->IsSegmented() && m_pStorage->GetCurrentVolume() != m_pInfo->m_uLastVolume)
				for(;;)
				{
					CZipAutoBuffer buf(4);
					m_pStorage->Read(buf, 4, true);
					if (!CZipFileHeader::VerifySignature(buf))
						break;
					CZipFileHeader* pHeader = new CZipFileHeader;
					m_pHeaders->Add(pHeader);
					if (!pHeader->Read(*this, false))
						ThrowError(CZipException::badZipFile);			
				}
		}
	
	// this is necessary when removing data descriptors, CZipArchive::MakeSpaceForReplace, deleting, replacing or encrypting files
	// sort always, to yield the same results in requesting files by index regardless of the reason for opening
	m_pHeaders->Sort(CompareHeaders); 
	RebuildFindFastArray();
}
ZipCentralDir.cpp162
VOID CZIPCENTRALDIR:Close()
void CZipCentralDir::Close()
{
	m_pOpenedFile = NULL;
	DestroySharedData();
	// do not reference it anymore
	m_pInfo = NULL;
	m_pHeaders = NULL;
	m_pFindArray = NULL;
}

bool CZipCentralDir::IsValidIndex(ZIP_INDEX_TYPE uIndex)const
{
	return uIndex < (ZIP_INDEX_TYPE)m_pHeaders->GetSize() && uIndex != ZIP_FILE_INDEX_UNSPECIFIED;
}
ZipCentralDir.cpp199
VOID CZIPCENTRALDIR:OpenFile(ZIP_INDEX_TYPE uIndex)
void CZipCentralDir::OpenFile(ZIP_INDEX_TYPE uIndex)
{
	CZipFileHeader* pOpenedFile = (*this)[uIndex];
	m_pStorage->ChangeVolume(pOpenedFile->m_uVolumeStart);
	m_pStorage->Seek(pOpenedFile->m_uOffset);
	if (!pOpenedFile->ReadLocal(*this))
		ThrowError(CZipException::badZipFile);
	m_pOpenedFile = pOpenedFile;
}
ZipCentralDir.cpp214
VOID CZIPCENTRALDIR:CloseFile(bool skipCheckingDataDescriptor)
void CZipCentralDir::CloseFile(bool skipCheckingDataDescriptor)
{
	if (!m_pOpenedFile)
		return;
	if (!skipCheckingDataDescriptor && IsConsistencyCheckOn(CZipArchive::checkDataDescriptor)
		&& !m_pOpenedFile->CheckDataDescriptor(m_pStorage))
		ThrowError(CZipException::badZipFile);
	m_pOpenedFile = NULL;
}
ZipCentralDir.cpp225
CZIPFILEHEADER* CZIPCENTRALDIR:AddNewFile(const CZipFileHeader & header, ZIP_INDEX_TYPE uReplaceIndex, int iLevel, bool bRichHeaderTemplateCopy)
CZipFileHeader* CZipCentralDir::AddNewFile(const CZipFileHeader & header, ZIP_INDEX_TYPE uReplaceIndex, int iLevel, bool bRichHeaderTemplateCopy)
{
	// copy some of the template data
	m_pOpenedFile = NULL;
	ZIP_INDEX_TYPE uIndex;
	CZipFileHeader* pHeader = new CZipFileHeader();	
	try
	{
		pHeader->m_uMethod = header.m_uMethod;
		pHeader->m_uModDate = header.m_uModDate;
		pHeader->m_uModTime = header.m_uModTime;


		pHeader->m_uExternalAttr = header.m_uExternalAttr;
		pHeader->m_uLocalComprSize = header.m_uLocalComprSize;
		pHeader->m_uLocalUncomprSize = header.m_uLocalUncomprSize;
		if (header.m_pszFileName != NULL)
			pHeader->m_pszFileName = new CZipString(*header.m_pszFileName);

		pHeader->m_pszFileNameBuffer = header.m_pszFileNameBuffer;
		pHeader->m_pszComment = header.m_pszComment;
		pHeader->m_aLocalExtraData = header.m_aLocalExtraData;
		// local will be removed in a moment in PrepareData
		pHeader->m_aCentralExtraData = header.m_aCentralExtraData;
		pHeader->m_aCentralExtraData.RemoveInternalHeaders();	
		pHeader->SetSystemCompatibility(header.GetSystemCompatibility());
		pHeader->m_uEncryptionMethod = header.m_uEncryptionMethod;

		// current settings
		pHeader->m_stringSettings = *m_pStringSettings;

		// set only when adding a new file, not in PrepareData (which may be called under different circumstances)
		// we need the proper encryption method to be set already
		RemoveFromDisk();
		
		bool bReplace = IsValidIndex(uReplaceIndex);
			
		pHeader->PrepareData(iLevel, m_pStorage->IsSegmented() != 0);
		
		if (bRichHeaderTemplateCopy)
		{
			// call here, because PrepareData will zero them
			pHeader->m_uCrc32 = header.m_uCrc32;
			pHeader->m_uComprSize = header.m_uComprSize;
			pHeader->m_uUncomprSize = header.m_uUncomprSize;
		}
		// local extra field is updated if needed, so we can check the lengths
		if (!pHeader->CheckLengths(true))
			ThrowError(CZipException::tooLongData);

		// now that everything is all right, we can add the new file		
		if (bReplace)
		{
			CZipFileHeader* pfh = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)uReplaceIndex];
			m_pStorage->Seek(pfh->m_uOffset);
			RemoveFile(pfh, uReplaceIndex, false);
			m_pHeaders->InsertAt((ZIP_ARRAY_SIZE_TYPE)uReplaceIndex, pHeader);
			m_pOpenedFile = pHeader;				
			uIndex = uReplaceIndex;		
		}
		else
		{
			uIndex = (ZIP_INDEX_TYPE)m_pHeaders->Add(pHeader);
			m_pOpenedFile = pHeader;
			m_pStorage->m_pFile->SeekToEnd();
		}
	}
	catch(...)
	{
		// otherwise it is added to the collection and will be auto-deleted
		if (pHeader != NULL && m_pOpenedFile == NULL)
			delete pHeader;
		throw;
	}

	if (m_pInfo->m_bFindFastEnabled)
		InsertFindFastElement(pHeader, uIndex); // GetCount > 0, because we have just added a header

	return pHeader;
}
ZipCentralDir.cpp235
VOID CZIPCENTRALDIR:SetComment(LPCTSTR lpszComment)
void CZipCentralDir::SetComment(LPCTSTR lpszComment)
{
	ZipCompatibility::ConvertStringToBuffer(lpszComment, m_pInfo->m_pszComment, m_pStringSettings->m_uCommentCodePage);
	RemoveFromDisk();
}
ZipCentralDir.cpp317
BOOL CZIPCENTRALDIR:SetFileComment(ZIP_INDEX_TYPE uIndex, LPCTSTR lpszComment)
bool CZipCentralDir::SetFileComment(ZIP_INDEX_TYPE uIndex, LPCTSTR lpszComment)
{
	if (!IsValidIndex(uIndex))
	{
		ASSERT(FALSE);
		return false;
	}
	CZipFileHeader* pHeader = (*this)[uIndex];
	pHeader->m_stringSettings.m_uCommentCodePage = m_pStringSettings->m_uCommentCodePage;
	pHeader->SetComment(lpszComment);
	RemoveFromDisk();
	return true;
}
ZipCentralDir.cpp323
VOID CZIPCENTRALDIR:RemoveFromDisk()
void CZipCentralDir::RemoveFromDisk()
{
	if (m_pInfo->m_bInArchive)
	{
		ASSERT(!m_pStorage->IsSegmented()); // you can't add files to an existing segmented archive or to delete them from it
		m_pStorage->m_pFile->SetLength((ZIP_FILE_USIZE)(m_pStorage->m_uBytesBeforeZip + m_pInfo->m_uOffset));
		m_pInfo->m_bInArchive = false;
	}
	else
		m_pStorage->Flush(); // if remove from disk is requested, then the archive modification will follow, so flush the buffers
}
ZipCentralDir.cpp337
VOID CZIPCENTRALDIR:CloseNewFile()
void CZipCentralDir::CloseNewFile()
{
	m_pOpenedFile->OnNewFileClose(m_pStorage);
	m_pOpenedFile = NULL;
}
ZipCentralDir.cpp350
VOID CZIPCENTRALDIR:Write()
void CZipCentralDir::Write()
{
	if (m_pInfo->m_bInArchive)
		return;

	m_pInfo->m_uEntriesNumber = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();	

	if (!m_pStorage->IsSegmented())
	{
		m_pStorage->Flush();
		m_pStorage->m_pFile->SeekToEnd();
	}
// 	else
// 		we are at the end already

	m_pInfo->m_uSize = 0;
	bool bDontAllowVolumeChange = false;
	
	if (m_pStorage->IsSegmented())
	{
		// segmentation signature at the beginning (4 bytes) + the size of the data descr. for each file
		ZIP_SIZE_TYPE uSize = GetSize(true);
		// if there is a segmented archive in creation and it is only one-volume,
		//	(current volume number is 0 so far, no bytes has been written so we know they are 
		//  all in the buffer)	make sure that it will be after writing central dir 
		// and make it a not segmented archive
		if (m_pStorage->GetCurrentVolume() == 0)
		{
			// calculate the size of data descriptors already in the buffer or on the disk
			// (they will be removed in the not segmented archive).
			ZIP_SIZE_TYPE uToGrow = uSize - 4;
			for (ZIP_INDEX_TYPE i = 0; i < m_pInfo->m_uEntriesNumber; i++)
			{
				CZipFileHeader* pHeader = (*this)[i];
				if (pHeader->NeedsDataDescriptor())
				{
					if (!pHeader->IsEncrypted())
						uToGrow -= 4; // remove the signature only
				}
				else
					uToGrow -= pHeader->GetDataDescriptorSize(true);
			}

			ZIP_SIZE_TYPE uVolumeFree = m_pStorage->VolumeLeft();
			
			if (uVolumeFree >= uToGrow) 
			// lets make sure it will be one-volume archive
			{
				// can the operation be done only in the buffer?
				if (!m_pStorage->m_uBytesWritten && // no bytes on the disk yet
					(m_pStorage->GetFreeInBuffer() >= uToGrow)) // is the buffer big enough?
				{
						RemoveDataDescr(true);
						bDontAllowVolumeChange = true; // if a volume change occurs somehow, we'll throw an error later
				}
				else
				{
					m_pStorage->Flush();
					if (RemoveDataDescr(false))
						bDontAllowVolumeChange = true; // if a volume change occurs somehow, we'll throw an error later
				}
			}
		}

		// make sure that in a segmented archive, the whole central directory will fit on the single volume
		if (!bDontAllowVolumeChange)
			m_pStorage->AssureFree(uSize);
	}

	try
	{
		WriteHeaders(bDontAllowVolumeChange || !m_pStorage->IsSegmented());
				
		WriteCentralEnd();

		if (bDontAllowVolumeChange)
		{
			if (m_pStorage->GetCurrentVolume() != 0)
				ThrowError(CZipException::badZipFile);
		}		
	}
	catch (...)
	{
		if (bDontAllowVolumeChange)
		{
			m_pStorage->FinalizeSegm();
			m_pInfo->m_uLastVolume = 0;
		}
		throw;
	}
	m_pInfo->m_bInArchive = true;
}
ZipCentralDir.cpp356
VOID CZIPCENTRALDIR:WriteHeaders(bool bOneDisk)
void CZipCentralDir::WriteHeaders(bool bOneDisk)
{
	CZipActionCallback* pCallback = m_pCallbacks->Get(CZipActionCallback::cbSave);
	m_pInfo->m_uVolumeEntriesNo = 0;
	m_pInfo->m_uVolumeWithCD = m_pStorage->GetCurrentVolume();
	
	m_pInfo->m_uOffset = m_pStorage->GetPosition();
	if (!m_pInfo->m_uEntriesNumber)
		return;

	ZIP_VOLUME_TYPE uDisk = m_pInfo->m_uVolumeWithCD;

	if (pCallback)
	{
		pCallback->Init();
		pCallback->SetTotal(m_pInfo->m_uEntriesNumber);
	}

	int iAborted = 0;
	if (m_pInfo->m_uEntriesNumber > 0)
	{
		ZIP_INDEX_TYPE uLast = (ZIP_INDEX_TYPE)(m_pInfo->m_uEntriesNumber - 1);
		ZIP_INDEX_TYPE i = 0;
		for (;;)
		{
			CZipFileHeader* pHeader = (*this)[i];
			
			m_pInfo->m_uSize += pHeader->Write(m_pStorage);

			if (m_pStorage->GetCurrentVolume() != uDisk)
			{
				m_pInfo->m_uVolumeEntriesNo = 1;
				uDisk = m_pStorage->GetCurrentVolume();
				// update the information about the offset and starting volume if the 
				// first header was written in the new volume
				if (i == 0)
				{
					m_pInfo->m_uOffset = 0;
					m_pInfo->m_uVolumeWithCD = uDisk;
				}
			}
			else 
				m_pInfo->m_uVolumeEntriesNo++;

			if (pCallback)
			{
				bool ret, last;
				if (i == uLast)
				{
					ret = pCallback->RequestLastCallback(1);
					last = true;
				}
				else
				{
					ret = pCallback->RequestCallback();
					last = false;
				}

				if (ret)
				{
					if (last)
						break;
				}
				else
				{
					if (bOneDisk) 
					{						
						ASSERT(!m_pStorage->IsSegmented());
						// if segmented, would need to m_pStorage->Flush(), but the headers can span multiple volumes
						m_pStorage->EmptyWriteBuffer();						
						// remove saved part from the volume
						m_pStorage->m_pFile->SetLength((ZIP_FILE_USIZE)(m_pStorage->m_uBytesBeforeZip + m_pInfo->m_uOffset));
	//	 				We can now abort safely
						iAborted = CZipException::abortedSafely;
					}
					else
						iAborted = CZipException::abortedAction;
					break;
				}
			}
			else if (i == uLast)
				break;

			i++;
		}
	}

	if (pCallback)
	{
		pCallback->CallbackEnd();
		if (iAborted)
			ThrowError(iAborted);
	}
}
ZipCentralDir.cpp449
VOID CZIPCENTRALDIR:WriteCentralEnd()
void CZipCentralDir::WriteCentralEnd()
{
	ZIP_SIZE_TYPE uSize = CENTRAL_DIR_END_SIZE + m_pInfo->m_pszComment.GetSize();

	CZipAutoBuffer buf((DWORD)uSize);
	char* pBuf = buf;
	ZIP_VOLUME_TYPE uDisk = m_pStorage->GetCurrentVolume();
	if (m_pStorage->IsSegmented() != 0)
	{
		// update the volume number
		m_pStorage->AssureFree(uSize);
		m_pInfo->m_uLastVolume = m_pStorage->GetCurrentVolume();
	}
	if (m_pInfo->m_uLastVolume != uDisk)
		m_pInfo->m_uVolumeEntriesNo = 0;


	WORD uCommentSize = (WORD)m_pInfo->m_pszComment.GetSize();
	memcpy(pBuf, m_gszSignature, 4);
	CBytesWriter::WriteBytes(pBuf + 4,  CBytesWriter::WriteSafeU16(m_pInfo->m_uLastVolume));
	CBytesWriter::WriteBytes(pBuf + 6,  CBytesWriter::WriteSafeU16(m_pInfo->m_uVolumeWithCD));
	CBytesWriter::WriteBytes(pBuf + 8,  CBytesWriter::WriteSafeU16(m_pInfo->m_uVolumeEntriesNo));
	CBytesWriter::WriteBytes(pBuf + 10, CBytesWriter::WriteSafeU16(m_pInfo->m_uEntriesNumber));
	CBytesWriter::WriteBytes(pBuf + 12, CBytesWriter::WriteSafeU32(m_pInfo->m_uSize));
	CBytesWriter::WriteBytes(pBuf + 16, CBytesWriter::WriteSafeU32(m_pInfo->m_uOffset));
	CBytesWriter::WriteBytes(pBuf + 20, uCommentSize);
	memcpy(pBuf + 22, m_pInfo->m_pszComment, uCommentSize);
	if (uSize > (DWORD)(-1))
		CZipException::Throw(CZipException::internalError);
	m_pStorage->Write(buf, (DWORD)uSize, true);
}
ZipCentralDir.cpp545
VOID CZIPCENTRALDIR:RemoveAll()
void CZipCentralDir::RemoveAll()
{
	ClearFindFastArray();
	RemoveHeaders();
}
ZipCentralDir.cpp577
VOID CZIPCENTRALDIR:RemoveFile(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex, bool bShift)
void CZipCentralDir::RemoveFile(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex, bool bShift)
{
	if (uIndex == ZIP_FILE_INDEX_UNSPECIFIED)
	{
		// we need to know the index to remove
		ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();
		for (ZIP_INDEX_TYPE i = 0; i < uCount; i++)
			if (pHeader == (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)i])
			{
				uIndex = i;
				break;
			}
	}
	ASSERT(uIndex != ZIP_FILE_INDEX_UNSPECIFIED || pHeader);
	if (!pHeader)
		pHeader = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)uIndex];

	if (m_pInfo->m_bFindFastEnabled)
	{
		ZIP_INDEX_TYPE i = FindFileNameIndex(pHeader->GetFileName());
		ASSERT(i != ZIP_FILE_INDEX_NOT_FOUND);
		CZipFindFast* pFindFast = (*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)i];
		ZIP_INDEX_TYPE uBorderIndex = pFindFast->m_uIndex;
		delete pFindFast;
		pFindFast = NULL;
		m_pFindArray->RemoveAt((ZIP_ARRAY_SIZE_TYPE)i);
		// shift down the indexes
		
		if (bShift)
		{
			ZIP_INDEX_TYPE uSize = (ZIP_INDEX_TYPE)m_pFindArray->GetSize();
			for (ZIP_INDEX_TYPE j = 0; j < uSize; j++)
			{
				if ((*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)j]->m_uIndex > uBorderIndex)
					(*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)j]->m_uIndex--;
			}
		}
	}

	if (uIndex != ZIP_FILE_INDEX_UNSPECIFIED)
	{
		delete pHeader;
		m_pHeaders->RemoveAt((ZIP_ARRAY_SIZE_TYPE)uIndex);
	}
}
ZipCentralDir.cpp584
VOID CZIPCENTRALDIR:RemoveLastFile(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex)
void CZipCentralDir::RemoveLastFile(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex)
{
	if (uIndex == ZIP_FILE_INDEX_UNSPECIFIED)
	{
		if (m_pHeaders->GetSize() == 0)
			return;			
		uIndex = (ZIP_VOLUME_TYPE)(m_pHeaders->GetSize() - 1);
	}
	if (!pHeader)
		pHeader = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)uIndex];
	ZIP_SIZE_TYPE uNewSize = pHeader->m_uOffset + m_pStorage->m_uBytesBeforeZip;
	// then remove
	RemoveFile(pHeader, uIndex);

	m_pStorage->Flush();
	m_pStorage->m_pFile->SetLength((ZIP_FILE_USIZE)uNewSize);
	m_pInfo->m_bInArchive = false; // it is true when AutoFlush is set to true
}


ZIP_SIZE_TYPE CZipCentralDir::GetSize(bool bWhole) const
{
	ZIP_SIZE_TYPE uTotal = CENTRAL_DIR_END_SIZE + m_pInfo->m_pszComment.GetSize();
	ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();
	if (bWhole)
	{
		for (ZIP_INDEX_TYPE i = 0; i < uCount; i++)
		{
			const CZipFileHeader* pHeader = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)i];
			uTotal += pHeader->GetSize();
		}
	}


	return uTotal;
}
ZipCentralDir.cpp631
BOOL CZIPCENTRALDIR:RemoveDataDescr(bool bFromBuffer)
bool CZipCentralDir::RemoveDataDescr(bool bFromBuffer)
{
	// this will not work if there are bytes before zip
	CZipFileMapping fm;
	char* pFile;
	ZIP_SIZE_TYPE uSize;
	if (bFromBuffer)
	{
		uSize = m_pStorage->m_uBytesInWriteBuffer;
		pFile = m_pStorage->m_pWriteBuffer;
	}
	else
	{
		uSize = (ZIP_SIZE_TYPE)m_pStorage->m_pFile->GetLength();
		// we cannot use CZipMemFile in multi-volume archive
		// so it must be CZipFile
		if (!fm.CreateMapping(static_cast(m_pStorage->m_pFile)))
			return false;
		pFile = fm.GetMappedMemory();
	}

	ZIP_SIZE_TYPE uOffsetToChange = 4;
	ZIP_SIZE_TYPE uPosInBuffer = 0;
	WORD uExtraHeaderLen;
	ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();
	for (ZIP_INDEX_TYPE i = 0; i < uCount; i++)
	{
		CZipFileHeader* pHeader = (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)i];
		char* pSour = pFile + pHeader->m_uOffset;

		if (pHeader->NeedsDataDescriptor())
			uExtraHeaderLen = (WORD)(pHeader->IsEncrypted() ? 0 : 4);
		else
		{
			uExtraHeaderLen = pHeader->GetDataDescriptorSize(true);
			// removing data descriptor
			pHeader->m_uFlag &= ~8;
			// update local header:
			// write modified flag in the local header
			CBytesWriter::WriteBytes(pSour + 6, pHeader->m_uFlag);			
			pHeader->WriteSmallDataDescriptor(pSour + 14, false);
		}

		ZIP_SIZE_TYPE uToCopy = (i == (uCount - 1) ? uSize : (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)(i + 1)]->m_uOffset)
			- pHeader->m_uOffset - uExtraHeaderLen;
		if (uToCopy > 0)
			// TODO: [postponed] the size_t limit on uToCopy, but creating such a big segment is unlikely (at least at the moment of writing)
			memmove(pFile + uPosInBuffer, pSour, (size_t)uToCopy);

		uPosInBuffer += uToCopy;
		pHeader->m_uOffset -= uOffsetToChange;
		uOffsetToChange += uExtraHeaderLen;
	}

	if (bFromBuffer)
		m_pStorage->m_uBytesInWriteBuffer = (DWORD)uPosInBuffer;
	else
	{
		m_pStorage->m_uBytesWritten = uPosInBuffer;
		fm.RemoveMapping();
		m_pStorage->m_pFile->SetLength((ZIP_FILE_USIZE)uPosInBuffer);
	}
	return true;
}
ZipCentralDir.cpp668
VOID CZIPCENTRALDIR:RemoveHeaders()
void CZipCentralDir::RemoveHeaders()
{
	ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();
	for (ZIP_INDEX_TYPE i = 0; i < uCount; i++)
		delete (*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)i];
	m_pHeaders->RemoveAll();
}
ZipCentralDir.cpp733
VOID CZIPCENTRALDIR:BuildFindFastArray( bool bCaseSensitive )
void CZipCentralDir::BuildFindFastArray( bool bCaseSensitive )
{
	ClearFindFastArray();
	m_pInfo->m_bCaseSensitive = bCaseSensitive;
	// for later
	m_pInfo->m_pCompare = GetCZipStrCompFunc(bCaseSensitive);
	ZIP_INDEX_TYPE uCount = (ZIP_INDEX_TYPE)m_pHeaders->GetSize();

	for (ZIP_INDEX_TYPE i = 0; i < uCount; i++)
		m_pFindArray->Add(new CZipFindFast((*m_pHeaders)[(ZIP_ARRAY_SIZE_TYPE)i], i));
	
	m_pFindArray->Sort(bCaseSensitive ? CompareFindFastCollate : CompareFindFastCollateNoCase);
}
ZipCentralDir.cpp741
VOID CZIPCENTRALDIR:EnableFindFast(bool bEnable, bool bCaseSensitive)
void CZipCentralDir::EnableFindFast(bool bEnable, bool bCaseSensitive)
{
	if (m_pInfo->m_bFindFastEnabled == bEnable)
		return;
	m_pInfo->m_bFindFastEnabled = bEnable;
	if (bEnable)
		BuildFindFastArray(bCaseSensitive);
	else
		m_pFindArray->RemoveAll();
}
ZipCentralDir.cpp755
ZIP_INDEX_TYPE CZIPCENTRALDIR:FindFile(LPCTSTR lpszFileName, bool bCaseSensitive, bool bSporadically, bool bFileNameOnly)
ZIP_INDEX_TYPE CZipCentralDir::FindFile(LPCTSTR lpszFileName, bool bCaseSensitive, bool bSporadically, bool bFileNameOnly)
{
	if (!m_pInfo->m_bFindFastEnabled)
		EnableFindFast(true, bSporadically ? !bCaseSensitive : bCaseSensitive);
	ZIP_INDEX_TYPE uResult = ZIP_FILE_INDEX_NOT_FOUND;
	if (bFileNameOnly)
	{
		//  a non-effective search (treat an array as unsorted)

		// set the proper compare function
		ZIPSTRINGCOMPARE pCompare = bCaseSensitive == m_pInfo->m_bCaseSensitive ? m_pInfo->m_pCompare : GetCZipStrCompFunc(bCaseSensitive);
		
		ZIP_INDEX_TYPE uSize = (ZIP_INDEX_TYPE)m_pFindArray->GetSize();
		for (ZIP_INDEX_TYPE i = 0; i < uSize; i++)
		{
			CZipString sz = (*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)i]->m_pHeader->GetFileName();
			CZipPathComponent::RemoveSeparators(sz); // to find a dir
			CZipPathComponent zpc(sz);
			sz = zpc.GetFileName();
			if ((sz.*pCompare)(lpszFileName) == 0)
			{
				uResult = i;
				break;
			}
		}
	}
	else if (bCaseSensitive == m_pInfo->m_bCaseSensitive)
		uResult = FindFileNameIndex(lpszFileName);
	else
	{
		if (bSporadically)
		{
			// a non-effective search (treat an array as unsorted)
			// do not use m_pInfo->m_pCompare, as it may be shared
			ZIPSTRINGCOMPARE pCompare = GetCZipStrCompFunc(bCaseSensitive);			
			ZIP_INDEX_TYPE uSize = (ZIP_INDEX_TYPE)m_pFindArray->GetSize();
			for (ZIP_INDEX_TYPE i = 0; i < uSize; i++)
				if (((*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)i]->m_pHeader->GetFileName().*pCompare)(lpszFileName) == 0)
				{
					uResult = i;
					break;
				}
		}
		else
		{
			BuildFindFastArray(bCaseSensitive);		
			uResult = FindFileNameIndex(lpszFileName);
		}
	}
	return uResult == ZIP_FILE_INDEX_NOT_FOUND ? ZIP_FILE_INDEX_NOT_FOUND : (*m_pFindArray)[(ZIP_ARRAY_SIZE_TYPE)uResult]->m_uIndex;	
}
ZipCentralDir.cpp766
ZIP_INDEX_TYPE CZIPCENTRALDIR:InsertFindFastElement(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex)
ZIP_INDEX_TYPE CZipCentralDir::InsertFindFastElement(CZipFileHeader* pHeader, ZIP_INDEX_TYPE uIndex)
{
	CZipString fileName = pHeader->GetFileName();
	ZIP_ARRAY_SIZE_TYPE uSize = m_pFindArray->GetSize();

	//	Our initial binary search range encompasses the entire array of filenames:
	ZIP_ARRAY_SIZE_TYPE start = 0;
	ZIP_ARRAY_SIZE_TYPE end = uSize;

	//	Keep halving our search range until we find the right place
	//	to insert the new element:
	while ( start < end )
	{
		//	Find the midpoint of the search range:
		ZIP_ARRAY_SIZE_TYPE midpoint = ( start + end ) / 2;

		//	Compare the filename with the filename at the midpoint of the current search range:
		int result = CompareElement(fileName, (ZIP_INDEX_TYPE)midpoint);

		//	If our filename is larger, it must fall in the first half of the search range:
		if ( result > 0 )
		{
			end = midpoint;
		}

		//	If it's smaller, it must fall in the last half:
		else if ( result < 0 )
		{
			start = midpoint + 1;
		}

		//	If they're equal, we can go ahead and insert here:
		else
		{
			start = midpoint;
			break;
		}
	}
	m_pFindArray->InsertAt(start, new CZipFindFast(pHeader, uIndex == ZIP_FILE_INDEX_UNSPECIFIED ? (ZIP_INDEX_TYPE)uSize : uIndex /* just in case */)); 
	return (ZIP_INDEX_TYPE)start;
}

ZIP_INDEX_TYPE CZipCentralDir::FindFileNameIndex(LPCTSTR lpszFileName) const
{
	ZIP_ARRAY_SIZE_TYPE start = 0;

	ZIP_ARRAY_SIZE_TYPE end = m_pFindArray->GetSize();
	if (end == 0)
		return ZIP_FILE_INDEX_NOT_FOUND;
	else
		end--;

	//	Keep halving our search range until we find the given element:
	while ( start <= end )
	{
		//	Find the midpoint of the search range:
		ZIP_ARRAY_SIZE_TYPE midpoint = ( start + end ) / 2;

		//	Compare the given filename with the filename at the midpoint of the search range:
		int result = CompareElement(lpszFileName, (ZIP_INDEX_TYPE)midpoint);

		//	If our filename is smaller, it must fall in the first half of the search range:
		if ( result > 0 )
		{
			if (midpoint == 0)
				return ZIP_FILE_INDEX_NOT_FOUND;
			end = midpoint - 1;
		}

		//	If it's larger, it must fall in the last half:
		else if ( result < 0 )
		{
			start = midpoint + 1;
		}

		//	If they're equal, return the result:
		else
		{
			return (ZIP_INDEX_TYPE)midpoint;
		}
	}

	//	Signal failure:
	return ZIP_FILE_INDEX_NOT_FOUND;
}
ZipCentralDir.cpp818
VOID CZIPCENTRALDIR:CreateSharedData()
void CZipCentralDir::CreateSharedData()
{
	m_pInfo = new CInfo();
	m_pInfo->Init();	
	m_pHeaders = new CZipArray();
	m_pFindArray = new CZipArray();
}
ZipCentralDir.cpp905
VOID CZIPCENTRALDIR:DestroySharedData()
void CZipCentralDir::DestroySharedData()
{
	if (!m_pInfo)
		return;
#ifdef ZIP_ARCHIVE_USE_LOCKING
	LockAccess();
	try
	{
#endif
		m_pInfo->m_iReference--;
		if (m_pInfo->m_iReference <= 0) // <= is just in case instead of ==
		{

			if (m_pHeaders != NULL)
			{
				RemoveHeaders();
				delete m_pHeaders;
				m_pHeaders = NULL;
			}
			
			if (m_pFindArray != NULL)
			{
				ClearFindFastArray();
				delete m_pFindArray;
				m_pFindArray = NULL;
			}
#ifdef ZIP_ARCHIVE_USE_LOCKING				
			UnlockAccess();
#endif
			delete m_pInfo;
			m_pInfo = NULL;
		}
#ifdef ZIP_ARCHIVE_USE_LOCKING
	}
	catch(...)
	{
		UnlockAccess();
		throw;
	}
	UnlockAccess();
#endif

}
ZipCentralDir.cpp913
ZipCompatibility.cpp
TypeFunctionSourceLine
DWORD ZIPCOMPATIBILITY:ConvertToSystem(DWORD uAttr, int iFromSystem, int iToSystem)
DWORD ZipCompatibility::ConvertToSystem(DWORD uAttr, int iFromSystem, int iToSystem)
{
	if (iToSystem != iFromSystem && iFromSystem < 11 && iToSystem < 11)
	{
		conv_func p = conv_funcs[iFromSystem], q = conv_funcs[iToSystem];
		if (p && q)
			uAttr = q( p(uAttr, true), false);
	 	else
	 		CZipException::Throw(CZipException::platfNotSupp);
	}
	return uAttr; 
}
ZipCompatibility.cpp82
DWORDAttrDos(DWORD uAttr, bool )
DWORD AttrDos(DWORD uAttr, bool )
{
	return uAttr;	
}
ZipCompatibility.cpp96
DWORDAttrUnix(DWORD uAttr, bool bFrom)
DWORD AttrUnix(DWORD uAttr, bool bFrom)
{
	DWORD uNewAttr = 0;
	if (bFrom)
	{
		bool isDir = (uAttr & UNIX_DIRECTORY_ATTRIBUTE) != 0;
		if (isDir)
			uNewAttr = attDir;

		uAttr = EXTRACT_USER_PERMISSIONS (uAttr);

		// we may set archive attribute if the file hasn't got the execute permissions
		// and is not a directory
		if (!isDir && !(uAttr & UNIX_EXEC))
			uNewAttr |= attArch	;

		if (!(uAttr & UNIX_WRITE)) 
		    uNewAttr |= attROnly;

	    if (!(uAttr & UNIX_READ)) 
		    uNewAttr |= attHidd;
	}
	else
	{

		uNewAttr = 0;

		// we cannot assume that if the file hasn't the archive attribute set		
		// then it is executable and set execute permissions

		if (!(uAttr & attHidd)) 
			uNewAttr |= (CREATE_OTHER_PERMISSIONS (UNIX_READ) | CREATE_GROUP_PERMISSIONS (UNIX_READ)) |
				CREATE_USER_PERMISSIONS (UNIX_READ);
							

		if (!(uAttr & attROnly))
			uNewAttr |= (CREATE_GROUP_PERMISSIONS (UNIX_WRITE) | CREATE_USER_PERMISSIONS (UNIX_WRITE));

		if (uAttr & attDir) 
		{
			uNewAttr |= UNIX_DIRECTORY_ATTRIBUTE;
			uNewAttr |= (CREATE_OTHER_PERMISSIONS (UNIX_EXEC) | CREATE_GROUP_PERMISSIONS (UNIX_EXEC)) |
				CREATE_USER_PERMISSIONS (UNIX_EXEC);
		}
		else
			uNewAttr |= UNIX_FILE_ATTRIBUTE;

	}

	return uNewAttr;	
}
ZipCompatibility.cpp103
DWORDAttrMac(DWORD uAttr, bool )
DWORD AttrMac(DWORD uAttr, bool )
{
	return uAttr & (attDir | attROnly);
}
ZipCompatibility.cpp155
ZIPINLINE BOOL ZIPCOMPATIBILITY:IsPlatformSupported(int iCode)
ZIPINLINE bool ZipCompatibility::IsPlatformSupported(int iCode)
{
	return iCode == zcDosFat || iCode == zcUnix || iCode == zcMacintosh
		|| iCode == zcNtfs || iCode == zcOs2Hpfs;
}
ZipCompatibility.cpp160
VOID ZIPCOMPATIBILITY:ConvertBufferToString(CZipString& szString, const CZipAutoBuffer& buffer, UINT uCodePage)
void ZipCompatibility::ConvertBufferToString(CZipString& szString, const CZipAutoBuffer& buffer, UINT uCodePage)
{
#ifdef _UNICODE	
	ZipPlatform::MultiByteToWide(buffer, szString, uCodePage);
#else
	// 	iLen does not include the NULL character
	int iLen;
	if (uCodePage == CP_OEMCP)
	{
		CZipAutoBuffer buf;
		buf = buffer;
		ZipPlatform::AnsiOem(buf, false);		
		iLen = buf.GetSize();
		memcpy(szString.GetBuffer(iLen), buf.GetBuffer(), iLen);
	}
	else
	{
		iLen = buffer.GetSize();		
		memcpy(szString.GetBuffer(iLen), buffer.GetBuffer(), iLen);
	}
	szString.ReleaseBuffer(iLen);
#endif
}
ZipCompatibility.cpp167
VOID ZIPCOMPATIBILITY:ConvertStringToBuffer(LPCTSTR lpszString, CZipAutoBuffer& buffer, UINT uCodePage)
void ZipCompatibility::ConvertStringToBuffer(LPCTSTR lpszString, CZipAutoBuffer& buffer, UINT uCodePage)
{
#ifdef _UNICODE
	ZipPlatform::WideToMultiByte(lpszString, buffer, uCodePage);
#else
	int iLen = (int)strlen(lpszString);
	// 	iLen does not include the NULL character
	buffer.Allocate(iLen);
	memcpy(buffer, lpszString, (size_t)iLen);
	if (uCodePage == CP_OEMCP)
		ZipPlatform::AnsiOem(buffer, true);
#endif
}
ZipCompatibility.cpp191
VOID ZIPCOMPATIBILITY:SlashBackslashChg(CZipString& szFileName, bool bReplaceSlash)
void ZipCompatibility::SlashBackslashChg(CZipString& szFileName, bool bReplaceSlash)
{
	TCHAR t1 = _T('\\') /*backslash*/, t2 = _T('/'), c1, c2;
	if (bReplaceSlash)
	{
		c1 = t1;
		c2 = t2;
	}
	else
	{
		c1 = t2;
		c2 = t1;
	}
	szFileName.Replace(c2, c1);
}
ZipCompatibility.cpp205
ZipCompressor.cpp
TypeFunctionSourceLine
CZIPCOMPRESSOR* CZIPCOMPRESSOR:CreateCompressor(WORD uMethod, CZipStorage* pStorage)
CZipCompressor* CZipCompressor::CreateCompressor(WORD uMethod, CZipStorage* pStorage)
{
	if (uMethod == methodStore || uMethod == methodDeflate)
		return new CDeflateCompressor(pStorage);
	return NULL;
}
ZipCompressor.cpp22
VOID CZIPCOMPRESSOR:UpdateFileCrc(const void *pBuffer, DWORD uSize)
void CZipCompressor::UpdateFileCrc(const void *pBuffer, DWORD uSize)
{
	m_pFile->m_uCrc32 = zarch_crc32(m_pFile->m_uCrc32, (zarch_Bytef*)pBuffer, uSize);
}
ZipCompressor.cpp29
VOID CZIPCOMPRESSOR:UpdateCrc(const void *pBuffer, DWORD uSize)
void CZipCompressor::UpdateCrc(const void *pBuffer, DWORD uSize)
{
	m_uCrc32 = zarch_crc32(m_uCrc32, (zarch_Bytef*)pBuffer, uSize);
}
ZipCompressor.cpp34
VOID CZIPCOMPRESSOR:UpdateOptions(const COptionsMap& optionsMap)
void CZipCompressor::UpdateOptions(const COptionsMap& optionsMap)
{
	const COptions* pOptions = GetOptions();
	if (pOptions == NULL)
		return;
	const COptions* pNewOptions = optionsMap.Get(pOptions->GetType());
	if (pNewOptions != NULL)
		UpdateOptions(pNewOptions);
}
ZipCompressor.cpp39
VOID CZIPCOMPRESSOR:InitBuffer()
void CZipCompressor::InitBuffer()
{
	// This should be greated that 64k for deflate when creating offsets pairs is enabled
	// otherwise deflate will not be able to write one block in one go and will never report
	// a flushed block for low-compressable data
	const COptions* pOptions = GetOptions();
	DWORD bufferSize = 0;
	if (pOptions != NULL)
        bufferSize = pOptions->m_iBufferSize;
	if (bufferSize == 0)
		bufferSize = COptions::cDefaultBufferSize;
	m_pBuffer.Allocate(bufferSize);
}
ZipCompressor.cpp49
VOID CZIPCOMPRESSOR::COPTIONSMAP:Set(const CZipCompressor::COptions* pOptions)
void CZipCompressor::COptionsMap::Set(const CZipCompressor::COptions* pOptions)
{
	if (pOptions == NULL)
		return;
	int iType = pOptions->GetType();
	Remove(iType);
	SetAt(iType, pOptions->Clone());
}

CZipCompressor::COptions* CZipCompressor::COptionsMap::Get(int iType) const
{
	COptions* pTemp = NULL;
	if (Lookup(iType, pTemp))
		return pTemp;
	else
		return NULL;
}
ZipCompressor.cpp64
VOID CZIPCOMPRESSOR::COPTIONSMAP:Remove(int iType)
void CZipCompressor::COptionsMap::Remove(int iType)
{
	COptions* pTemp = Get(iType);
	if (pTemp != NULL)
	{
		delete pTemp;
		RemoveKey(iType);
	}	
}
ZipCompressor.cpp82
CZIPCOMPRESSOR::COPTIONSMAP::COptionsMap()
CZipCompressor::COptionsMap::~COptionsMap()
{
	COptionsMap::iterator iter = GetStartPosition();
	while (IteratorValid(iter))
	{
		COptions* pOptions = NULL;
		int iType = 0;
		GetNextAssoc(iter, iType, pOptions);
		delete pOptions;
	}
	RemoveAll();
}
ZipCompressor.cpp92
ZipCrc32Cryptograph.cpp
TypeFunctionSourceLine
BOOL CZIPCRC32CRYPTOGRAPH:InitDecode(CZipAutoBuffer& password, CZipFileHeader& currentFile, CZipStorage& storage)
bool CZipCrc32Cryptograph::InitDecode(CZipAutoBuffer& password, CZipFileHeader& currentFile, CZipStorage& storage)
{
	CryptInitKeys(password);
	CZipAutoBuffer buf(ZIPARCHIVE_ENCR_HEADER_LEN);
	storage.Read(buf, ZIPARCHIVE_ENCR_HEADER_LEN, false);
	BYTE b = 0;
	for (int i = 0; i < ZIPARCHIVE_ENCR_HEADER_LEN; i++)
	{
		b = buf[i]; // only temporary
		CryptDecode((char&)b);
	}
	// check the last byte
	return currentFile.IsDataDescriptor() ?
		(BYTE(currentFile.m_uModTime >> 8) == b) : (BYTE(currentFile.m_uCrc32 >> 24) == b);
}
ZipCrc32Cryptograph.cpp18
VOID CZIPCRC32CRYPTOGRAPH:InitEncode(CZipAutoBuffer& password, CZipFileHeader& currentFile, CZipStorage& storage)
void CZipCrc32Cryptograph::InitEncode(CZipAutoBuffer& password, CZipFileHeader& currentFile, CZipStorage& storage)
{
	CZipAutoBuffer buf(ZIPARCHIVE_ENCR_HEADER_LEN);
	// use pseudo-crc since we don't know it yet	
	CryptInitKeys(password);
	srand(UINT(time(NULL)));
	// genereate pseudo-random sequence
	char c;
	char* buffer = (char*)buf;
	for (int i = 0; i < ZIPARCHIVE_ENCR_HEADER_LEN - 2; i++)
	{
		int t1 = rand();
		c = (char)((t1 >> 6) & 0xFF);
		if (!c)
			c = (char)(t1 & 0xFF);
		CryptEncode(c);
		buffer[i] = c;

	}
	long iCrc = (long)currentFile.m_uModTime << 16;	
	c = (char)((iCrc >> 16) & 0xFF);
	CryptEncode(c);
	buffer[ZIPARCHIVE_ENCR_HEADER_LEN - 2] = c;
	c = (char)((iCrc >> 24) & 0xFF);
	CryptEncode(c);
	buffer[ZIPARCHIVE_ENCR_HEADER_LEN - 1] = c;
	storage.Write(buf, ZIPARCHIVE_ENCR_HEADER_LEN, false);
	currentFile.m_uComprSize += ZIPARCHIVE_ENCR_HEADER_LEN;
}
ZipCrc32Cryptograph.cpp34
VOID CZIPCRC32CRYPTOGRAPH:CryptInitKeys(CZipAutoBuffer& password)
void CZipCrc32Cryptograph::CryptInitKeys(CZipAutoBuffer& password)
{
	m_keys[0] = 305419896L;
	m_keys[1] = 591751049L;
	m_keys[2] = 878082192L;
	for (DWORD i = 0; i < password.GetSize(); i++)
		CryptUpdateKeys(password[i]);
}
ZipCrc32Cryptograph.cpp64
VOID CZIPCRC32CRYPTOGRAPH:CryptUpdateKeys(char c)
void CZipCrc32Cryptograph::CryptUpdateKeys(char c)
{	
	m_keys[0] = CryptCRC32(m_keys[0], c);
	m_keys[1] += m_keys[0] & 0xff;
	m_keys[1] = m_keys[1] * 134775813L + 1;
	c = char(m_keys[1] >> 24);
	m_keys[2] = CryptCRC32(m_keys[2], c);
}
ZipCrc32Cryptograph.cpp73
ZipCryptograph.cpp
TypeFunctionSourceLine
CZIPCRYPTOGRAPH* CZIPCRYPTOGRAPH:CreateCryptograph(int iEncryptionMethod)
CZipCryptograph* CZipCryptograph::CreateCryptograph(int iEncryptionMethod)
{
	if (iEncryptionMethod == encNone)
		return NULL;
		return new CZipCrc32Cryptograph();
}
ZipCryptograph.cpp20
DWORD CZIPCRYPTOGRAPH:GetEncryptedInfoSize(int iEncryptionMethod)
DWORD CZipCryptograph::GetEncryptedInfoSize(int iEncryptionMethod)
{
	if (iEncryptionMethod != encNone)
	{
		if (iEncryptionMethod == encStandard)
			return CZipCrc32Cryptograph::GetEncryptedInfoSizeBeforeData() + CZipCrc32Cryptograph::GetEncryptedInfoSizeAfterData();
	}
	return 0;
}
ZipCryptograph.cpp28
DWORD CZIPCRYPTOGRAPH:GetEncryptedInfoSizeBeforeData(int iEncryptionMethod)
DWORD CZipCryptograph::GetEncryptedInfoSizeBeforeData(int iEncryptionMethod)
{
	if (iEncryptionMethod != encNone)
	{
		if (iEncryptionMethod == encStandard)
			return CZipCrc32Cryptograph::GetEncryptedInfoSizeBeforeData();
	}
	return 0;
}
ZipCryptograph.cpp38
DWORD CZIPCRYPTOGRAPH:GetEncryptedInfoSizeAfterData(int iEncryptionMethod)
DWORD CZipCryptograph::GetEncryptedInfoSizeAfterData(int iEncryptionMethod)
{
	if (iEncryptionMethod != encNone)
	{
		if (iEncryptionMethod == encStandard)
			return CZipCrc32Cryptograph::GetEncryptedInfoSizeAfterData();
	}
	return 0;
}
ZipCryptograph.cpp49
ZipException.cpp
TypeFunctionSourceLine
CZIPEXCEPTION::~CZIPEXCEPTION()throw()
CZipException::~CZipException() throw()
{

}

// inline void CZipException::Throw(int iZipError, LPCTSTR lpszZipName)
// {
// #ifdef _MFC_VER
// 	throw new CZipException(iZipError, lpszZipName);
// #else
// 	CZipException e(iZipError, lpszZipName);
// 	throw e;
// #endif
// MSVC++: ignore "Unreachable code" warning here, it's due to 
// optimizations
// }


#ifdef ZIP_ENABLE_ERROR_DESCRIPTION

ZBOOL CZipException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
	UINT* )
ZipException.cpp38
ZBOOL CZIPEXCEPTION:GetErrorMessage(LPTSTR lpszError, UINT nMaxError, UINT* )
{
	if (!lpszError || !nMaxError)
		return FALSE;
	CZipString sz = GetErrorDescription();
	if (sz.IsEmpty())
		return FALSE;
	UINT iLen = sz.GetLength();
	if (nMaxError - 1 < iLen)
		iLen = nMaxError - 1;
	LPTSTR lpsz = sz.GetBuffer(iLen);
#if _MSC_VER >= 1400
	#ifdef _UNICODE	
		wcsncpy_s(lpszError, nMaxError, lpsz, iLen);
	#else
		strncpy_s(lpszError, nMaxError, lpsz, iLen);
	#endif
#else
	#ifdef _UNICODE	
		wcsncpy(lpszError, lpsz, iLen);
	#else
		strncpy(lpszError, lpsz, iLen);
	#endif
#endif

	lpszError[iLen] = _T('\0');
	return TRUE;
}
ZipException.cpp61
CZIPSTRING CZIPEXCEPTION:GetErrorDescription()
CZipString CZipException::GetErrorDescription()
{
	return GetInternalErrorDescription(m_iCause);
}
ZipException.cpp90
CZIPSTRING CZIPEXCEPTION:GetSystemErrorDescription()
CZipString CZipException::GetSystemErrorDescription()
{
#ifdef WIN32
	DWORD x = GetLastError();
	if (x)
	{
		LPVOID lpMsgBuf;
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,    
			          NULL, x, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
				      (LPTSTR) &lpMsgBuf, 0, NULL);
		CZipString sz = (LPCTSTR)lpMsgBuf;
		LocalFree(lpMsgBuf);
		return sz;
	}
#endif
	return GetInternalErrorDescription(errno == 0 ? genericError : errno, true);
}
ZipException.cpp96
CZIPSTRING CZIPEXCEPTION:GetInternalErrorDescription(int iCause, bool bNoLoop)
CZipString CZipException::GetInternalErrorDescription(int iCause, bool bNoLoop)
{
	CZipString sz;
	switch (iCause)
	{
		case EROFS:
			sz = _T("Read-only file system.");
			break;
		case ESPIPE:
			sz = _T("Illegal seek.");
			break;
		case ENOSPC:
			sz = _T("No space left on device.");
			break;
		case EFBIG:
			sz = _T("File too large.");
			break;
		case EMFILE:
			sz = _T("Too many open files.");
			break;
		case ENFILE:
			sz = _T("File table overflow.");
			break;
		case EINVAL:
			sz = _T("Invalid argument.");
			break;
		case EISDIR:
			sz = _T("Is a directory.");
			break;
		case ENOTDIR:
			sz = _T("Not a directory.");
			break;
		case ENODEV:
			sz = _T("No such device.");
			break;
		case EXDEV:
			sz = _T("Cross-device link.");
			break;
		case EEXIST:
			sz = _T("File exists.");
			break;
		case EFAULT:
			sz = _T("Bad address.");
			break;
		case EACCES:
			sz = _T("Permission denied.");
			break;
		case ENOMEM:
			sz = _T("Not enough space.");
			break;
		case EBADF:
			sz = _T("Bad file number.");
			break;
		case ENXIO:
			sz = _T("No such device or address.");
			break;
		case EIO:
			sz = _T("I/O error.");
			break;
		case EINTR:
			sz = _T("Interrupted system call.");
			break;
		case ENOENT:
			sz = _T("No such file or directory.");
			break;
		case EPERM:
			sz = _T("Not super-user.");
			break;
		case badZipFile:
			sz = _T("Damaged or not a zip file.");
			break;
		case badCrc:
			sz = _T("Crc is mismatched.");
			break;
		case noCallback:
			sz = _T("There is no spanned archive callback object set.");
			break;
		case aborted:
			sz = _T("Volume change aborted in a segmented archive.");
			break;
		case abortedAction:
			sz = _T("Action aborted.");
			break;
		case abortedSafely:
			sz = _T("Action aborted safely.");
			break;
		case nonRemovable:
			sz = _T("The device selected for the spanned archive is not removable.");
			break;
		case tooManyVolumes:
			sz = _T("The limit of the maximum volumes reached.");
			break;
		case tooManyFiles:
			sz = _T("The limit of the maximum files in an archive reached.");
			break;
		case tooLongData:
			sz = _T("The filename, the comment or the local or central extra field of the file added to the archive is too long.");
			break;
		case tooBigSize:
			sz = _T("The file size is too large to be supported.");
			break;
		case badPassword:
			sz = _T("An incorrect password set for the file being decrypted.");
			break;
		case dirWithSize:
			sz = _T("The directory with a non-zero size found while testing.");
			break;
		case internalError:
			sz = _T("An internal error.");
			break;
		case notRemoved:
			sz.Format(_T("%s (%s)."), _T("Error while removing a file"), (LPCTSTR)GetSystemErrorDescription());
			break;
		case notRenamed:
			sz.Format(_T("%s (%s)."), _T("Error while renaming a file"), (LPCTSTR)GetSystemErrorDescription());
			break;
		case platfNotSupp:
			sz = _T("Cannot create a file for the specified platform.");
			break;
		case cdirNotFound:
			sz = _T("The central directory was not found in the archive (or you were trying to open not the last volume of a segmented archive).");
			break;
		case noZip64:
			sz = _T("The Zip64 format has not been enabled for the library, but is required to use the archive.");
			break;
		case noAES:
			sz = _T("WinZip AES encryption has not been enabled for the library, but is required to decompress the archive.");
			break;
#ifdef ZIP_ARCHIVE_STL
			case outOfBounds:
			sz = _T("The collection is empty and the bounds do not exist.");
			break;
#endif
#ifdef ZIP_ARCHIVE_USE_LOCKING
		case mutexError:
			sz = _T("Locking or unlocking resources access was unsuccessful.");
			break;
#endif
		case streamEnd:
			sz = _T("Zlib library error (end of stream).");
			break;
		case errNo:
			sz = GetInternalErrorDescription(errno != errNo ? errno : genericError);
			break;
		case streamError:
			sz = _T("Zlib library error (stream error).");
			break;
		case dataError:
			sz = _T("Zlib library error (data error).");
			break;
		case memError:
			sz = _T("Not enough memory.");
			break;
		case bufError:
			sz = _T("Zlib library error (buffer error).");
			break;
		case versionError:
			sz = _T("Zlib library error (version error).");
			break;
		default:
			sz = bNoLoop ? _T("Unknown error") :(LPCTSTR) GetSystemErrorDescription();
	}
	return sz;
}
ZipException.cpp114
ZipExtraData.cpp
TypeFunctionSourceLine
BOOL CZIPEXTRADATA:Read(char* buffer, WORD uSize)
bool CZipExtraData::Read(char* buffer, WORD uSize)
{
	if (uSize < 4)
			return false;
	WORD size;
	CBytesWriter::ReadBytes(m_uHeaderID, buffer);
	CBytesWriter::ReadBytes(size, buffer + 2);
	if (uSize - 4 < size)
		return false;
	m_data.Allocate(size);
	memcpy(m_data, buffer + 4, size);
	return true;
}

WORD CZipExtraData::Write(char* buffer)const
{
	CBytesWriter::WriteBytes(buffer, m_uHeaderID);
	WORD size = (WORD)m_data.GetSize();
	CBytesWriter::WriteBytes(buffer + 2, size);
	memcpy(buffer + 4, m_data, size);
	return (WORD)(size + 4);
}
ZipExtraData.cpp22
ZipExtraField.cpp
TypeFunctionSourceLine
BOOL CZIPEXTRAFIELD:Read(CZipStorage *pStorage, WORD uSize)
bool CZipExtraField::Read(CZipStorage *pStorage, WORD uSize)
{
	if (uSize == 0)
		return true;
	Clear();
	CZipAutoBuffer buffer;
	buffer.Allocate(uSize);
	pStorage->Read(buffer, uSize, true);
	char* position = (char*) buffer;
	do
	{
		CZipExtraData* pExtra = new CZipExtraData();
		if (!pExtra->Read(position, uSize))
		{
			delete pExtra;
			return false;
		}
		int totalSize = pExtra->GetTotalSize();
		if (totalSize > uSize || totalSize < 0)
			return false;
		position += totalSize;
		uSize = (WORD)(uSize - totalSize);
		Add(pExtra);
	}
	while (uSize > 0);
	return true;
}


void CZipExtraField::Write(char* buffer)const
{
	int offset = 0;
	for (int i = 0; i < GetCount(); i++)
		offset += GetAt(i)->Write(buffer + offset);
}

int CZipExtraField::GetTotalSize()const
{
	int total = 0;
	for (int i = 0; i < GetCount(); i++)
		total += GetAt(i)->GetTotalSize();
	return total;
}
ZipExtraField.cpp18
VOID CZIPEXTRAFIELD:RemoveInternalHeaders()
void CZipExtraField::RemoveInternalHeaders()
{
	for (int i = GetCount() - 1; i >= 0; i--)
	{
		WORD headerID = GetAt(i)->GetHeaderID();
		if (
			headerID == ZIP_EXTRA_ZARCH_NAME)
				RemoveAt(i);
	}
}

CZipExtraData* CZipExtraField::Lookup(WORD headerID, int& index) const
{
	// we can do a non-efficient search here
	// usually the number of extra fields is low, if any
	for (int i = 0; i < GetCount(); i++)
	{
		CZipExtraData* pExtra = GetAt(i);
		if (pExtra->m_uHeaderID == headerID)
		{
			index = i;
			return pExtra;
		}
	}
	return NULL;
}
ZipExtraField.cpp62
ZipFileHeader.cpp
TypeFunctionSourceLine
CZIPFILEHEADER:CZipFileHeader()
CZipFileHeader::CZipFileHeader()
{
	m_uExternalAttr = 0;//ZipPlatform::GetDefaultAttributes();
	m_uModDate = m_uModTime = 0;
	m_uMethod = CZipCompressor::methodDeflate;
	m_uVersionMadeBy = 0;	
	m_uCrc32 = 0;
	// initialize to 0, because on 64 bit platform unsigned long is 8 byte and we are copying only 4 bytes in Read()
	m_uComprSize = m_uUncomprSize = m_uOffset = 0;
	m_uLocalFileNameSize = 0;
	m_uLocalComprSize = m_uLocalUncomprSize = 0;
	m_uVolumeStart = 0;
	m_pszFileName = NULL;
	m_uEncryptionMethod = CZipCryptograph::encNone;
	m_bIgnoreCrc32 = false;
	m_uFlag = 0;
}
ZipFileHeader.cpp34
CZIPFILEHEADER::CZipFileHeader()
CZipFileHeader::~CZipFileHeader()
{
	if (m_pszFileName != NULL)
		delete m_pszFileName;
}
ZipFileHeader.cpp52
BOOL CZIPFILEHEADER:Read(CZipCentralDir& centralDir, bool bReadSignature)
bool CZipFileHeader::Read(CZipCentralDir& centralDir, bool bReadSignature)
{
	CZipStorage *pStorage = centralDir.m_pStorage;
	WORD uFileNameSize, uCommentSize, uExtraFieldSize;
	CZipAutoBuffer buf(FILEHEADERSIZE);
	if (bReadSignature)
	{
		pStorage->Read(buf, FILEHEADERSIZE, true);	
		if (!VerifySignature(buf))
			return false;
	}
	else
		pStorage->Read((char*)buf + 4, FILEHEADERSIZE - 4, true);	

	CBytesWriter::ReadBytes(m_uVersionMadeBy,	buf + 4);
	CBytesWriter::ReadBytes(m_uVersionNeeded,	buf + 6);
	CBytesWriter::ReadBytes(m_uFlag,			buf + 8);
	CBytesWriter::ReadBytes(m_uMethod,			buf + 10);
	CBytesWriter::ReadBytes(m_uModTime,			buf + 12);
	CBytesWriter::ReadBytes(m_uModDate,			buf + 14);
	CBytesWriter::ReadBytes(m_uCrc32,			buf + 16);
	CBytesWriter::ReadBytes(m_uComprSize,		buf + 20, 4);
	CBytesWriter::ReadBytes(m_uUncomprSize,		buf + 24, 4);
	CBytesWriter::ReadBytes(uFileNameSize,		buf + 28);
	CBytesWriter::ReadBytes(uExtraFieldSize,	buf + 30);
	CBytesWriter::ReadBytes(uCommentSize,		buf + 32);
	CBytesWriter::ReadBytes(m_uVolumeStart,		buf + 34, 2);
	CBytesWriter::ReadBytes(m_uInternalAttr,	buf + 36);
	CBytesWriter::ReadBytes(m_uExternalAttr,	buf + 38);
	CBytesWriter::ReadBytes(m_uOffset,			buf + 42, 4);
	buf.Release();

	// we may need to modify this later
	m_uEncryptionMethod = (BYTE)((m_uFlag & (WORD) 1) != 0 ? CZipCryptograph::encStandard : CZipCryptograph::encNone);
	
	ZIP_VOLUME_TYPE uCurDsk = pStorage->GetCurrentVolume();
	m_pszFileNameBuffer.Allocate(uFileNameSize); // don't add NULL at the end
	pStorage->Read(m_pszFileNameBuffer, uFileNameSize, true);

	if (centralDir.m_pStringSettings->IsStandardNameCodePage())
		m_stringSettings.SetDefaultNameCodePage(GetSystemCompatibility());
	else
		m_stringSettings.m_uNameCodePage = centralDir.m_pStringSettings->m_uNameCodePage;

	if (!centralDir.m_pStringSettings->IsStandardCommentCodePage())
		m_stringSettings.m_uCommentCodePage = centralDir.m_pStringSettings->m_uCommentCodePage;

	if (!m_aCentralExtraData.Read(pStorage, uExtraFieldSize))
		return false;

	CZipExtraData* pExtra = m_aCentralExtraData.Lookup(ZIP_EXTRA_ZARCH_NAME);
	if (pExtra != NULL)
	{		
		WORD uExtraDataSize = (WORD)pExtra->m_data.GetSize();
		int offset = 1;
		if (offset > uExtraDataSize)
			return false;
		if (pExtra->m_data[0] <= ZIP_EXTRA_ZARCH_NAME_VER) // else don't parse it
		{
			offset++;
			if (offset > uExtraDataSize)
				return false;
			BYTE flag = pExtra->m_data[1];
			bool bReadCommentCp = (flag & 4) != 0;
			if ((flag & 1) != 0)
			{
				// code page present
				if (offset + 4 > uExtraDataSize)
					return false;
				// avoid warnings
				DWORD temp;
				CBytesWriter::ReadBytes(temp, pExtra->m_data + offset);
				m_stringSettings.m_uNameCodePage = temp;
				offset += 4;
			}

			if ((flag & 3) == 3)
			{
				m_stringSettings.m_bStoreNameInExtraData = true;
				int iFileNameSize = pExtra->m_data.GetSize() - 2 - 4;
				if (bReadCommentCp)
					iFileNameSize -= 4;
				// code page present
				if (offset + iFileNameSize > uExtraDataSize || iFileNameSize <= 0)
					return false;
				CZipAutoBuffer buffer;
				buffer.Allocate(iFileNameSize);
				memcpy(buffer, pExtra->m_data + offset, iFileNameSize);
				m_pszFileName = new CZipString(_T(""));
				ZipCompatibility::ConvertBufferToString(*m_pszFileName, buffer, m_stringSettings.m_uNameCodePage);
				offset += iFileNameSize;
				m_pszFileNameBuffer.Release();
			}
			else
				m_stringSettings.m_bStoreNameInExtraData = false;

			if (bReadCommentCp)
			{
				// code page present
				if (offset + 4 > uExtraDataSize)
					return false;
				DWORD temp;
				CBytesWriter::ReadBytes(temp, pExtra->m_data + offset);
				m_stringSettings.m_uCommentCodePage = temp;
				// offset += 4;
			}
		}
	}


	if (uCommentSize)
	{
		m_pszComment.Allocate(uCommentSize);
		pStorage->Read(m_pszComment, uCommentSize, true);
	}
	
	return pStorage->GetCurrentVolume() == uCurDsk; // check that the whole header is in one volume
}


time_t CZipFileHeader::GetTime()const
{
	struct tm atm;
	atm.tm_sec = (m_uModTime & ~0xFFE0) << 1;
	atm.tm_min = (m_uModTime & ~0xF800) >> 5;
	atm.tm_hour = m_uModTime >> 11;

	atm.tm_mday = m_uModDate & ~0xFFE0;
	atm.tm_mon = ((m_uModDate & ~0xFE00) >> 5) - 1;
	atm.tm_year = (m_uModDate >> 9) + 80;
	atm.tm_isdst = -1;
	return mktime(&atm);
}
ZipFileHeader.cpp58
DWORD CZIPFILEHEADER:Write(CZipStorage *pStorage)
DWORD CZipFileHeader::Write(CZipStorage *pStorage)
{
	m_aCentralExtraData.RemoveInternalHeaders();
	
	WORD uMethod = m_uMethod;

	if (!CheckLengths(false))
		CZipException::Throw(CZipException::tooLongData);

	PrepareFileName();

		
	if (m_stringSettings.m_bStoreNameInExtraData)
	{
		if (m_pszFileName == NULL && m_pszFileNameBuffer.IsAllocated())
			GetFileName(false); // don't clear the buffer, it will be needed in a moment
		ASSERT(m_pszFileName != NULL);
		if (m_pszFileName->GetLength() == 0)
			m_stringSettings.m_bStoreNameInExtraData = false;
	}

	int iSystemCompatibility = GetSystemCompatibility();
	if (!m_stringSettings.IsStandard(iSystemCompatibility))
	{
		CZipExtraData* pExtra = m_aCentralExtraData.CreateNew(ZIP_EXTRA_ZARCH_NAME);
		bool bWriteCommentCp = !m_stringSettings.IsStandardCommentCodePage();

		BYTE flag = 0;				
		int offset = 2;
		char* data = NULL;
		if (m_stringSettings.m_bStoreNameInExtraData)
		{
			CZipAutoBuffer buffer;
			// m_pszFileNameBuffer contains CP_ACP page, we don't check if the current page is CP_ACP - too large dependency on PrepareFileName
			ZipCompatibility::ConvertStringToBuffer(*m_pszFileName, buffer, m_stringSettings.m_uNameCodePage);
			int size = 2 + 4 + buffer.GetSize();
			if (bWriteCommentCp)
				size += 4;
			pExtra->m_data.Allocate(size);
			data = (char*)pExtra->m_data;
			CBytesWriter::WriteBytes(data + offset, (DWORD)m_stringSettings.m_uNameCodePage);
			offset += 4;
			memcpy(data + offset, buffer, buffer.GetSize());
			offset += buffer.GetSize();
			flag = 3;
		}
		else if (!m_stringSettings.IsStandardNameCodePage(iSystemCompatibility))
		{
			int size = 2 + 4;
			if (bWriteCommentCp)
				size += 4;
			pExtra->m_data.Allocate(size);
			data = (char*)pExtra->m_data;
			CBytesWriter::WriteBytes(data + offset, (DWORD)m_stringSettings.m_uNameCodePage);
			offset += 4;
			flag = 1;
		}

		if (bWriteCommentCp)
		{
			if (!pExtra->m_data.IsAllocated())
			{
				pExtra->m_data.Allocate(2 + 4);
				data = (char*)pExtra->m_data;
			}
			ASSERT(data);
			CBytesWriter::WriteBytes(data + offset, (DWORD)m_stringSettings.m_uCommentCodePage);
			flag |= 4;
		}

		data[0] = ZIP_EXTRA_ZARCH_NAME_VER;
		data[1] = flag;
	}

	WORD uFileNameSize = (WORD)m_pszFileNameBuffer.GetSize(), uCommentSize = (WORD)GetCommentSize(),
		uExtraFieldSize = (WORD)m_aCentralExtraData.GetTotalSize();
	DWORD uSize = FILEHEADERSIZE + uFileNameSize + uCommentSize + uExtraFieldSize;
	CZipAutoBuffer buf(uSize);
	char* dest = (char*)buf;
	memcpy(dest, m_gszSignature, 4);
	CBytesWriter::WriteBytes(dest + 4,  m_uVersionMadeBy);
	CBytesWriter::WriteBytes(dest + 6,  m_uVersionNeeded);
	CBytesWriter::WriteBytes(dest + 8,  m_uFlag);
	CBytesWriter::WriteBytes(dest + 10, uMethod);
	CBytesWriter::WriteBytes(dest + 12, m_uModTime);
	CBytesWriter::WriteBytes(dest + 14, m_uModDate);
	WriteCrc32(dest + 16);
	CBytesWriter::WriteBytes(dest + 20, CBytesWriter::WriteSafeU32(m_uComprSize));
	CBytesWriter::WriteBytes(dest + 24, CBytesWriter::WriteSafeU32(m_uUncomprSize));
	CBytesWriter::WriteBytes(dest + 28, uFileNameSize);
	CBytesWriter::WriteBytes(dest + 30, uExtraFieldSize);
	CBytesWriter::WriteBytes(dest + 32, uCommentSize);
	CBytesWriter::WriteBytes(dest + 34, CBytesWriter::WriteSafeU16(m_uVolumeStart));
	CBytesWriter::WriteBytes(dest + 36, m_uInternalAttr);
	CBytesWriter::WriteBytes(dest + 38, m_uExternalAttr);
	CBytesWriter::WriteBytes(dest + 42, CBytesWriter::WriteSafeU32(m_uOffset));

	memcpy(dest + 46, m_pszFileNameBuffer, uFileNameSize);

	if (uExtraFieldSize)
		m_aCentralExtraData.Write(dest + 46 + uFileNameSize);

	if (uCommentSize)
		memcpy(dest + 46 + uFileNameSize + uExtraFieldSize, m_pszComment, uCommentSize);
	
	pStorage->Write(dest, uSize, true);

	// remove to avoid miscalculations in GetSize()
	m_aCentralExtraData.RemoveInternalHeaders();	
	ClearFileName();
	return uSize;
}
ZipFileHeader.cpp192
BOOL CZIPFILEHEADER:ReadLocal(CZipCentralDir& centralDir)
bool CZipFileHeader::ReadLocal(CZipCentralDir& centralDir)
{
	char buf[LOCALFILEHEADERSIZE];
	CZipStorage* pStorage = centralDir.m_pStorage;
	pStorage->Read(buf, LOCALFILEHEADERSIZE, true);
	if (memcmp(buf, m_gszLocalSignature, 4) != 0)
		return false;
	
	bool bIsDataDescr = (((WORD)*(buf + 6)) & 8) != 0;
	
	WORD uTemp; 
	CBytesWriter::ReadBytes(uTemp, buf + 6);
	// do not compare the whole flag - the bits reserved by PKWARE may differ 
	// in local and central headers
	if (centralDir.IsConsistencyCheckOn( CZipArchive::checkLocalFlag)
		&& (uTemp & 0xf) != (m_uFlag & 0xf))
		return false;
	
	// method
	WORD uMethod;
	CBytesWriter::ReadBytes(uMethod, buf + 8);

	// this may be different in the local header (it may contain disk name for example)
	CBytesWriter::ReadBytes(m_uLocalFileNameSize, buf + 26); 
	WORD uExtraFieldSize;
	CBytesWriter::ReadBytes(uExtraFieldSize, buf + 28);
	ZIP_VOLUME_TYPE uCurDsk = pStorage->GetCurrentVolume();
	// skip reading the local file name
	pStorage->m_pFile->Seek(m_uLocalFileNameSize, CZipAbstractFile::current);
	if (!m_aLocalExtraData.Read(pStorage, uExtraFieldSize))
		return false;

		CBytesWriter::ReadBytes(m_uLocalComprSize, buf + 18, 4);
		CBytesWriter::ReadBytes(m_uLocalUncomprSize, buf + 22, 4);
	if (uMethod == CZipCompressor::methodWinZipAes && IsEncrypted())
		CZipException::Throw(CZipException::noAES);

	if (centralDir.IsConsistencyCheckOn( CZipArchive::checkLocalMethod)
		&& uMethod != m_uMethod )
		return false;

	if (!bIsDataDescr && centralDir.IsConsistencyCheckOn( CZipArchive::checkLocalCRC |  CZipArchive::checkLocalSizes))
	{
		// read all at once - probably overally faster than checking and reading separately
		DWORD uCrc32;
		CBytesWriter::ReadBytes(uCrc32, buf + 14);
		if (centralDir.IsConsistencyCheckOn( CZipArchive::checkLocalCRC)
			&& uCrc32 != m_uCrc32)
			return false;

		if (centralDir.IsConsistencyCheckOn( CZipArchive::checkLocalSizes)
			// do not check, if local compressed size is 0 - this usually means, that some archiver 
			// could not update the compressed size after compression
			&& ( m_uLocalComprSize != 0 && m_uLocalComprSize != m_uComprSize || m_uLocalUncomprSize != m_uUncomprSize))
			return false;
	}
	return pStorage->GetCurrentVolume() == uCurDsk; // check that the whole header is in one volume
}
ZipFileHeader.cpp306
VOID CZIPFILEHEADER:SetTime(const time_t & ttime)
void CZipFileHeader::SetTime(const time_t & ttime)
{
#if _MSC_VER >= 1400
	tm gts;
	tm* gt = >s;
	localtime_s(gt, &ttime);
#else
	tm* gt = localtime(&ttime);
#endif
	WORD year, month, day, hour, min, sec;
	if (gt == NULL)
	{
		year = 0;
		month = day = 1;
		hour = min = sec = 0;
	}
	else
	{
		year = (WORD)(gt->tm_year + 1900);		
		if (year <= 1980)
			year = 0;
		else
			year -= 1980;
		month = (WORD)gt->tm_mon + 1;
		day = (WORD)gt->tm_mday;
		hour = (WORD)gt->tm_hour;
		min = (WORD)gt->tm_min;
		sec = (WORD)gt->tm_sec;
	}
	    
    m_uModDate = (WORD) (day + ( month << 5) + (year << 9));
    m_uModTime = (WORD) ((sec >> 1) + (min << 5) + (hour << 11));
}

void CZipFileHeader::ConvertFileName(CZipAutoBuffer& buffer) const
{	
	if (m_pszFileName == NULL)
		return;
	CZipString temp = *m_pszFileName;
	ZipCompatibility::SlashBackslashChg(temp, false);
	if (m_stringSettings.m_bStoreNameInExtraData)
		ZipCompatibility::ConvertStringToBuffer(temp, buffer, m_stringSettings.GetDefaultNameCodePage(GetSystemCompatibility()));
	else
		ZipCompatibility::ConvertStringToBuffer(temp, buffer, m_stringSettings.m_uNameCodePage);
}

void CZipFileHeader::ConvertFileName(CZipString& szFileName) const
{	
	if (!m_pszFileNameBuffer.IsAllocated() || m_pszFileNameBuffer.GetSize() == 0)
		return;
	ZipCompatibility::ConvertBufferToString(szFileName, m_pszFileNameBuffer, m_stringSettings.m_uNameCodePage);
	int sc = ZipPlatform::GetSystemID();
	if (sc == ZipCompatibility::zcDosFat || sc == ZipCompatibility::zcNtfs)
		ZipCompatibility::SlashBackslashChg(szFileName, true);
	else // some archives may have an invalid path separator stored
		ZipCompatibility::SlashBackslashChg(szFileName, false);
}
ZipFileHeader.cpp365
VOID CZIPFILEHEADER:WriteLocal(CZipStorage *pStorage)
void CZipFileHeader::WriteLocal(CZipStorage *pStorage)
{	
	if (IsDataDescriptor())
	{
		m_uLocalComprSize = 0;
		// write, if we know it - WinZip 9.0 in segmented mode with AES encryption will 
		// complain otherwise (this seems like a bug, because the data descriptor is present and
		// local descriptor should be discarded)
		if (!IsWinZipAesEncryption())
			m_uLocalUncomprSize = 0;
	}
	else
	{
		m_uLocalComprSize = GetDataSize(true, false);
	}

	WORD uMethod = m_uMethod;

	PrepareFileName();
	m_uLocalFileNameSize = (WORD)m_pszFileNameBuffer.GetSize();
	DWORD uExtraFieldSize = m_aLocalExtraData.GetTotalSize();
	DWORD iLocalSize = LOCALFILEHEADERSIZE + uExtraFieldSize + m_uLocalFileNameSize;
	CZipAutoBuffer buf(iLocalSize);
	char* dest = (char*) buf;
	memcpy(dest, m_gszLocalSignature, 4);

	CBytesWriter::WriteBytes(dest + 4,  m_uVersionNeeded);
	CBytesWriter::WriteBytes(dest + 6,  m_uFlag);
	CBytesWriter::WriteBytes(dest + 8,  uMethod);
	CBytesWriter::WriteBytes(dest + 10, m_uModTime);
	CBytesWriter::WriteBytes(dest + 12, m_uModDate);
	WriteSmallDataDescriptor(dest + 14);
	CBytesWriter::WriteBytes(dest + 26, m_uLocalFileNameSize);
	CBytesWriter::WriteBytes(dest + 28, (WORD)uExtraFieldSize);
	memcpy(dest + 30, m_pszFileNameBuffer, m_uLocalFileNameSize);

	if (uExtraFieldSize)
		m_aLocalExtraData.Write(dest + 30 + m_uLocalFileNameSize);

	// possible volume change before writing to the file in the segmented archive
	// so write the local header first 
	pStorage->Write(dest, iLocalSize, true);

	m_uVolumeStart = pStorage->GetCurrentVolume();	
	m_uOffset = pStorage->GetPosition() - iLocalSize;
	ClearFileName();
}

WORD CZipFileHeader::GetDataDescriptorSize(bool bConsiderSignature) const
{
	if (IsDataDescriptor())
	{
		
		WORD size = 12;
		return (WORD)(bConsiderSignature ? size + 4 : size);
	}
	else
		return 0;
}	

bool CZipFileHeader::NeedsDataDescriptor() const
{
	return m_uEncryptionMethod == CZipCryptograph::encStandard;
}
ZipFileHeader.cpp423
VOID CZIPFILEHEADER:PrepareData(int iLevel, bool bSegm)
void CZipFileHeader::PrepareData(int iLevel, bool bSegm)
{
	// could be == 1, but the way below it works for PredictMaximumFileSizeInArchive when used on an existing segmented archive - for whatever reason
	m_uInternalAttr = 0;

	// version made by

	SetVersion((WORD)(0x14)); 


	m_uCrc32 = 0;
	m_uComprSize = 0;
	m_uUncomprSize = 0;

	ASSERT(CZipCompressor::IsCompressionSupported(m_uMethod) && ((iLevel == 0) == (m_uMethod == CZipCompressor::methodStore)));

	m_uFlag  = 0;
	if (m_uMethod == CZipCompressor::methodDeflate)
		switch (iLevel)
		{
		case 1:
			m_uFlag  |= 6;
			break;
		case 2:
			m_uFlag  |= 4;
			break;
		case 8:
		case 9:
			m_uFlag  |= 2;
			break;
		}

	UpdateFlag(bSegm);

	m_uVersionNeeded = 0;
	if (m_uVersionNeeded == 0)
		m_uVersionNeeded = IsDirectory() ? 0xa : 0x14; // 1.0 or 2.0		
}


void CZipFileHeader::GetCrcAndSizes(char * pBuffer)const
{
	WriteCrc32(pBuffer);
	CBytesWriter::WriteBytes(pBuffer + 4, m_uComprSize, 4);
	CBytesWriter::WriteBytes(pBuffer + 8, m_uUncomprSize, 4);
}

bool CZipFileHeader::CheckDataDescriptor(CZipStorage* pStorage) const
{
	if (!IsDataDescriptor())
		return true;

	const int sizeOfSize = 4;

	const int size = 4 + 2 * sizeOfSize; // crc and two sizes

	CZipAutoBuffer buf(size + 4);
	pStorage->Read(buf, size, false);
	char* pBuf;

	// when an archive is segmented, files that are divided between volume have bit 3 of flag set
	// which tell about the presence of the data descriptor after the compressed data
	// This signature may be in a segmented archive that is one volume only
	// (it is detected as a not segmented archive)
	if (memcmp(buf, CZipStorage::m_gszExtHeaderSignat, 4) == 0) // there is a signature
	{
		pStorage->Read((char*)buf + size, 4, false);
		pBuf = (char*)buf + 4;
	}
	else 
		pBuf = buf;

	DWORD uCrc32 = 0;
	ZIP_SIZE_TYPE uCompressed = 0, uUncompressed = 0;

	CBytesWriter::ReadBytes(uCrc32,			pBuf);
	CBytesWriter::ReadBytes(uCompressed,	pBuf + 4, sizeOfSize);
	CBytesWriter::ReadBytes(uUncompressed,	pBuf + 4 + sizeOfSize, sizeOfSize);
	return uCrc32 == m_uCrc32 && uCompressed == m_uComprSize && uUncompressed == m_uUncomprSize;
}

DWORD CZipFileHeader::GetSize()const
{	
	DWORD uSize = FILEHEADERSIZE + PredictFileNameSize() + GetCommentSize();
	uSize += m_aCentralExtraData.GetTotalSize();
	if (m_stringSettings.m_bStoreNameInExtraData)
	{
		CZipString temp;
		if (m_pszFileName != NULL)
			temp = *m_pszFileName;
		else
			ConvertFileName(temp);			
		if (temp.GetLength() > 0)
		{
			uSize += 4 + 2 + 4; // headerID, size + version, flag + filename code page
			CZipAutoBuffer buffer;				
			ZipCompatibility::ConvertStringToBuffer(temp, buffer, m_stringSettings.m_uNameCodePage);
			uSize += buffer.GetSize();
			if (!m_stringSettings.IsStandardCommentCodePage())
				uSize += 4;
		}
	}
	return uSize;
}

DWORD CZipFileHeader::GetLocalSize(bool bReal)const
{
	DWORD uSize = LOCALFILEHEADERSIZE + m_aLocalExtraData.GetTotalSize();
	if (bReal)
		uSize += m_uLocalFileNameSize;
	else
		uSize += PredictFileNameSize();
	return uSize;
}
ZipFileHeader.cpp489
VOID CZIPFILEHEADER:SetComment(LPCTSTR lpszComment)
void CZipFileHeader::SetComment(LPCTSTR lpszComment)
{
	ZipCompatibility::ConvertStringToBuffer(lpszComment, m_pszComment, m_stringSettings.m_uCommentCodePage);
}

CZipString CZipFileHeader::GetComment() const
{
	CZipString temp;
	ZipCompatibility::ConvertBufferToString(temp, m_pszComment, m_stringSettings.m_uCommentCodePage);
	return temp;
}

int CZipFileHeader::GetCompressionLevel() const
{
	if (m_uMethod == CZipCompressor::methodStore)
		return CZipCompressor::levelStore;
	else if ((m_uFlag & (WORD) 6) != 0)
		return 1;
	else if ((m_uFlag & (WORD) 4) != 0)
		return 2;
	else if ((m_uFlag & (WORD) 2) != 0)
		return CZipCompressor::levelBest;
	else
		return CZipCompressor::levelDefault;
}
ZipFileHeader.cpp604
VOID CZIPFILEHEADER:SetFileName(LPCTSTR lpszFileName)
void CZipFileHeader::SetFileName(LPCTSTR lpszFileName)
{
	if (m_pszFileName == NULL)
		m_pszFileName = new CZipString(lpszFileName);
	else
		*m_pszFileName = lpszFileName;
	m_pszFileNameBuffer.Release();
}
ZipFileHeader.cpp630
CZIPSTRING& CZIPFILEHEADER:GetFileName(bool bClearBuffer)
CZipString& CZipFileHeader::GetFileName(bool bClearBuffer)
{
	if (m_pszFileName != NULL)
		return *m_pszFileName;
	m_pszFileName = new CZipString(_T(""));
	ConvertFileName(*m_pszFileName);
	// don't keep it in memory
	if (bClearBuffer)
		m_pszFileNameBuffer.Release();		
	return *m_pszFileName;
}
ZipFileHeader.cpp639
BOOL CZIPFILEHEADER:IsDirectory()
bool CZipFileHeader::IsDirectory()
{
	return ZipPlatform::IsDirectory(GetSystemAttr());
}
ZipFileHeader.cpp651
DWORD CZIPFILEHEADER:GetSystemAttr()
DWORD CZipFileHeader::GetSystemAttr()
{
	int iSystemComp = GetSystemCompatibility();
	if (ZipCompatibility::IsPlatformSupported(iSystemComp))
	{		
		DWORD uAttr = iSystemComp == ZipCompatibility::zcUnix ? (m_uExternalAttr >> 16) : (m_uExternalAttr & 0xFFFF);
		if (!uAttr && CZipPathComponent::HasEndingSeparator(GetFileName()))			
			return ZipPlatform::GetDefaultDirAttributes(); // can happen
		else
		{			
			uAttr = ZipCompatibility::ConvertToSystem(uAttr, iSystemComp, ZipPlatform::GetSystemID());
#ifdef ZIP_ARCHIVE_LNX
			// converting from Windows attributes may create a not readable linux directory
			if (iSystemComp != ZipCompatibility::zcUnix && ZipPlatform::IsDirectory(uAttr))
				return ZipPlatform::GetDefaultDirAttributes();
#endif
			return uAttr;
		}
	}
	else
		return CZipPathComponent::HasEndingSeparator(GetFileName()) ? ZipPlatform::GetDefaultDirAttributes() : ZipPlatform::GetDefaultAttributes();
}
ZipFileHeader.cpp656
VOID CZIPFILEHEADER:SetSystemAttr(DWORD uAttr)
void CZipFileHeader::SetSystemAttr(DWORD uAttr)
{
	// make it readable under Unix as well, since it stores its attributes in HIWORD(uAttr)
	int iSystemComp = GetSystemCompatibility();
	m_uExternalAttr = ZipCompatibility::ConvertToSystem(uAttr, ZipPlatform::GetSystemID(), iSystemComp);
	if (iSystemComp == ZipCompatibility::zcUnix)
	{
		m_uExternalAttr <<= 16;
		if (ZipPlatform::IsDirectory(uAttr))
			m_uExternalAttr |= 0x10; // make it recognizable under other systems (all use 0x10 for directory)
	}
	else
		// make it readable under linux
		m_uExternalAttr |= (ZipCompatibility::ConvertToSystem(uAttr, ZipPlatform::GetSystemID(), ZipCompatibility::zcUnix) << 16);		
}
ZipFileHeader.cpp679
CZIPFILEHEADER& CZIPFILEHEADER::OPERATOR(const CZipFileHeader& header)
CZipFileHeader& CZipFileHeader::operator=(const CZipFileHeader& header)
{
	m_uVersionMadeBy = header.m_uVersionMadeBy;	
	m_uVersionNeeded = header.m_uVersionNeeded;
	m_uFlag = header.m_uFlag;
	m_uMethod = header.m_uMethod;
	m_uModTime = header.m_uModTime;
	m_uModDate = header.m_uModDate;
	m_uCrc32 = header.m_uCrc32;
	m_uComprSize = header.m_uComprSize;
	m_uUncomprSize = header.m_uUncomprSize;
	m_uVolumeStart = header.m_uVolumeStart;
	m_uInternalAttr = header.m_uInternalAttr;
	m_uLocalComprSize = header.m_uLocalComprSize;
	m_uLocalUncomprSize = header.m_uUncomprSize;
	m_uExternalAttr = header.m_uExternalAttr;	
	m_uLocalFileNameSize = header.m_uLocalFileNameSize;;
	m_uOffset = header.m_uOffset;
	m_aLocalExtraData = header.m_aLocalExtraData;
	m_aCentralExtraData = header.m_aCentralExtraData;
	m_uEncryptionMethod = header.m_uEncryptionMethod;
	if (m_pszFileName)
		delete m_pszFileName;

	if (header.m_pszFileName)
		m_pszFileName = new CZipString(*header.m_pszFileName);
	else
		m_pszFileName = NULL;
	
	m_pszFileNameBuffer = header.m_pszFileNameBuffer;
	m_pszComment = header.m_pszComment;
	m_stringSettings = header.m_stringSettings;

	return *this;
}
ZipFileHeader.cpp695
VOID CZIPFILEHEADER:WriteSmallDataDescriptor(char* pDest, bool bLocal)
void CZipFileHeader::WriteSmallDataDescriptor(char* pDest, bool bLocal)
{
	WriteCrc32(pDest);
	if (bLocal)
	{
		CBytesWriter::WriteBytes(pDest + 4, m_uLocalComprSize, 4);
		CBytesWriter::WriteBytes(pDest + 8, m_uLocalUncomprSize, 4);
	}
	else
	{
		CBytesWriter::WriteBytes(pDest + 4, m_uComprSize, 4);
		CBytesWriter::WriteBytes(pDest + 8, m_uUncomprSize, 4);
	}
}
ZipFileHeader.cpp731
VOID CZIPFILEHEADER:WriteDataDescriptor(CZipStorage* pStorage)
void CZipFileHeader::WriteDataDescriptor(CZipStorage* pStorage)
{
	if (!IsDataDescriptor())
		return;
	bool signature = NeedsSignatureInDataDescriptor(pStorage);
	CZipAutoBuffer buf;
	buf.Allocate(GetDataDescriptorSize(signature));
	char* pBuf;
	if (signature)
	{
		memcpy(buf, CZipStorage::m_gszExtHeaderSignat, 4);
		pBuf = (char*)buf + 4;
	}
	else
		pBuf = buf;
	WriteCrc32(pBuf);
		CBytesWriter::WriteBytes(pBuf + 4, m_uComprSize, 4);
		CBytesWriter::WriteBytes(pBuf + 8, m_uUncomprSize, 4);
	pStorage->Write(buf, buf.GetSize(), true);
}
ZipFileHeader.cpp747
VOID CZIPFILEHEADER:UpdateLocalHeader(CZipStorage* pStorage)
void CZipFileHeader::UpdateLocalHeader(CZipStorage* pStorage)
{
	if (pStorage->IsSegmented() != 0 || IsDataDescriptor())
		// there is nothing to fix 
		return;
	pStorage->Flush();
	ZIP_FILE_USIZE uPos = pStorage->m_pFile->GetPosition();	
		// update crc and sizes, the sizes may already be all right,
		// but 8 more bytes won't make a difference, we need to update crc32 anyway
		CZipAutoBuffer buf(12);		
		m_uLocalComprSize = CBytesWriter::WriteSafeU32(m_uComprSize);
		m_uLocalUncomprSize = CBytesWriter::WriteSafeU32(m_uUncomprSize);
		WriteSmallDataDescriptor(buf);
		pStorage->Seek(m_uOffset + 14);
		pStorage->m_pFile->Write(buf, 12);

	pStorage->m_pFile->Seek(uPos);
}

void CZipFileHeader::WriteCrc32(char* pBuf) const
{
	DWORD uCrc = m_bIgnoreCrc32 ? 0 : m_uCrc32;
	CBytesWriter::WriteBytes(pBuf, uCrc);
}
ZipFileHeader.cpp768
ZipFile_mfc.cpp
TypeFunctionSourceLine
IMPLEMENT_DYNAMIC(CZIPFILE, CFILE) CZIPFILE:CZipFile()
CZipFile::CZipFile()
{
}
ZipFile_mfc.cpp25
CZIPFILE::CZipFile()
CZipFile::~CZipFile()
{
	Close();
}
ZipFile_mfc.cpp29
CZIPFILE::OPERATORHANDLE()
CZipFile::operator HANDLE()
{
	return (HANDLE)m_hFile;
}
ZipFile_mfc.cpp34
ZipFile_stl.cpp
TypeFunctionSourceLine
CZIPFILE:CZipFile()
CZipFile::CZipFile()
{
	m_hFile = -1;
}

void CZipFile::ThrowError() const
{
	CZipException::Throw(errno, m_szFileName);
}


ZIP_FILE_USIZE CZipFile::GetLength() const
{
	// cannot use Seek here, Seek is not const
	ZIP_SIZE_TYPE lLen, lCur;
	lCur = _lseek(m_hFile, 0, current);
	if (lCur == (ZIP_SIZE_TYPE)-1)
		ThrowError();
	lLen = _lseek(m_hFile, 0, end);

	// first go back
	bool err = _lseek(m_hFile, lCur, begin) == -1;

	if (err || lLen == (ZIP_SIZE_TYPE)-1)
		ThrowError();
	return lLen;

}
ZipFile_stl.cpp32
BOOL CZIPFILE:Open(LPCTSTR lpszFileName, UINT openFlags, bool bThrow)
bool CZipFile::Open(LPCTSTR lpszFileName, UINT openFlags, bool bThrow)
{
	if (!IsClosed())
		Close();

#ifdef O_BINARY
	UINT iNewFlags = O_BINARY;
#else
	UINT iNewFlags = 0;
#endif

	bool bReadOnly = false;
	if (openFlags & CZipFile::modeCreate)
		iNewFlags |= O_CREAT;
	if ((openFlags & CZipFile::modeReadWrite) == CZipFile::modeReadWrite)
		iNewFlags |= O_RDWR;
	else if (openFlags & CZipFile::modeRead)
	{
		// O_RDONLY is defined as 0
		bReadOnly = true;
		iNewFlags |= O_RDONLY;
	}
	else if (openFlags & CZipFile::modeWrite)
		iNewFlags |= O_WRONLY;

	if (!(openFlags & CZipFile::modeNoTruncate) && !bReadOnly)
		iNewFlags |= O_TRUNC;
	m_hFile = ZipPlatform::OpenFile(lpszFileName, iNewFlags, openFlags & 0x1C);
	if (m_hFile == -1)
		if (bThrow)
			CZipException::Throw(errno, lpszFileName);
		else
			return false;
	m_szFileName = lpszFileName;
	return true;
}
ZipFile_stl.cpp62
VOID CZIPFILE:SetLength(ULONGLONG uNewLen)
void CZipFile::SetLength(ULONGLONG uNewLen)
{
	ZipPlatform::TruncateFile(m_hFile, uNewLen);
}

ZIP_FILE_USIZE CZipFile::GetPosition() const
{
	#ifndef __GNUC__
		ZIP_FILE_USIZE ret = _tell(m_hFile);
	#else
		ZIP_FILE_USIZE ret = lseek(m_hFile, 0, SEEK_CUR);
	#endif
		if (ret == (ZIP_FILE_USIZE)-1)
			ThrowError();
		return ret;
}
ZipFile_stl.cpp100
ZIP_FILE_USIZE CZIPFILE:Seek(ZIP_FILE_SIZE dOff, int nFrom)
ZIP_FILE_USIZE CZipFile::Seek(ZIP_FILE_SIZE dOff, int nFrom)
{
	// restricted to signed
	ZIP_FILE_SIZE ret = (ZIP_FILE_SIZE)_lseek(m_hFile, (long)dOff, nFrom);
	if (ret == -1)
		ThrowError();
	return (ZIP_FILE_USIZE)ret;
}
ZipFile_stl.cpp117
VOID CZIPFILE:Flush()
void  CZipFile::Flush()
{
	if (!ZipPlatform::FlushFile(m_hFile)) 
		ThrowError();
}
ZipFile_stl.cpp126
CZIPFILE::OPERATORHANDLE()
CZipFile::operator HANDLE()
{
	intptr_t fh = ZipPlatform::GetFileSystemHandle(m_hFile);
	if (fh == -1)
		ThrowError();
#if _MSC_VER >= 1300
	return (HANDLE)fh;
#else
	return (HANDLE)fh;
#endif
}
ZipFile_stl.cpp132
ZipMemFile.cpp
TypeFunctionSourceLine
VOID CZIPMEMFILE:Grow(size_t nGrowTo)
void CZipMemFile::Grow(size_t nGrowTo)
{
	if (m_nBufSize < (UINT)nGrowTo)
	{
		if (m_nGrowBy == 0)
			CZipException::Throw(CZipException::memError);
		size_t nNewSize = m_nBufSize;
		while (nNewSize < nGrowTo)
			nNewSize += m_nGrowBy;
		BYTE* lpNew;
		if (m_lpBuf)
			lpNew = (BYTE*)realloc((void*) m_lpBuf, nNewSize);
		else
			lpNew = (BYTE*)malloc(nNewSize);

		if (!lpNew)
			CZipException::Throw(CZipException::memError);
		m_nBufSize = nNewSize;
		m_lpBuf = lpNew;
	}
} 
ZipMemFile.cpp23
VOID CZIPMEMFILE:SetLength(ZIP_FILE_USIZE nNewLen)
void CZipMemFile::SetLength(ZIP_FILE_USIZE nNewLen)
{
	if (m_nBufSize < (size_t)nNewLen)
		Grow((size_t)nNewLen);
	else
		m_nPos = (size_t)nNewLen;
	m_nDataSize = (size_t)nNewLen;
}
ZipMemFile.cpp45
UINT CZIPMEMFILE:Read(void *lpBuf, UINT nCount)
UINT CZipMemFile::Read(void *lpBuf, UINT nCount)
{
	if (m_nPos >= m_nDataSize)
		return 0;
	UINT nToRead = (m_nPos + nCount > m_nDataSize) ? (UINT)(m_nDataSize - m_nPos) : nCount;
	memcpy(lpBuf, m_lpBuf + m_nPos, nToRead);
	m_nPos += nToRead;
	return nToRead;

}
ZipMemFile.cpp54
VOID CZIPMEMFILE:Write(const void *lpBuf, UINT nCount)
void CZipMemFile::Write(const void *lpBuf, UINT nCount)
{
	if (!nCount)
		return;

	if (m_nPos + nCount > m_nBufSize)
		Grow(m_nPos + nCount);
	memcpy(m_lpBuf + m_nPos, lpBuf, nCount);
	m_nPos += nCount;
	if (m_nPos > m_nDataSize)
		m_nDataSize = m_nPos;
}
ZipMemFile.cpp65
ZIP_FILE_USIZE CZIPMEMFILE:Seek(ZIP_FILE_SIZE lOff, int nFrom)
ZIP_FILE_USIZE CZipMemFile::Seek(ZIP_FILE_SIZE lOff, int nFrom)
{
	ZIP_FILE_USIZE lNew = m_nPos;

	if (nFrom == CZipAbstractFile::begin)
	{
		if (lOff < 0)
			CZipException::Throw(CZipException::memError);
		lNew = lOff;
	}
	else if (nFrom == CZipAbstractFile::current)
	{
		if (lOff < 0 && (ZIP_FILE_USIZE)(-lOff) > lNew)
			CZipException::Throw(CZipException::memError);
		lNew += lOff;
	}
	else if (nFrom == CZipAbstractFile::end)
	{
		if (lOff < 0 && ZIP_FILE_USIZE(-lOff) > m_nDataSize)
			CZipException::Throw(CZipException::memError);
		lNew = m_nDataSize + lOff;
	}
	else
		return lNew;

	// assumption that size_t is always signed
	if (lNew > (size_t)(-1)) // max of size_t
		CZipException::Throw(CZipException::memError);
	if (lNew > m_nDataSize)
		Grow((size_t)lNew);
	
	m_nPos = (size_t)lNew;
	return lNew;
}
ZipMemFile.cpp77
ZipPathComponent_lnx.cpp
TypeFunctionSourceLine
CZIPPATHCOMPONENT::CZipPathComponent()
CZipPathComponent::~CZipPathComponent()
{
}
ZipPathComponent_lnx.cpp23
VOID CZIPPATHCOMPONENT:SetFullPath(LPCTSTR lpszFullPath)
void CZipPathComponent::SetFullPath(LPCTSTR lpszFullPath)
{
	
	CZipString szTempPath(lpszFullPath);
	const CZipString szPrefix = _T("\\\\?\\unc\\");
	int i = -1, iLen = szPrefix.GetLength();
	if (iLen > szTempPath.GetLength())
		iLen = szTempPath.GetLength();
	CZipString szPossiblePrefix = szTempPath.Left(iLen);
	szPossiblePrefix.MakeLower(); // must perform case insensitive comparison
	while (++i < iLen && szPossiblePrefix[i] == szPrefix[i]); 
	if (i == 2 || i == 4 || i == 8) // unc path, unicode path or unc path meeting windows file name conventions
	{
		m_szPrefix = szTempPath.Left(i);
		szTempPath = szTempPath.Mid(i);		
	}
	else
		m_szPrefix.Empty();


	m_szDrive.Empty(); 
	m_szFileTitle.Empty();
	m_szDirectory.Empty();
	m_szFileExt.Empty();
	int p;
	for (p = szTempPath.GetLength() - 1; p >= 0; p--)
		if (szTempPath[p] == m_cSeparator)
			break;

	if (p != -1)
	{
		m_szDirectory = szTempPath.Left(p);
		if (p == szTempPath.GetLength() - 1 )
			return; // no filename present
		else 
			p++;
	}
	else 
		p = 0;

	// p points at the beginning of the filename
	m_szFileTitle = szTempPath.Mid(p);
	for (p = m_szFileTitle.GetLength() - 1; p >= 0; p--)
		if (m_szFileTitle[p] == _T('.'))
			break;

	if (p != -1)
	{
		m_szFileExt = m_szFileTitle.Mid(p+1);
		m_szFileTitle = m_szFileTitle.Left(p);
	}


	
}

CZipString CZipPathComponent::GetNoDrive() const
{
	CZipString szPath = m_szDirectory;
	CZipString szFileName = GetFileName();
	if (!szFileName.IsEmpty() && !szPath.IsEmpty())
		szPath += m_cSeparator;

	szPath += szFileName;
	return szPath;	
}
ZipPathComponent_lnx.cpp27
ZipPathComponent_win.cpp
TypeFunctionSourceLine
CZIPPATHCOMPONENT::CZipPathComponent()
CZipPathComponent::~CZipPathComponent()
{

}
ZipPathComponent_win.cpp22
VOID CZIPPATHCOMPONENT:SetFullPath(LPCTSTR lpszFullPath)
void CZipPathComponent::SetFullPath(LPCTSTR lpszFullPath)
{

	TCHAR szDrive[_MAX_DRIVE];
#if defined _UNICODE && _MSC_VER >= 1400
	TCHAR szDir[32767];
#else
	TCHAR szDir[_MAX_DIR];
#endif
	TCHAR szFname[_MAX_FNAME];
	TCHAR szExt[_MAX_EXT];
	
	
	CZipString szTempPath(lpszFullPath);
	const CZipString szPrefix = _T("\\\\?\\unc\\");
	int i = -1, iLen = szPrefix.GetLength();
	if (iLen > szTempPath.GetLength())
		iLen = szTempPath.GetLength();
	CZipString szPossiblePrefix = szTempPath.Left(iLen);
	szPossiblePrefix.MakeLower(); // must perform case insensitive comparison
	while (++i < iLen && szPossiblePrefix[i] == szPrefix[i]); 
	if (i == 2 || i == 4 || i == 8) // unc path, unicode path or unc path meeting windows file name conventions
	{
		m_szPrefix = szTempPath.Left(i);
		szTempPath = szTempPath.Mid(i);		
	}
	else
		m_szPrefix.Empty();
#if _MSC_VER >= 1400	
	_tsplitpath_s(szTempPath, szDrive , szDir, szFname, szExt);
#else
	_tsplitpath(szTempPath, szDrive , szDir, szFname, szExt);
#endif
	
	m_szDrive = szDrive;
	m_szDirectory = szDir;
	
	m_szDirectory.TrimLeft(m_cSeparator);
	m_szDirectory.TrimRight(m_cSeparator);
	SetExtension(szExt);
	m_szFileTitle = szFname;
}


CZipString CZipPathComponent::GetNoDrive() const
{
	CZipString szPath = m_szDirectory;
	CZipString szFileName = GetFileName();
	if (!szFileName.IsEmpty() && !szPath.IsEmpty())
		szPath += m_cSeparator;

	szPath += szFileName;
	return szPath;	
}
ZipPathComponent_win.cpp27
ZipPlatformComm.cpp
TypeFunctionSourceLine
BOOL ZIPPLATFORM:DirectoryExists(LPCTSTR lpszDir)
bool ZipPlatform::DirectoryExists(LPCTSTR lpszDir)
{
	CZipString sz;
	if (!GetCurrentDirectory(sz))
		return false;
	if (!ChangeDirectory(lpszDir))
		return false;
	ChangeDirectory(sz);
	return true;
}
ZipPlatformComm.cpp22
BOOL ZIPPLATFORM:ForceDirectory(LPCTSTR lpDirectory)
bool ZipPlatform::ForceDirectory(LPCTSTR lpDirectory)
{
	ASSERT(lpDirectory);
	CZipString szDirectory = lpDirectory;
	szDirectory.TrimRight(CZipPathComponent::m_cSeparator);
	CZipPathComponent zpc(szDirectory);
	if ((zpc.GetFilePath().Compare((LPCTSTR)szDirectory)) == 0 ||
		(FileExists(szDirectory) == -1))
		return true;
	if (!ForceDirectory(zpc.GetFilePath()))
		return false;
	if (!CreateDirectory(szDirectory))
		return false;
	return true;
}
ZipPlatformComm.cpp33
BOOL ZIPPLATFORM:GetFileSize(LPCTSTR lpszFileName, ZIP_SIZE_TYPE& dSize)
bool ZipPlatform::GetFileSize(LPCTSTR lpszFileName, ZIP_SIZE_TYPE& dSize)
{
	CZipFile f;
	if (!f.Open(lpszFileName, CZipFile::modeRead | CZipFile::shareDenyWrite, false))
		return false;
	bool ret;
	try
	{
		ZIP_FILE_USIZE size = f.GetLength();
		// the file may be too large if zip64 is not enabled
		ret = size <= ZIP_SIZE_TYPE(-1);
		if (ret)
			dSize = (ZIP_SIZE_TYPE)size;
	}
#ifdef ZIP_ARCHIVE_MFC
	catch(CZipBaseException* e)
	{
		e->Delete();
		ret = false;
	}
#else
	catch(CZipBaseException e)
	{
		ret = false;
	}
#endif

	try
	{
		f.Close();
	}
#ifdef ZIP_ARCHIVE_MFC
	catch(CZipBaseException* e)
	{
		e->Delete();
	}
#else
	catch(CZipBaseException e)
	{
	}
#endif

	return ret;	
}
ZipPlatformComm.cpp49
ZipPlatform_lnx.cpp
TypeFunctionSourceLine
ULONGLONG ZIPPLATFORM:GetDeviceFreeSpace(LPCTSTR lpszPath)
ULONGLONG ZipPlatform::GetDeviceFreeSpace(LPCTSTR lpszPath)
{
	struct statfs sStats;

	#if defined (__SVR4) && defined (__sun)
		if (statvfs(lpszPath, &sStats) == -1) // Solaris
	#else
		if (statfs(lpszPath, &sStats) == -1)
	#endif
		return 0;

        return sStats.f_bsize * sStats.f_bavail;
}
ZipPlatform_lnx.cpp59
CZIPSTRING ZIPPLATFORM:GetTmpFileName(LPCTSTR lpszPath, ZIP_SIZE_TYPE uSizeNeeded)
CZipString ZipPlatform::GetTmpFileName(LPCTSTR lpszPath, ZIP_SIZE_TYPE uSizeNeeded)
{
	TCHAR empty[] = _T(""), prefix [] = _T("zar");
	CZipString tempPath = lpszPath;
	if (tempPath.IsEmpty())
		tempPath = "/tmp";
	if (ZipPlatform::GetDeviceFreeSpace(tempPath) < uSizeNeeded)
		return empty;
	CZipPathComponent::AppendSeparator(tempPath);
	tempPath += prefix;
	tempPath += _T("XXXXXX");
	int handle = mkstemp(tempPath.GetBuffer(tempPath.GetLength()));
	tempPath.ReleaseBuffer();
	if (handle != -1)
	{
		close(handle); // we just create the file and open it later
		return tempPath;
	}
	else
		return empty;		
}
ZipPlatform_lnx.cpp77
BOOL ZIPPLATFORM:GetCurrentDirectory(CZipString& sz)
bool ZipPlatform::GetCurrentDirectory(CZipString& sz)
{
	char* pBuf = getcwd(NULL, 0);
	if (!pBuf)
		return false;
	sz = pBuf;
	free(pBuf);
	return true;
}
ZipPlatform_lnx.cpp99
BOOL ZIPPLATFORM:SetFileAttr(LPCTSTR lpFileName, DWORD uAttr)
bool ZipPlatform::SetFileAttr(LPCTSTR lpFileName, DWORD uAttr)
{
	return chmod(lpFileName, uAttr) == 0;
}
ZipPlatform_lnx.cpp109
BOOL ZIPPLATFORM:GetFileAttr(LPCTSTR lpFileName, DWORD& uAttr)
bool ZipPlatform::GetFileAttr(LPCTSTR lpFileName, DWORD& uAttr)
{
	struct stat sStats;
	if (stat(lpFileName, &sStats) == -1)
		return false;
  	uAttr = (sStats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_IFMT));
  	return true;
}
ZipPlatform_lnx.cpp114
BOOL ZIPPLATFORM:SetExeAttr(LPCTSTR lpFileName)
bool ZipPlatform::SetExeAttr(LPCTSTR lpFileName)
{
	DWORD uAttr;
	if (!GetFileAttr(lpFileName, uAttr))
		return false;
	uAttr |= S_IXUSR;
	return ZipPlatform::SetFileAttr(lpFileName, uAttr);
}
ZipPlatform_lnx.cpp123
BOOL ZIPPLATFORM:GetFileModTime(LPCTSTR lpFileName, time_t & ttime)
bool ZipPlatform::GetFileModTime(LPCTSTR lpFileName, time_t & ttime)
{
    struct stat st;
	if (stat(lpFileName, &st) != 0)
		return false;

 	ttime = st.st_mtime;
	if (ttime == (time_t)-1)
	{
		ttime = time(NULL);
		return false;
	}
	else
		return true;
}
ZipPlatform_lnx.cpp133
BOOL ZIPPLATFORM:SetFileModTime(LPCTSTR lpFileName, time_t ttime)
bool ZipPlatform::SetFileModTime(LPCTSTR lpFileName, time_t ttime)
{
	struct utimbuf ub;
	ub.actime = time(NULL);
	ub.modtime = ttime == -1 ? time(NULL) : ttime; // if wrong file time, set it to the current
	return utime(lpFileName, &ub) == 0;
}
ZipPlatform_lnx.cpp149
BOOL ZIPPLATFORM:ChangeDirectory(LPCTSTR lpDirectory)
bool ZipPlatform::ChangeDirectory(LPCTSTR lpDirectory)
{
	return chdir(lpDirectory) == 0; 
}
ZipPlatform_lnx.cpp158
INT ZIPPLATFORM:FileExists(LPCTSTR lpszName)
int ZipPlatform::FileExists(LPCTSTR lpszName)
{
    	struct stat st;
	if (stat(lpszName, &st) != 0)
		return 0;
	else
	{
		if (S_ISDIR(st.st_mode))
			return -1;
		else
			return 1;
	}
}
ZipPlatform_lnx.cpp162
ZIPINLINE BOOL ZIPPLATFORM:IsDriveRemovable(LPCTSTR lpszFilePath)
ZIPINLINE  bool ZipPlatform::IsDriveRemovable(LPCTSTR lpszFilePath)
{
	// not implemmented
	return true;
}
ZipPlatform_lnx.cpp176
ZIPINLINE BOOL ZIPPLATFORM:SetVolLabel(LPCTSTR lpszPath, LPCTSTR lpszLabel)
ZIPINLINE  bool ZipPlatform::SetVolLabel(LPCTSTR lpszPath, LPCTSTR lpszLabel)
{
	// not implemmented
        return true;
}
ZipPlatform_lnx.cpp182
ZIPINLINE VOID ZIPPLATFORM:AnsiOem(CZipAutoBuffer& buffer, bool bAnsiToOem)
ZIPINLINE void ZipPlatform::AnsiOem(CZipAutoBuffer& buffer, bool bAnsiToOem)
{
	// not implemmented
}
ZipPlatform_lnx.cpp188
ZIPINLINE BOOL ZIPPLATFORM:RemoveFile(LPCTSTR lpszFileName, bool bThrow)
ZIPINLINE  bool ZipPlatform::RemoveFile(LPCTSTR lpszFileName, bool bThrow)
{
	if (unlink(lpszFileName) != 0)
		if (bThrow)
			CZipException::Throw(CZipException::notRemoved, lpszFileName);
		else 
			return false;
	return true;


}
ZipPlatform_lnx.cpp193
ZIPINLINE BOOL ZIPPLATFORM:RenameFile( LPCTSTR lpszOldName, LPCTSTR lpszNewName , bool bThrow)
ZIPINLINE  bool ZipPlatform::RenameFile( LPCTSTR lpszOldName, LPCTSTR lpszNewName , bool bThrow)
{

	if (rename(lpszOldName, lpszNewName) != 0)
		if (bThrow)
			CZipException::Throw(CZipException::notRenamed, lpszOldName);
		else 
			return false;
		return true;

}
ZipPlatform_lnx.cpp204
ZIPINLINE BOOL ZIPPLATFORM:IsDirectory(DWORD uAttr)
ZIPINLINE  bool ZipPlatform::IsDirectory(DWORD uAttr)
{
	return S_ISDIR(uAttr) != 0;
}
ZipPlatform_lnx.cpp215
ZIPINLINE BOOL ZIPPLATFORM:CreateDirectory(LPCTSTR lpDirectory)
ZIPINLINE  bool ZipPlatform::CreateDirectory(LPCTSTR lpDirectory)
{	
	return mkdir(lpDirectory, ZIP_DEFAULT_DIR_ATTRIBUTES) == 0;
}
ZipPlatform_lnx.cpp220
ZIPINLINE DWORD ZIPPLATFORM:GetDefaultAttributes()
ZIPINLINE  DWORD ZipPlatform::GetDefaultAttributes()
{
	return S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
}
ZipPlatform_lnx.cpp225
ZIPINLINE DWORD ZIPPLATFORM:GetDefaultDirAttributes()
ZIPINLINE  DWORD ZipPlatform::GetDefaultDirAttributes()
{
	return S_IFDIR | ZIP_DEFAULT_DIR_ATTRIBUTES;
}
ZipPlatform_lnx.cpp230
ZIPINLINE INT ZIPPLATFORM:GetSystemID()
ZIPINLINE  int ZipPlatform::GetSystemID()
{
	return ZipCompatibility::zcUnix;
}
ZipPlatform_lnx.cpp236
ZIPINLINE BOOL ZIPPLATFORM:GetSystemCaseSensitivity()
ZIPINLINE bool ZipPlatform::GetSystemCaseSensitivity()
{
	return true;
}
ZipPlatform_lnx.cpp241
BOOL ZIPPLATFORM:TruncateFile(int iDes, ULONGLONG uSize)
bool ZipPlatform::TruncateFile(int iDes, ULONGLONG uSize)
{
	return ftruncate(iDes, uSize) == 0;

}
ZipPlatform_lnx.cpp247
INT ZIPPLATFORM:OpenFile(LPCTSTR lpszFileName, UINT iMode, int iShareMode)
int ZipPlatform::OpenFile(LPCTSTR lpszFileName, UINT iMode, int iShareMode)
{
	return open(lpszFileName, iMode, S_IRUSR | S_IWUSR | S_IRGRP |S_IROTH );	
}
ZipPlatform_lnx.cpp253
BOOL ZIPPLATFORM:FlushFile(int iDes)
bool ZipPlatform::FlushFile(int iDes)
{
	return fsync(iDes) == 0;
}
ZipPlatform_lnx.cpp258
INTPTR_T ZIPPLATFORM:GetFileSystemHandle(int iDes)
intptr_t ZipPlatform::GetFileSystemHandle(int iDes)
{
        return iDes;
}
ZipPlatform_lnx.cpp263
ZipPlatform_win.cpp
TypeFunctionSourceLine
ULONGLONG ZIPPLATFORM:GetDeviceFreeSpace(LPCTSTR lpszPath)
ULONGLONG ZipPlatform::GetDeviceFreeSpace(LPCTSTR lpszPath)
{
	ULONGLONG uFreeBytesToCaller = 0, uTotalBytes = 0, uFreeBytes = 0;

	CZipPathComponent zpc (lpszPath);
	CZipString szDrive = zpc.GetFileDrive();

	if (!GetDiskFreeSpaceEx(
		szDrive,
		(PULARGE_INTEGER)&uFreeBytesToCaller,
		(PULARGE_INTEGER)&uTotalBytes,
        (PULARGE_INTEGER)&uFreeBytes))

	{
		CZipPathComponent::AppendSeparator(szDrive); // in spite of what is written in MSDN it is sometimes needed (on fixed disks)
		if (!GetDiskFreeSpaceEx(
			szDrive,
			(PULARGE_INTEGER)&uFreeBytesToCaller,
			(PULARGE_INTEGER)&uTotalBytes,
			(PULARGE_INTEGER)&uFreeBytes))	
				return 0;
	}
	return uFreeBytes;
}
ZipPlatform_win.cpp50
CZIPSTRING ZIPPLATFORM:GetTmpFileName(LPCTSTR lpszPath, ZIP_SIZE_TYPE uSizeNeeded)
CZipString ZipPlatform::GetTmpFileName(LPCTSTR lpszPath, ZIP_SIZE_TYPE uSizeNeeded)
{
		TCHAR empty[] = _T("");
		CZipString tempPath;
		bool bCheckTemp = true;
		if (lpszPath)
		{
			tempPath = lpszPath;
			bCheckTemp = GetDeviceFreeSpace(tempPath) < uSizeNeeded;

		}
		if (bCheckTemp)
		{
			DWORD size = GetTempPath(0, empty);
			if (size == 0)
				return (CZipString)empty;
		
			GetTempPath(size, tempPath.GetBuffer(size));
			tempPath.ReleaseBuffer();
			if (GetDeviceFreeSpace(tempPath) < uSizeNeeded)
			{
				if (!GetCurrentDirectory(tempPath) || GetDeviceFreeSpace(tempPath) < uSizeNeeded)
					return (CZipString)empty;
			}
		}
		CZipString tempName;
		if (!GetTempFileName(tempPath, _T("ZAR"), 0, tempName.GetBuffer(_MAX_PATH)))
			return (CZipString)empty;
		tempName.ReleaseBuffer();
		return tempName;
}
ZipPlatform_win.cpp75
BOOL ZIPPLATFORM:GetCurrentDirectory(CZipString& sz)
bool ZipPlatform::GetCurrentDirectory(CZipString& sz)
{
	DWORD i = ::GetCurrentDirectory(0, NULL);
	if (!i)
		return false;
	TCHAR* pBuf = new TCHAR[i];
	bool b = true;
	if (!::GetCurrentDirectory(i, pBuf))
		b = false;
	else
		sz = pBuf;
	delete[] pBuf;
	return b;
}
ZipPlatform_win.cpp108
BOOL ZIPPLATFORM:SetFileAttr(LPCTSTR lpFileName, DWORD uAttr)
bool ZipPlatform::SetFileAttr(LPCTSTR lpFileName, DWORD uAttr)
{
	return ::SetFileAttributes(lpFileName, uAttr) != 0;
}
ZipPlatform_win.cpp123
BOOL ZIPPLATFORM:GetFileAttr(LPCTSTR lpFileName, DWORD& uAttr)
bool ZipPlatform::GetFileAttr(LPCTSTR lpFileName, DWORD& uAttr)
{
	// not using MFC due to MFC bug (attr is one byte there)
	DWORD temp = ::GetFileAttributes(lpFileName);
	if (temp == INVALID_FILE_ATTRIBUTES)
		return false;
	uAttr = temp;
	return true;
	
}
ZipPlatform_win.cpp128
BOOL ZIPPLATFORM:GetFileModTime(LPCTSTR lpFileName, time_t & ttime)
bool ZipPlatform::GetFileModTime(LPCTSTR lpFileName, time_t & ttime)
{
#ifndef __BORLANDC__
    struct _stat st;
    if (_tstat(lpFileName, &st) != 0)
#else
    struct stat st;
    if (stat(lpFileName, &st) != 0)
#endif
	return false;
	ttime = st.st_mtime;
	if (ttime == (time_t)-1)
	{
		ttime = time(NULL);
		return false;
	}
	else
		return true;
}
ZipPlatform_win.cpp139
BOOL ZIPPLATFORM:SetFileModTime(LPCTSTR lpFileName, time_t ttime)
bool ZipPlatform::SetFileModTime(LPCTSTR lpFileName, time_t ttime)
{
	struct _utimbuf ub;
	ub.actime = time(NULL);
	ub.modtime = ttime == -1 ? time(NULL) : ttime; // if wrong file time, set it to the current
	return _tutime(lpFileName, &ub) == 0;
}
ZipPlatform_win.cpp159
BOOL ZIPPLATFORM:ChangeDirectory(LPCTSTR lpDirectory)
bool ZipPlatform::ChangeDirectory(LPCTSTR lpDirectory)
{
	return _tchdir(lpDirectory) == 0; // returns 0 if ok
}
ZipPlatform_win.cpp167
INT ZIPPLATFORM:FileExists(LPCTSTR lpszName)
int ZipPlatform::FileExists(LPCTSTR lpszName)
{
#ifndef __BORLANDC__
	#if _MSC_VER >= 1400
	if (_taccess_s(lpszName, 0) == 0)
	#else
	if (_taccess(lpszName, 0) == 0)
	#endif
#else
	#ifdef _UNICODE
	if (_waccess(lpszName, 0) == 0)
	#else
	if (access(lpszName, 0) == 0)
	#endif
#endif
	{
		if (DirectoryExists(lpszName))
			return -1;
		return 1;
	}
	else
		return 0;

}
ZipPlatform_win.cpp172
ZIPINLINE BOOL ZIPPLATFORM:IsDriveRemovable(LPCTSTR lpszFilePath)
ZIPINLINE  bool ZipPlatform::IsDriveRemovable(LPCTSTR lpszFilePath)
{
	CZipPathComponent zpc(lpszFilePath);
	return ::GetDriveType(zpc.GetFileDrive()) == DRIVE_REMOVABLE;
}
ZipPlatform_win.cpp197
ZIPINLINE BOOL ZIPPLATFORM:SetVolLabel(LPCTSTR lpszPath, LPCTSTR lpszLabel)
ZIPINLINE  bool ZipPlatform::SetVolLabel(LPCTSTR lpszPath, LPCTSTR lpszLabel)
{
	CZipPathComponent zpc(lpszPath);
	CZipString szDrive = zpc.GetFileDrive();
	CZipPathComponent::AppendSeparator(szDrive);
	return ::SetVolumeLabel(szDrive, lpszLabel) != 0;
}
ZipPlatform_win.cpp203
ZIPINLINE VOID ZIPPLATFORM:AnsiOem(CZipAutoBuffer& buffer, bool bAnsiToOem)
ZIPINLINE void ZipPlatform::AnsiOem(CZipAutoBuffer& buffer, bool bAnsiToOem)
{
#ifdef ZIP_USES_SAFE_WINDOWS_API
	UINT cpIn, cpOut;
	if (bAnsiToOem)
	{
		cpIn = CP_ACP;
		cpOut = CP_OEMCP;
	}
	else
	{
		cpIn = CP_OEMCP;
		cpOut = CP_ACP;
	}

	CZipAutoBuffer interBuffer;

	int size = buffer.GetSize();
	// iLen doesn't include terminating character
	int iLen = MultiByteToWideChar(cpIn, MB_PRECOMPOSED, buffer, size, NULL, 0);
	if (iLen <= 0)
		return;
	interBuffer.Allocate(iLen * sizeof(wchar_t));
	LPWSTR lpszWide = (LPWSTR)(char*)interBuffer;
	iLen = MultiByteToWideChar(cpIn, MB_PRECOMPOSED, buffer, size, lpszWide, iLen);
	ASSERT(iLen != 0);

	// iLen does not include terminating character
	size = WideCharToMultiByte(cpOut, 0, lpszWide, iLen, NULL, 0, NULL, NULL);
	if (size <= 0)
		return;
	buffer.Allocate(size);
	size = WideCharToMultiByte(cpOut, 0, lpszWide, iLen, buffer, size, NULL, NULL);
	ASSERT(size != 0);
#else
	if (bAnsiToOem)
		CharToOemBuffA(buffer, buffer, buffer.GetSize());
	else
		OemToCharBuffA(buffer, buffer, buffer.GetSize());
#endif
}
ZipPlatform_win.cpp211
ZIPINLINE BOOL ZIPPLATFORM:RemoveFile(LPCTSTR lpszFileName, bool bThrow)
ZIPINLINE  bool ZipPlatform::RemoveFile(LPCTSTR lpszFileName, bool bThrow)
{
	if (!::DeleteFile((LPTSTR)lpszFileName))
		if (bThrow)
			CZipException::Throw(CZipException::notRemoved, lpszFileName);
		else 
			return false;
	return true;

}
ZipPlatform_win.cpp253
ZIPINLINE BOOL ZIPPLATFORM:RenameFile( LPCTSTR lpszOldName, LPCTSTR lpszNewName, bool bThrow)
ZIPINLINE  bool ZipPlatform::RenameFile( LPCTSTR lpszOldName, LPCTSTR lpszNewName, bool bThrow)
{
	if (!::MoveFile((LPTSTR)lpszOldName, (LPTSTR)lpszNewName))
		if (bThrow)
			CZipException::Throw(CZipException::notRenamed, lpszOldName);
		else 
			return false;
	return true;

}
ZipPlatform_win.cpp263
ZIPINLINE BOOL ZIPPLATFORM:IsDirectory(DWORD uAttr)
ZIPINLINE  bool ZipPlatform::IsDirectory(DWORD uAttr)
{
	return (uAttr & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
ZipPlatform_win.cpp274
ZIPINLINE BOOL ZIPPLATFORM:CreateDirectory(LPCTSTR lpDirectory)
ZIPINLINE  bool ZipPlatform::CreateDirectory(LPCTSTR lpDirectory)
{
	return ::CreateDirectory(lpDirectory, NULL) != 0;
}
ZipPlatform_win.cpp279
ZIPINLINE DWORD ZIPPLATFORM:GetDefaultAttributes()
ZIPINLINE  DWORD ZipPlatform::GetDefaultAttributes()
{
	return FILE_ATTRIBUTE_ARCHIVE;
}
ZipPlatform_win.cpp284
ZIPINLINE DWORD ZIPPLATFORM:GetDefaultDirAttributes()
ZIPINLINE  DWORD ZipPlatform::GetDefaultDirAttributes()
{
	return FILE_ATTRIBUTE_DIRECTORY;
}
ZipPlatform_win.cpp289
ZIPINLINE INT ZIPPLATFORM:GetSystemID()
ZIPINLINE  int ZipPlatform::GetSystemID()
{
	return ZipCompatibility::zcDosFat;
}
ZipPlatform_win.cpp294
ZIPINLINE BOOL ZIPPLATFORM:GetSystemCaseSensitivity()
ZIPINLINE bool ZipPlatform::GetSystemCaseSensitivity()
{
	return false;
}
ZipPlatform_win.cpp299
INT ZIPPLATFORM:WideToMultiByte(LPCWSTR lpszIn, CZipAutoBuffer &szOut, UINT uCodePage)
int ZipPlatform::WideToMultiByte(LPCWSTR lpszIn, CZipAutoBuffer &szOut, UINT uCodePage)
{
	size_t wideLen = wcslen(lpszIn);
	if (wideLen == 0)
	{
		szOut.Release();
		return 0;
	}

	// iLen does not include terminating character
	int iLen = WideCharToMultiByte(uCodePage, 0, lpszIn, (int)wideLen, szOut, 
		0, NULL, NULL);
	if (iLen > 0)
	{
		szOut.Allocate(iLen, true);
		iLen = WideCharToMultiByte(uCodePage, 0, lpszIn , (int)wideLen, szOut, 
			iLen, NULL, NULL);
		ASSERT(iLen != 0);
	}
	else // here it means error
	{
		szOut.Release();
		iLen --;
	}
	return iLen;

}
ZipPlatform_win.cpp305
INT ZIPPLATFORM:MultiByteToWide(const CZipAutoBuffer &szIn, CZipString& szOut, UINT uCodePage)
int ZipPlatform::MultiByteToWide(const CZipAutoBuffer &szIn, CZipString& szOut, UINT uCodePage)
{
	int singleLen = szIn.GetSize();
	// iLen doesn't include terminating character
	DWORD dwFlags = uCodePage <= CP_OEMCP ? MB_PRECOMPOSED : 0;
	int iLen = MultiByteToWideChar(uCodePage, dwFlags, szIn.GetBuffer(), singleLen, NULL, 0);
	if (iLen > 0)
	{
		iLen = MultiByteToWideChar(uCodePage, dwFlags, szIn.GetBuffer(), singleLen, 
			szOut.GetBuffer(iLen) , iLen);
		szOut.ReleaseBuffer(iLen);
		ASSERT(iLen != 0);
	}
	else
	{
		szOut.Empty();
		iLen --; // return -1
	}
	return iLen;
}
ZipPlatform_win.cpp332
BOOL ZIPPLATFORM:TruncateFile(int iDes, ULONGLONG uSize)
bool ZipPlatform::TruncateFile(int iDes, ULONGLONG uSize)
{	
#if (_MSC_VER >= 1400)
	return _chsize_s(iDes, uSize) == 0;
#else
	if (uSize <= LONG_MAX)
		return chsize(iDes, (LONG)uSize) == 0;
	else if (uSize > _I64_MAX)
		CZipException::Throw(CZipException::tooBigSize);
	else
	{
		HANDLE handle = (HANDLE)GetFileSystemHandle(iDes);
		ULARGE_INTEGER li;
		li.QuadPart = uSize;
		li.LowPart = SetFilePointer(handle, li.LowPart, (LONG*)&li.HighPart, FILE_BEGIN);
		if (li.LowPart == UINT_MAX && GetLastError() != NO_ERROR)
			return false;
		return SetEndOfFile(handle) != 0;
	}
	return false; // for the compiler
#endif

}
ZipPlatform_win.cpp364
INT ZIPPLATFORM:OpenFile(LPCTSTR lpszFileName, UINT iMode, int iShareMode)
int ZipPlatform::OpenFile(LPCTSTR lpszFileName, UINT iMode, int iShareMode)
{
	switch (iShareMode)
	{
	case (CZipFile::shareDenyWrite & CZipFile::shareDenyRead):
		iShareMode = SH_DENYRW;
		break;
	case (CZipFile::shareDenyRead):
		iShareMode = SH_DENYRD;
		break;
	case (CZipFile::shareDenyWrite):
		iShareMode = SH_DENYWR;
		break;
	default:
		iShareMode = SH_DENYNO;
	}
#if _MSC_VER >= 1400	
	int handle;
	if (_tsopen_s(&handle, lpszFileName, iMode, iShareMode, S_IREAD | S_IWRITE /*required only when O_CREAT mode*/) != 0)
		return -1;
	else
		return handle;
#else
	return  _tsopen(lpszFileName, iMode, iShareMode, S_IREAD | S_IWRITE /*required only when O_CREAT mode*/);
#endif
	
}
ZipPlatform_win.cpp393
BOOL ZIPPLATFORM:FlushFile(int iDes)
bool ZipPlatform::FlushFile(int iDes)
{
	return _commit(iDes) == 0;
}
ZipPlatform_win.cpp421
INTPTR_T ZIPPLATFORM:GetFileSystemHandle(int iDes)
intptr_t ZipPlatform::GetFileSystemHandle(int iDes)
{
	return _get_osfhandle(iDes);
}
ZipPlatform_win.cpp426
ZipStorage.cpp
TypeFunctionSourceLine
CZIPSTORAGE:CZipStorage()
CZipStorage::CZipStorage()
{
	Initialize();
}
ZipStorage.cpp24
VOID CZIPSTORAGE:Initialize()
void CZipStorage::Initialize()
{	
	m_pSplitChangeVolumeFunc = m_pSpanChangeVolumeFunc = m_pChangeVolumeFunc = NULL;
	m_iWriteBufferSize = 65536;	
	m_pFile = NULL;
	m_szSplitExtension = _T("zip");
	m_iLocateBufferSize = 32768;
	m_uBytesBeforeZip = 0;
	m_uCurrentVolume = ZIP_VOLUME_NUMBER_UNSPECIFIED;
	m_szArchiveName.Empty();
}
ZipStorage.cpp29
CZIPSTORAGE::CZipStorage()
CZipStorage::~CZipStorage()
{

}
ZipStorage.cpp41
DWORD CZIPSTORAGE:Read(void *pBuf, DWORD iSize, bool bAtOnce)
DWORD CZipStorage::Read(void *pBuf, DWORD iSize, bool bAtOnce)
{
	if (iSize == 0)
		return 0;
	DWORD iRead;
	for(;;)
	{
		iRead = m_pFile->Read(pBuf, iSize);
		if (!iRead)
		{
			if (IsSegmented())
				ChangeVolume();
			else
				ThrowError(CZipException::badZipFile);
		}
		else
			break;
	}

	if (iRead == iSize)
		return iRead;
	else if (bAtOnce || !IsSegmented())
		ThrowError(CZipException::badZipFile);

	while (iRead < iSize)
	{
		ChangeVolume();
		UINT iNewRead = m_pFile->Read((char*)pBuf + iRead, iSize - iRead);
		if (!iNewRead && iRead < iSize)
			ThrowError(CZipException::badZipFile);
		iRead += iNewRead;
	}

	return iRead;
}
ZipStorage.cpp46
VOID CZIPSTORAGE:Open(LPCTSTR lpszPathName, int iMode, ZIP_SIZE_TYPE uVolumeSize)
void CZipStorage::Open(LPCTSTR lpszPathName, int iMode, ZIP_SIZE_TYPE uVolumeSize)
{
	m_uCurrentVolume = ZIP_VOLUME_NUMBER_UNSPECIFIED;
	m_pWriteBuffer.Allocate(m_iWriteBufferSize); 
	m_uBytesInWriteBuffer = 0;
	m_bNewSegm = false;
	m_pFile = &m_internalfile;
	m_bInMemory = false;
	m_szArchiveName = lpszPathName;
	m_pChangeVolumeFunc = NULL;

	if (iMode ==  CZipArchive::zipCreate || iMode ==  CZipArchive::zipCreateSegm
		|| iMode ==  CZipArchive::zipCreateAppend) // create new archive
	{
		m_bReadOnly = false;
		m_uCurrentVolume = 0;
		if (iMode ==  CZipArchive::zipCreate || iMode ==  CZipArchive::zipCreateAppend)
		{
			m_iSegmMode = noSegments;
			OpenFile(lpszPathName, (iMode ==  CZipArchive::zipCreate ? CZipFile::modeCreate : CZipFile::modeNoTruncate) | CZipFile::modeReadWrite);
		}
		else // create a segmented archive
		{
			m_bNewSegm = true;
			m_uBytesWritten = 0;
			if (uVolumeSize == ZIP_AUTODETECT_VOLUME_SIZE) // spanned archive
			{
				if (!m_pSpanChangeVolumeFunc)
					ThrowError(CZipException::noCallback);
				if (!ZipPlatform::IsDriveRemovable(lpszPathName))
					ThrowError(CZipException::nonRemovable);
				m_iSegmMode = spannedArchive;
				m_pChangeVolumeFunc = m_pSpanChangeVolumeFunc;
			}
			else
			{
				m_uSplitData = uVolumeSize;
				m_iSegmMode = splitArchive;
				m_pChangeVolumeFunc = m_pSplitChangeVolumeFunc;
			}

			NextVolume(4);
			Write(m_gszExtHeaderSignat, 4, true);
		}
	}
	else // open existing
	{
		m_bReadOnly = iMode ==  CZipArchive::zipOpenReadOnly;
		OpenFile(lpszPathName, CZipFile::modeNoTruncate |
			(m_bReadOnly ? CZipFile::modeRead : CZipFile::modeReadWrite));
		// m_uData and m_iSegmMode are automatically set during reading the central dir
		m_iSegmMode = uVolumeSize == 0 ? suggestedAuto : suggestedSplit;
	}
		
}
ZipStorage.cpp82
VOID CZIPSTORAGE:Open(CZipAbstractFile& af, int iMode)
void CZipStorage::Open(CZipAbstractFile& af, int iMode)
{
	m_pWriteBuffer.Allocate(m_iWriteBufferSize); 
	m_uBytesInWriteBuffer = 0;
	m_bNewSegm = false;
	m_pFile = ⁡
	m_bInMemory = true;

	if (iMode ==  CZipArchive::zipCreate || iMode ==  CZipArchive::zipCreateAppend)
	{
		m_uCurrentVolume = 0;
		m_iSegmMode = noSegments;
		if (iMode ==  CZipArchive::zipCreate)
			af.SetLength(0);
		else
			af.SeekToEnd();
	}
	else // open existing
	{
		af.SeekToBegin();
		m_iSegmMode = suggestedAuto;
	}
}
ZipStorage.cpp139
VOID CZIPSTORAGE:ChangeVolume(ZIP_VOLUME_TYPE uNumber)
void CZipStorage::ChangeVolume(ZIP_VOLUME_TYPE uNumber)
{
	if (uNumber == m_uCurrentVolume || m_iSegmMode == noSegments) // the second condition may happen in some bad archives
		return;

	m_uCurrentVolume = uNumber;
	OpenFile(IsSpanned() ? ChangeSpannedRead() : ChangeSplitRead(),
		CZipFile::modeNoTruncate | CZipFile::modeRead);
}
ZipStorage.cpp164
VOID CZIPSTORAGE:ThrowError(int err)
void CZipStorage::ThrowError(int err)
{
	CZipException::Throw(err, m_pFile->GetFilePath());
}
ZipStorage.cpp174
BOOL CZIPSTORAGE:OpenFile(LPCTSTR lpszName, UINT uFlags, bool bThrow)
bool CZipStorage::OpenFile(LPCTSTR lpszName, UINT uFlags, bool bThrow)
{
	return m_pFile->Open(lpszName, uFlags | CZipFile::shareDenyWrite, bThrow);
}
ZipStorage.cpp179
CZIPSTRING CZIPSTORAGE:ChangeSpannedRead()
CZipString CZipStorage::ChangeSpannedRead()
{
	CZipString szTemp = m_pFile->GetFilePath();
	m_pFile->Close();
	CallCallback(0, CZipSegmCallback::scVolumeNeededForRead, szTemp);
	return szTemp;
}
ZipStorage.cpp185
CZIPSTRING CZIPSTORAGE:ChangeSplitRead()
CZipString CZipStorage::ChangeSplitRead()
{
	bool lastPart = (ZIP_SIZE_TYPE)m_uCurrentVolume == m_uSplitData;
	CZipString szTemp = GetSplitVolumeName(lastPart);
	if (m_pChangeVolumeFunc)
	{
		int iCode = CZipSegmCallback::scVolumeNeededForRead;
		for(;;)
		{
			CallCallback(lastPart ? ZIP_SPLIT_LAST_VOLUME : 0, iCode, szTemp);
			if (ZipPlatform::FileExists(m_pChangeVolumeFunc->m_szExternalFile))
			{
				szTemp = m_pChangeVolumeFunc->m_szExternalFile;
				break;
			}
			else
				iCode = CZipSegmCallback::scFileNotFound;
		}
	}
	m_pFile->Close();
	return szTemp;
}
ZipStorage.cpp193
CZIPSTRING CZIPSTORAGE:RenameLastFileInSplitArchive()
CZipString CZipStorage::RenameLastFileInSplitArchive()
{
	ASSERT(IsSplit());
		// give to the last volume the zip extension
	CZipString szFileName = m_pFile->GetFilePath();
	CZipString szNewFileName = GetSplitVolumeName(true);
	if (m_pChangeVolumeFunc)
	{
		int code = CZipSegmCallback::scVolumeNeededForWrite;
		for(;;)
		{
			CallCallback(ZIP_SPLIT_LAST_VOLUME, code, szNewFileName);
			szNewFileName = m_pChangeVolumeFunc->m_szExternalFile;
			if (ZipPlatform::FileExists(szNewFileName))
				code = CZipSegmCallback::scFileNameDuplicated;
			else
				break;
		}
	}
	if (!m_bInMemory)
	{
		m_pFile->Flush();
		m_pFile->Close();
	}
	if (!m_pChangeVolumeFunc && ZipPlatform::FileExists(szNewFileName))
		ZipPlatform::RemoveFile(szNewFileName);
	ZipPlatform::RenameFile(szFileName, szNewFileName);
	return szNewFileName;
}
ZipStorage.cpp216
CZIPSTRING CZIPSTORAGE:Close(bool bAfterException)
CZipString CZipStorage::Close(bool bAfterException)
{
	bool bClose = true;
	CZipString sz;
	if (!bAfterException)
	{
		Flush();
		if (IsSplit() && m_bNewSegm)
		{
			sz = RenameLastFileInSplitArchive();
			bClose = false;// already closed in RenameLastFileInSplitArchive
		}
	}
	if (sz.IsEmpty())
		sz = m_pFile->GetFilePath();
	if (bClose && !m_bInMemory)
	{
		if (!bAfterException)
			FlushFile();
		m_pFile->Close();
	}

	m_pWriteBuffer.Release();
	m_uCurrentVolume = ZIP_VOLUME_NUMBER_UNSPECIFIED;
	m_iSegmMode = noSegments;
	m_pFile = NULL;
	m_uBytesBeforeZip = 0;
	return sz;
}

CZipString CZipStorage::GetSplitVolumeName(bool bLast) const
{
	CZipString szFilePath = m_szArchiveName;
	CZipPathComponent zpc(szFilePath);
	CZipString szExt;
	if (bLast)
		szExt = m_szSplitExtension;
	else
	{
		DWORD vol = m_uCurrentVolume + 1;
		if (vol < 100)
			szExt.Format(_T("z%.2u"), vol);
		else
			szExt.Format(_T("z%u"), vol);
	}
	zpc.SetExtension(szExt);
	return zpc.GetFullPath();
}
ZipStorage.cpp246
VOID CZIPSTORAGE:NextVolume(ZIP_SIZE_TYPE uNeeded)
void CZipStorage::NextVolume(ZIP_SIZE_TYPE uNeeded)
{
	Flush();
	ASSERT(m_iSegmMode != noSegments);
	bool bSpan = IsSpanned();
	if (m_uBytesWritten)
	{
		m_uBytesWritten = 0;
		m_uCurrentVolume++;
		ZIP_VOLUME_TYPE uMaxVolumes = (ZIP_VOLUME_TYPE)(bSpan ? 999 : 0xFFFF);
		if (m_uCurrentVolume >= uMaxVolumes) // m_uCurrentVolume is a zero-based index
			ThrowError(CZipException::tooManyVolumes);
	} 

	CZipString szFileName;
	
	if (bSpan)
		szFileName  = m_szArchiveName;
	else
		szFileName =  GetSplitVolumeName(false);

	if (!m_pFile->IsClosed())
	{
		m_pFile->Flush();
		m_pFile->Close();
	}

	if (m_pChangeVolumeFunc)
	{
		int iCode = CZipSegmCallback::scVolumeNeededForWrite;
		for(;;)
		{
			CallCallback(uNeeded, iCode, szFileName);
			if (!bSpan)
				// allow the user to change the filename
				szFileName = m_pChangeVolumeFunc->m_szExternalFile;

			if (ZipPlatform::FileExists(szFileName))
				iCode = CZipSegmCallback::scFileNameDuplicated;
			else
			{
				if (bSpan)
				{
					CZipString label;
					label.Format(_T("pkback# %.3d"), m_uCurrentVolume + 1);
					if (!ZipPlatform::SetVolLabel(szFileName, label))
					{
						iCode = CZipSegmCallback::scCannotSetVolLabel;
						continue;
					}
				}					
				
				if (OpenFile(szFileName, CZipFile::modeCreate | CZipFile::modeReadWrite, false))
					break;
				else
					iCode = CZipSegmCallback::scFileCreationFailure;
			}

		}
		m_uCurrentVolSize = bSpan ? GetFreeVolumeSpace() : m_uSplitData;
	}
	else
	{
		if (bSpan)
			ThrowError(CZipException::internalError);
		m_uCurrentVolSize = m_uSplitData;
		OpenFile(szFileName, CZipFile::modeCreate | CZipFile::modeReadWrite);
	}
}
ZipStorage.cpp295
VOID CZIPSTORAGE:CallCallback(ZIP_SIZE_TYPE uNeeded, int iCode, CZipString szTemp)
void CZipStorage::CallCallback(ZIP_SIZE_TYPE uNeeded, int iCode, CZipString szTemp)
{
	if (!m_pChangeVolumeFunc)
		ThrowError(CZipException::internalError);
	m_pChangeVolumeFunc->m_szExternalFile = szTemp;
	m_pChangeVolumeFunc->m_uVolumeNeeded = (ZIP_VOLUME_TYPE)(m_uCurrentVolume + 1);
	m_pChangeVolumeFunc->m_iCode = iCode; 
	if (!m_pChangeVolumeFunc->Callback(uNeeded))
		CZipException::Throw(CZipException::aborted, szTemp);
}

ZIP_SIZE_TYPE CZipStorage::GetFreeVolumeSpace() const
{
	ASSERT (IsSpanned());
	CZipString szTemp = m_pFile->GetFilePath();
	if (szTemp.IsEmpty()) // called once when creating a segmented archive
		return 0;
	else
	{
		CZipPathComponent zpc(szTemp);
        ULONGLONG ret = ZipPlatform::GetDeviceFreeSpace(zpc.GetFilePath());
        if (ret > (ZIP_SIZE_TYPE)(-1))
                return (ZIP_SIZE_TYPE)(-1);
        else
                return (ZIP_SIZE_TYPE)ret;
	}
}
ZipStorage.cpp365
VOID CZIPSTORAGE:UpdateSegmMode(ZIP_VOLUME_TYPE uLastDisk)
void CZipStorage::UpdateSegmMode(ZIP_VOLUME_TYPE uLastDisk)
{
	m_uCurrentVolume = uLastDisk;
	if (uLastDisk)
	{
		// segmentation detected
		CZipString szFilePath = m_pFile->GetFilePath();
		if (m_iSegmMode == suggestedAuto)
			m_iSegmMode = ZipPlatform::IsDriveRemovable(szFilePath) ? 
				spannedArchive : splitArchive;
		else
		{
			ASSERT(m_iSegmMode == suggestedSplit);
			m_iSegmMode = splitArchive;
		}

		if (IsSpanned())
		{
			if (!m_pSpanChangeVolumeFunc)
				ThrowError(CZipException::noCallback);
			m_pChangeVolumeFunc = m_pSpanChangeVolumeFunc;
		}
		else /*if (IsSplit())*/
		{
			m_uSplitData = uLastDisk; // volume with .zip extension ( the last one)
			m_pChangeVolumeFunc = m_pSplitChangeVolumeFunc;
		}
		CZipPathComponent zpc(szFilePath);
		m_szSplitExtension = zpc.GetFileExt();
		m_pWriteBuffer.Release(); // no need for this in this case
	}
	else 
		m_iSegmMode = noSegments;

}
ZipStorage.cpp394
ZIP_SIZE_TYPE CZIPSTORAGE:AssureFree(ZIP_SIZE_TYPE uNeeded)
ZIP_SIZE_TYPE CZipStorage::AssureFree(ZIP_SIZE_TYPE uNeeded)
{
	ZIP_SIZE_TYPE uFree;
	while ((uFree = VolumeLeft()) < uNeeded)
	{
		if (IsSplit() && !m_uBytesWritten && !m_uBytesInWriteBuffer)
			// in the splitArchive mode, if the size of the archive is less 
			// than the size of the packet to be written at once,
			// increase once the size of the volume
			m_uCurrentVolSize = uNeeded;
		else
			NextVolume(uNeeded);
	}
	return uFree;
}
ZipStorage.cpp430
VOID CZIPSTORAGE:Write(const void *pBuf, DWORD iSize, bool bAtOnce)
void CZipStorage::Write(const void *pBuf, DWORD iSize, bool bAtOnce)
{
	if (!IsSegmented())
		WriteInternalBuffer((char*)pBuf, iSize);
	else
	{
		// if not at once, one byte is enough free space
		DWORD iNeeded = bAtOnce ? iSize : 1; 
		DWORD uTotal = 0;

		while (uTotal < iSize)
		{			
			ZIP_SIZE_TYPE uFree = AssureFree(iNeeded);
			DWORD uLeftToWrite = iSize - uTotal;
			DWORD uToWrite = uFree < uLeftToWrite ? (DWORD)uFree : uLeftToWrite;
			WriteInternalBuffer((char*)pBuf + uTotal, uToWrite);
			if (bAtOnce)
				return;
			else
				uTotal += uToWrite;
		}

	}
}
ZipStorage.cpp446
VOID CZIPSTORAGE:WriteInternalBuffer(const char *pBuf, DWORD uSize)
void CZipStorage::WriteInternalBuffer(const char *pBuf, DWORD uSize)
{
	DWORD uWritten = 0;
	while (uWritten < uSize)
	{
		DWORD uFreeInBuffer = GetFreeInBuffer();
		if (uFreeInBuffer == 0)
		{
			Flush();
			uFreeInBuffer = m_pWriteBuffer.GetSize();
		}
		DWORD uLeftToWrite = uSize - uWritten;
		DWORD uToCopy = uLeftToWrite < uFreeInBuffer ? uLeftToWrite : uFreeInBuffer;
		memcpy((char*)m_pWriteBuffer + m_uBytesInWriteBuffer, pBuf + uWritten, uToCopy);
		uWritten += uToCopy;
		m_uBytesInWriteBuffer += uToCopy;
	}
}

ZIP_SIZE_TYPE CZipStorage::VolumeLeft() const
{
	// for spanned archives m_uCurrentVolSize is updated after each flush()
	ZIP_SIZE_TYPE uBytes = m_uBytesInWriteBuffer + (IsSpanned() ? 0 : m_uBytesWritten);	
	return uBytes > m_uCurrentVolSize ? 0 : m_uCurrentVolSize - uBytes;
}
ZipStorage.cpp472
VOID CZIPSTORAGE:Flush()
void CZipStorage::Flush()
{	
	if (m_uBytesInWriteBuffer)
	{
		m_pFile->Write(m_pWriteBuffer, m_uBytesInWriteBuffer);
		if (m_iSegmMode != noSegments)
			m_uBytesWritten += m_uBytesInWriteBuffer;
		m_uBytesInWriteBuffer = 0;
	}
	if (IsSpanned()) 
		// after writing it is difficult to predict the free space due to 
		// not completly written clusters, write operation may start from a new cluster
		m_uCurrentVolSize = GetFreeVolumeSpace();
	
}
ZipStorage.cpp498
ZIP_FILE_USIZE CZIPSTORAGE:LocateSignature(char* szSignature, ZIP_SIZE_TYPE uMaxDepth)
ZIP_FILE_USIZE CZipStorage::LocateSignature(char* szSignature, ZIP_SIZE_TYPE uMaxDepth)
{
	const int recordSize = 4;
	CZipAutoBuffer buffer(m_iLocateBufferSize);
	ZIP_FILE_USIZE uFileLength = m_pFile->GetLength();
	ZIP_SIZE_TYPE max = (ZIP_SIZE_TYPE)(uFileLength < uMaxDepth ? uFileLength : uMaxDepth);
	ZIP_SIZE_TYPE position = (ZIP_SIZE_TYPE)(uFileLength - m_pFile->GetPosition());
	int offset = 0;
	int leftToFind = recordSize - 1;
	int toRead = m_iLocateBufferSize;
	bool found = false; // for fast checking if leftToFind needs resetting
	while ( position < max )
	{
		position += toRead;
		if ( position > max )
		{
			int diff = (int) ( position - max );
			toRead -= diff;
			offset = diff;
			position = max;
		}
		Seek(position, seekFromEnd);	
		int actuallyRead = m_pFile->Read((char*)buffer + offset, toRead);
		if (actuallyRead != toRead)
			ThrowError(CZipException::badZipFile);
		int pos = m_iLocateBufferSize - 1;
		while ( pos >= offset )
		{
			if ( buffer[pos] == szSignature[leftToFind] )
			{
				if ( leftToFind == 0 )
					return (ZIP_FILE_USIZE)(uFileLength - ( position - ( pos - offset ) ));
				if ( !found )
					found = true;
				leftToFind--;
				pos--;
			}
			else if ( found )
			{
				leftToFind = recordSize - 1;
				found = false;
				// do not decrease position, the current pos may be the first to find
			}
			else
				pos--;
		}
	}
	return SignatureNotFound;
}
ZipStorage.cpp514
ULONGLONG CZIPSTORAGE:Seek(ULONGLONG lOff, SeekType iSeekType)
ULONGLONG CZipStorage::Seek(ULONGLONG lOff, SeekType iSeekType)
{	
	if (iSeekType == seekCurrent)
	{
		ZIP_SIZE_TYPE uPosition = (ZIP_SIZE_TYPE)m_pFile->GetPosition();
		if (IsSegmented() == -1)
		{
			ZIP_FILE_USIZE uLength = m_pFile->GetLength();
			while (uPosition + lOff >= uLength)
			{
				ZIP_SIZE_TYPE uCanSeek = (ZIP_SIZE_TYPE)(uLength - uPosition);
				lOff -= uCanSeek;
				ChangeVolume();
				uPosition = 0;
				uLength = m_pFile->GetLength();
			}
			return lOff > 0 ? m_pFile->Seek((ZIP_FILE_USIZE)lOff) : 0;
		}
		else
			return m_pFile->Seek((ZIP_FILE_SIZE)lOff, CZipAbstractFile::current);			
	}
	else
	{
		if (m_uCurrentVolume == 0 && m_uBytesBeforeZip > 0)
			lOff += m_uBytesBeforeZip;
		return m_pFile->Seek((ZIP_FILE_USIZE)lOff, iSeekType == seekFromBeginning);
	}
}
ZipStorage.cpp564
VOID CZIPSTORAGE:FinalizeSegm()
void CZipStorage::FinalizeSegm()
{
	ASSERT(IsSegmented() == 1); // spanned archive in creation
	ASSERT(!m_bInMemory);

	CZipString szFileName;
	if (IsSplit() && m_bNewSegm)
		szFileName = RenameLastFileInSplitArchive();
	else
	{
		szFileName = m_pFile->GetFilePath();
		// the file is already closed
		m_pFile->Close();
	}
	m_bNewSegm = false;
	if (m_uCurrentVolume == 0) // one-volume segmented archive was converted to normal archive
		m_iSegmMode = noSegments;
	else
		m_uSplitData = m_uCurrentVolume;
	
	OpenFile(szFileName, CZipFile::modeNoTruncate | (m_iSegmMode == noSegments ? CZipFile::modeReadWrite : CZipFile::modeRead));	
}
ZipStorage.cpp593
ZipString.cpp
TypeFunctionSourceLine
ZIPSTRINGCOMPAREGetCZipStrCompFunc(bool bCaseSensitive, bool bCollate)
ZIPSTRINGCOMPARE GetCZipStrCompFunc(bool bCaseSensitive, bool bCollate)
{
	if (bCollate)
		return bCaseSensitive ? & CZipString::Collate : & CZipString::CollateNoCase;
	else
		return bCaseSensitive ? & CZipString::Compare : & CZipString::CompareNoCase;
}
ZipString.cpp18