CryptDecode with modifier CRYPT_ARCH_ZIP - How to use? - page 6

 
Mikalas:

Unpack standard ZIP files!

(for now, only with one packed file in the archive, later I will make it for several (if needed) )

Thank you. Just what I needed! Michael, you did very good. I will start to work it out in the evening. But MQ's comments are still needed.
 
Mine did not unpack, but gave an internal error (4024)
 
Mikalas:

Unpack standard ZIP files!

(for now, only with one packed file in the archive, later I will make it for several (if needed) )

Attach the zip file you unpacked.
 

so he has his own file?

and I was happy )

ZS: surely even if it's just his own it's already great

 
sanyooooook:

so he has his own file?

and I was happy )

ZS: surely even if it's just his own it's already great

I'll try to do it today.
Files:
GAZR-6_15.zip  1 kb
 

Vasiliy!

Is it necessary to do this or not?

 
Mikalas:

Vasiliy!

Do you have to do it or not?

Not yet. We will see MQ's comments on Monday. It's clear from Alexander's post that it's your zip-archiver. Other archives your code does not unpack:

sanyooooook:
I had trouble decompressing causing an internal error (4024)

s.s. At least the error is different.

Mikalas:

Decompresses standard ZIP files!

(for now, only with one packed file in the archive, then I will do for several (if necessary) )

Another question. What zip archiver did you use, and what parameters did you use (compression ratio, dictionary size).
 
C-4:

Not yet. We will see MQ's comments on Monday. It's clear from Alexander's post that it's your zip-archiver. Other archives your code does not decompress:

s.s. At least the error is different.

Another question. What zip archiver did you use to create the archive, and what parameters did you use (compression ratio, dictionary size).

WinRar with default settings.

I know how to decompress all archives.

But it takes a bit to figure out the 4 bytes of the MQ packer

If needed, I will do it.

MQ may not answer:)

 

The last 4 bytes in the MQ packer are hash or CRC

(service information).

But it's not clear if it's the packed data or the raw data.

We will have to wait for MQ's response

 

In the meantime, it's like this:

