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

 

Василий!

Не дождался от Вас ответа. (не знаю успели MQ внедрить изменения в билд 1100 )

Декодер:

//+------------------------------------------------------------------+
//|                                                  Zip_decoder.mq5 |
//|                                          Copyright 2015, Mikalas |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
//
#define uint_size  4
#define hdr_size   2
#define descr_size 12
//
struct ZIP_HEADER
{
  uint   sign;
  ushort a_version;
  ushort bit_flag;
  ushort comp_method;
  ushort last_mod_time;
  ushort last_mod_date;
  uint   crc_32;
  uint   pack_size;
  uint   unpack_size;
  ushort fn_len;
  ushort extr_field_len;
};
//---
struct ZIP_ENTRYES
{
  uint   file_count;
  string zip_fnames[];
  ulong  zip_offsets[];
  uint   pack_size[];
  uint   unpack_size[];
};
struct DATA_DESCRIPTOR
{
  uint crc_32;
  uint pack_size;
  uint unpack_size;
};
//
DATA_DESCRIPTOR data_descriptor;
ZIP_HEADER      zip_header;
ZIP_ENTRYES     zip_entryes;
uchar           key[] = {1,0,0,0};
bool            f_found;
uchar           f_name[];
bool            is_descr;
//+------------------------------------------------------------------+
//| Get entryes in ZIP file                                          |
//+------------------------------------------------------------------+
uint GetEntryesZip( int handle, ZIP_ENTRYES &f_entr )
{
//--- Check valid file handle
  if ( handle != INVALID_HANDLE )
  {
    f_entr.file_count = 0;
//---      
    ulong file_size = FileSize( handle );
    if ( file_size > 0 ) 
    {
//---Set file position to "0"
      FileSeek( handle, 0, SEEK_SET );
//---Build table           
      while ( FileTell( handle ) < ( file_size - uint_size ) )
      {
        zip_header.sign = FileReadInteger( handle, uint_size );
//---        
        if ( zip_header.sign == 0x04034b50 )
        {
          FileSeek( handle, -4, SEEK_CUR );
          f_entr.file_count++;
          FileReadStruct( handle, zip_header );
//---Check needed version 
          if ( ( zip_header.a_version != 0x0014 ) && ( f_entr.file_count == 1 ) )
          {
            Print( "Unsupported version!" );
            f_entr.file_count = 0;
            return( f_entr.file_count );
          }
          if ( ( zip_header.extr_field_len != 0 ) && ( f_entr.file_count == 1 ) )
          {
            Print( "File compressed using ZIP64 format!" );
            f_entr.file_count = 0;
            return( f_entr.file_count );
          }
//---Resize out data
          ArrayResize( f_entr.pack_size, f_entr.file_count );
          ArrayResize( f_entr.unpack_size, f_entr.file_count );   
          ArrayResize( f_entr.zip_fnames, f_entr.file_count );
          ArrayResize( f_entr.zip_offsets, f_entr.file_count );           
//---Check for sizes using extra bit
          if ( ( ( zip_header.bit_flag & 4 ) >> 2 ) == 1 )
          {
            is_descr = true; 
          }  
          else
          {
            is_descr = false;
            f_entr.pack_size[ f_entr.file_count - 1] = zip_header.pack_size;
            f_entr.unpack_size[ f_entr.file_count - 1] = zip_header.unpack_size;
          }
//---Get current file name
          ArrayResize( f_name, zip_header.fn_len );
          f_entr.zip_fnames[f_entr.file_count - 1] = ""; 
          uint fn_res = FileReadArray( handle, f_name, 0, int( zip_header.fn_len ) );
          for ( int i = 0; i < int( fn_res ); i++ )
           f_entr.zip_fnames[f_entr.file_count - 1] += CharToString( f_name[i] );
//---Store offset
          f_entr.zip_offsets[ f_entr.file_count - 1] = FileTell( handle );
//---Get descriptor, if present
          if ( is_descr )
          {
            uint sign;
            while ( FileTell( handle ) < ( file_size - uint_size ) )
            {
              sign = FileReadInteger( handle, uint_size );
              if ( ( sign == 0x04034b50 ) || ( sign == 0x02014b50 ) )
              {
//---Seek back for read descriptor              
                FileSeek( handle, -( uint_size + descr_size ), SEEK_CUR );
                FileReadStruct( handle, data_descriptor );
                f_entr.pack_size[ f_entr.file_count - 1] = data_descriptor.pack_size;
                f_entr.unpack_size[ f_entr.file_count - 1] = data_descriptor.unpack_size;
//---Align file positon to new file
                FileSeek( handle, f_entr.zip_offsets[f_entr.file_count - 1] +
                                  f_entr.pack_size[ f_entr.file_count - 1], SEEK_SET ); 
                break;                                  
              }
            }
          }
          else            
//---Seek to new file          
          FileSeek( handle, f_entr.pack_size[ f_entr.file_count - 1 ], SEEK_CUR ); 
        }
      }
    }
    else
    {
      Print( "Invalid zip file size!" );
    }
  }
  else
  {
    Print( "Invalid zip file handle!" );
  }  
  return( f_entr.file_count );
}
//+------------------------------------------------------------------+
//| Get file from ZIP file                                           |
//+------------------------------------------------------------------+
bool GetFile( const int handle, const ulong offset, const uint pack_size,
              const uint unp_size, uchar &unp_data[] )
{
  if ( ( handle != INVALID_HANDLE ) && ( pack_size != 0 ) && ( unp_size != 0 ) )
  {
    uchar pack_data[];
    ArrayResize( pack_data, pack_size + hdr_size );
    FileSeek( handle, offset, SEEK_SET );
    uint ar_res = FileReadArray( handle, pack_data, hdr_size, pack_size );
    if ( ar_res == pack_size )
    {
      pack_data[0] = 0x78;
      pack_data[1] = 0x5E;
      ResetLastError();
      uint dec_res = CryptDecode( CRYPT_ARCH_ZIP, pack_data, key, unp_data );
      if ( dec_res == unp_size )
      {
        return( true );
      }
      else
      {
        Print( "Last error = ", GetLastError() );
      }
    }
  }
  return( false );
}


 Вызовы:

