CryptDecode с модификатором CRYPT_ARCH_ZIP - Как использовать? - страница 6

 
Mikalas:

Распаковывает стандартные ZIP файлы!

(пока, только с одним запакованным файлом в архиве, потом сделаю для нескольких (если надо) ) 

Спасибо. То что нужно! Михаил, Вы молодец. Вечером начну разбираться. Но комментарии MQ по-прежнему необходимы. 
 
 А у меня что-то не распаковал выдал внутреннюю ошибку (4024)
 
Mikalas:

Распаковывает стандартные ZIP файлы!

(пока, только с одним запакованным файлом в архиве, потом сделаю для нескольких (если надо) ) 

Приложите зип-файл, который Вы распаковывали.
 

так у него под свой файл?

а я обрадовался )

ЗЫ: несомненно даже если только свой это уже отлично

 
sanyooooook:

так у него под свой файл?

а я обрадовался )

ЗЫ: несомненно даже если только свой это уже отлично

Постараюсь сделать сегодня
Файлы:
GAZR-6_15.zip  1 kb
 

Василий!

Так нужно делать или нет?

 
Mikalas:

Василий!

Так нужно делать или нет?

Пока нет. Посмотрим комментарии MQ в понедельник. По посту Александра понятно что дело в вашем зип-архиваторе. Другие архивы Ваш код не распаковывает:

sanyooooook:
 А у меня что-то не распаковал выдал внутреннюю ошибку (4024)

з.ы. хорошо хоть ошибка другая. 

 

Mikalas:

Распаковывает стандартные ZIP файлы!

(пока, только с одним запакованным файлом в архиве, потом сделаю для нескольких (если надо) ) 

Еще вопрос. Каким именно зип-архиватором создавали архив, и какие параметры использовали (степень сжатия, размер словаря).
 
C-4:

Пока нет. Посмотрим комментарии MQ в понедельник. По посту Александра понятно что дело в вашем зип-архиваторе. Другие архивы Ваш код не распаковывает:

з.ы. хорошо хоть ошибка другая. 

 

Еще вопрос. Каким именно зип-архиватором создавали архив, и какие параметры использовали (степень сжатия, размер словаря).

WinRar со стандартными настройками.

Я знаю как распаковывать все архивы.

Но для этого нужно немного разобраться с 4-я байтами запаковщика MQ

Если нужно, то сделаю.

MQ могут и не ответить:) 

 

Последние 4 байта в запаковщике MQ - это хеш или CRC 

(служебная информация) 

Но не понятно, запакованных или исходных данных.

Придётся ждать ответа MQ 

 

А пока так:

//+------------------------------------------------------------------+
//|                                                  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 );
}

 

 Вызов функций:

//+------------------------------------------------------------------+
//|                                                     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);
  }

  

Извлекает 2-ой файл (GAZR-6.15.dat) в архиве. Архив сделан WinRar со стандартными настройками.

В функции GetFile() параметр position (1), нужен для точной идентификации файла в ZIP архиве.

В архиве могут быть файлы с ОДИНАКОВЫМИ именами. 

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