//+------------------------------------------------------------------+
//|                                                  Zip_decoder.mqh |
//|                                          Copyright 2015, Mikalas |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
struct ZIP_HEADER
{
  uint   sign;
  ushort a_version;
  ushort bit_flag;
  ushort comp_method;
  ushort last_mod_time;
  ushort last_mod_date;
  int    crc_32;
  uint   pack_size;
  uint   unpack_size;
  ushort fn_len;
  ushort extr_field_len;
};
//
ZIP_HEADER zip_header;
bool f_found;
//+------------------------------------------------------------------+
//| Get entryes in ZIP file                                          |
//+------------------------------------------------------------------+
uint GetEntryesZip( const string file_name, string  &f_names[] )
{
  uint a_cnt = 0;
  uchar array[];
  int handle = FileOpen( file_name, FILE_READ | FILE_BIN );
  if ( handle != INVALID_HANDLE )
  {
    ulong file_size = FileSize( handle );
    if ( file_size > 0 ) 
    {
      while ( FileTell( handle ) < file_size - 4 )
      {
        zip_header.sign = FileReadInteger( handle, 4 );
        
        if ( zip_header.sign == 0x04034b50 )
        {
          a_cnt++;  
          ArrayResize( f_names, a_cnt );
          f_names[ a_cnt - 1] = "";  
          FileSeek( handle, -4, SEEK_CUR );
          FileReadStruct( handle, zip_header ); 
          if ( zip_header.extr_field_len != 0 )
          {
            FileSeek( handle, zip_header.extr_field_len, SEEK_CUR );
          }
          ArrayResize( array, int( zip_header.fn_len ) );
          uint fn_res = FileReadArray( handle, array, 0, int( zip_header.fn_len ) );
          for ( int i = 0; i < int( fn_res ); i++ )
          {
            f_names[a_cnt - 1] += CharToString( array[i] );
          }
          FileSeek( handle, zip_header.pack_size, SEEK_CUR );
        }
      }
    }
    FileClose( handle );
  }
  return( a_cnt );
}
bool GetFile( const string src_name, const string dest_name, const int position, uchar &unp_data[] )
{
  uchar array[];
  uchar key[];
  f_found = false;
  int f_cnt = 0;
  int handle = FileOpen( src_name, FILE_READ | FILE_BIN );
  if ( handle != INVALID_HANDLE )
  {
    ulong file_size = FileSize( handle );
    if ( file_size > 0 ) 
    {
      while ( FileTell( handle ) < file_size - 4 )
      {
        zip_header.sign = FileReadInteger( handle, 4 );
        
        if ( zip_header.sign == 0x04034b50 )
        {
          f_cnt++;
          FileSeek( handle, -4, SEEK_CUR );
          FileReadStruct( handle, zip_header ); 
          if ( zip_header.extr_field_len != 0 )
          {
            FileSeek( handle, zip_header.extr_field_len, SEEK_CUR );
          }
          ArrayResize( array, int( zip_header.fn_len ) );
          
          uint fn_res = FileReadArray( handle, array, 0, int( zip_header.fn_len ) );
          
          string file_name = "";
          for ( int i = 0; i < int( fn_res ); i++ )
          {
            file_name += CharToString( array[i] );
          }  
          if ( ( file_name == dest_name ) && ( position == f_cnt - 1 ) )
          {
            f_found = true;
            ArrayResize( array, int( zip_header.pack_size ) + 6 );
            
            uint ar_res = FileReadArray( handle, array, 2, int( zip_header.pack_size ) );  
            if ( ar_res == uint( zip_header.pack_size ) ) 
            {
              array[0] = 0x78;
              array[1] = 0x5E;
              array[int( zip_header.pack_size ) + 2] = 193;  //Wait MQ !!!!!!!!!!!!!!!!!!!!!!!!!
              array[int( zip_header.pack_size ) + 3] = 12;   //Wait MQ !!!!!!!!!!!!!!!!!!!!!!!!
              array[int( zip_header.pack_size ) + 4] = 31;   //Wait MQ !!!!!!!!!!!!!!!!!!!!!!!!!
              array[int( zip_header.pack_size ) + 5] = 159;  //Wait MQ !!!!!!!!!!!!!!!!!!!!!!!!!!!
              ArrayResize( key, int( zip_header.pack_size ) + 6 );
              for ( int j = 0; j < int( zip_header.pack_size ) + 6; j++ ) key[j] = 0;
              ResetLastError();
              int dec_res = CryptDecode( CRYPT_ARCH_ZIP, array, key, unp_data );
              if ( dec_res == int( zip_header.unpack_size ) )
              {
                FileClose( handle );
                return( true );
              }
              else
              {
                Print( " Ошибка распаковки = ", GetLastError() );
                FileClose( handle );
                return( false );
              }
            } 
            break;
          }
          if ( f_found ) break;  
          FileSeek( handle, zip_header.pack_size, SEEK_CUR );
        }
      }
    }
    FileClose( handle );
  }
  return( false );
}

Calling functions:

//+------------------------------------------------------------------+
//|                                                     Zip_test.mq5 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//
#include "Zip_decoder.mqh";
//
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   string file_name = "Files.zip";
   string file_names[];
   uchar result[];
   uint files_tot = GetEntryesZip( file_name, file_names );
   if ( GetFile( file_name, file_names[1], 1, result ) )
   {
     Print( "Файл распакован. Имя файла = ", file_names[1] );
   }
//---
   return(INIT_SUCCEEDED);
  }

Extracts the 2nd file (GAZR-6.15.dat) in the archive. The archive is made by WinRar with standard settings.

In function GetFile() parameter position (1), it is necessary for exact identification of file in ZIP archive.

Archive can contain files with identical names.

2015.03.29 21:38:05.553 Zip_test (GAZR-6.15,M1) Файл распакован. Имя файла = GAZR-6.15.dat
Files:
Files.zip  1 kb