//+------------------------------------------------------------------+
//|                                                     Zip_test.mq5 |
//|                                          Copyright 2015, Mikalas |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Mikalas"
#property link      "https://www.mql5.com"
#property version   "1.00"
//
#include "Zip_decoder.mqh";
//
int         zip_handle;
ZIP_ENTRYES entries;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   string file_name = "Settings.zip";
   zip_handle = FileOpen( file_name, FILE_READ | FILE_BIN );
   
   if ( zip_handle != INVALID_HANDLE )
   {
     uint zip_files = GetEntryesZip( zip_handle, entries );
     if ( zip_files > 0 )
     {
//---Get 3 file from zip archive ([2])     
       uchar file_data[];
       if ( GetFile( zip_handle, entries.zip_offsets[2], entries.pack_size[2],
                     entries.unpack_size[2], file_data ) )
       {
         Print(" Unpack done.");
       }
       else
       {
         Print("Unpack failed!");
       }
     }
   }  
//---
   return(INIT_SUCCEEDED);
  }
void OnDeinit( const int reason )
{
  if ( zip_handle != INVALID_HANDLE ) FileClose( zip_handle );
}
 
Mikalas:

Василий!

Не дождался от Вас ответа. (не знаю успели MQ внедрить изменения в билд 1100 )

Декодер:

 Вызовы:

Не успели. Билд 1100 введен до начала нашего обсуждения.
 
-Aleks-:

Mikalas , а возможно код декодирования и кодирования сделать в виде библиотеки с проверкой окончания распоковки?

Конечно. Этим и займусь в ближайшее время. Будет упкаковка/распаковка. Добавление и удаление файлов из архива. Главное, что бы CryptDecode не подвела.
 
C-4:
Конечно. Этим и займусь в ближайшее время. Будет упкаковка/распаковка. Добавление и удаление файлов из архива. Главное, что бы CryptDecode не подвела.

Василий!

А нужна ли запаковка в ZIP?

Думаю оно того не стоит. 

1. Если Вы хотите построить на базе ZIP БД, то это будет не актуально.

Скоро MQ добавит стандартные функции для работы с БД (Ренат делал опрос)

2. Нельзя решить проблему с размером файлов больше uint.

Для размеров ulong должна быть компрессия ZIP64.

3. Вы не знаете как именно компрессируются данные МТ5

Вожможно, большие файлы ( даже размера uint ) будут

компрессироваться ЧАС! 

4. Чтобы "впихивать" файлы в архив, Вам придётся держать в

памяти достаточно много информации - будут ТОРМОЗА!

Настоятельно не советую.... 

 

Я наверно думаю по старинке, но для меня архивация интересна для ускорения передачи данных в сети интернет. Локально с большими винчестерами размер файла теряет свою актуальность, а БД будет для ограниченного круга лиц, да и затратна в реализации, так как потребует от программиста и пользователя дополнительных знаний.

Правда zip существенно уступает в сжатии, особенно текста, rar'у - что малость печально. 

 
Mikalas:

Василий!

А нужна ли запаковка в ZIP?

Думаю оно того не стоит. 

Я думаю иначе.

Mikalas:

1. Если Вы хотите построить на базе ZIP БД, то это будет не актуально.

Скоро MQ добавит стандартные функции для работы с БД (Ренат делал опрос)

 Нет, zip интересен не как альтернатива БД. Заморочиться с запаковкой стоит не поэтому.

Mikalas:

2. Нельзя решить проблему с размером файлов больше uint.

Для размеров ulong должна быть компрессия ZIP64.

 У меня нет цели создать аналог WinZip или WinRar. Только самые элементарные архивы. Запаковывать файлы больше 4 Гб не кому даже в голову не придет.

Mikalas:

3. Вы не знаете как именно компрессируются данные МТ5

Вожможно, большие файлы ( даже размера uint ) будут

компрессироваться ЧАС! 

4. Чтобы "впихивать" файлы в архив, Вам придётся держать в

памяти достаточно много информации - будут ТОРМОЗА!

Настоятельно не советую.... 

1. MQ не делает медленных функций, а если и делает, то своевременно оптимизирует их работу по заявкам из сервисдеска. Я почему-то уверен что CryptEncode будет летать.

2. Ни каких тормозов не будет. Вы не знаете на что способен современный MQL5 в плане производительности. Памяти на современных компьютерах как грязи. Загрузить и запаковать файл на пару сотен мегабайт - плевое дело, а больше и не надо. Ибо это уже другие задачи.

 
Mikalas:

Василий!

А нужна ли запаковка в ZIP?

Думаю оно того не стоит.  

А знаете ли Вы что реализация запаковки файлов в zip, например, откроет дорогу к созданию файлов docx и xmlx. Это значит, что прямо из вашего эксперта можно будет создать Excel таблицу с отчетом и отослать ее например по почте. При этом речь будет идти исключительно о штатном функционале, без использования DLL. Такие библиотеки можно будет распространять в составе продуктов маркета. И это только один пример.
 
C-4:

Я думаю иначе.

 Нет, zip интересен не как альтернатива БД. Заморочиться с запаковкой стоит не поэтому.

 У меня нет цели создать аналог WinZip или WinRar. Только самые элементарные архивы. Запаковывать файлы больше 4 Гб не кому даже в голову не придет.

1. MQ не делает медленных функций, а если и делает, то своевременно оптимизирует их работу по заявкам из сервисдеска. Я почему-то уверен что CryptEncode будет летать.

2. Ни каких тормозов не будет. Вы не знаете на что способен современный MQL5 в плане производительности. Памяти на современных компьютерах как грязи. Загрузить и запаковать файл на пару сотен мегабайт - плевое дело, а больше и не надо. Ибо это уже другие задачи.

В добрый путь!
 
-Aleks-:

Я наверно думаю по старинке, но для меня архивация интересна для ускорения передачи данных в сети интернет. Локально с большими винчестерами размер файла теряет свою актуальность, а БД будет для ограниченного круга лиц, да и затратна в реализации, так как потребует от программиста и пользователя дополнительных знаний.

Правда zip существенно уступает в сжатии, особенно текста, rar'у - что малость печально. 

Совершено верно. Общаться со сторонним сервером через WebRequest можно будет гораздо быстрее используя запаковку отсылаемой информации. Эта еще одна идея, почему релазовать запаковку - правильное решение.

-Aleks-:

Правда zip существенно уступает в сжатии, особенно текста, rar'у - что малость печально. 

Цените то что нам дали. Поверьте, возможность работы с самым распространненым форматом сжатия покрывает 90% всех задач. 80% избыточности зип вполне успешно устраняет. Дальше идет погоня за попугаями, которые не кому не нужны.

 
Mikalas:
В добрый путь!
Я исследовал формат стандартного zip файла. Он не сложен. Что бы "научиться" упаковывать достаточно записывать в конце файла две дополнительные структуры похожие на заголовочную структуру. Поэтому игра явна стоит свеч.