CryptDecode com modificador CRYPT_ARCH_ZIP - Como usar? - página 10

 

Vasiliy!

Não esperei por uma resposta sua. (não sei se a MQ teve tempo para implementar mudanças na construção 1100)

Decodificador:

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


Chamadas:

//+------------------------------------------------------------------+
//|                                                     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:

Vasiliy!

Não esperei por uma resposta sua. (não sei se a MQ teve tempo para implementar mudanças na construção 1100)

Decodificador:

Chamadas:

Não tive tempo. O Bild 1100 foi apresentado antes do início de nossa discussão.
 
-Aleks-:

Mikalas, é possível fazer a decodificação e codificação do código como uma biblioteca com um cheque para desempacotar a conclusão?

Sim, é claro. Isso é o que farei no futuro próximo. Haverá embalagem/desembalagem. Acréscimo e remoção de arquivos do arquivo. Desde que o CryptDecode não falhe.
 
C-4:
Claro. Isso é o que farei num futuro próximo. Haverá embalagem/desembalagem. Adicionar e remover arquivos do arquivo. O principal é que o CryptDecode não falha.

Vasiliy!

A embalagem ZIP é necessária?

Acho que não vale a pena.

1. Se você quiser construir um banco de dados com base no ZIP, ele não será relevante.

Em breve a MQ acrescentará funções padrão para trabalhar com o banco de dados (Renat fez uma pesquisa).

2. Você não pode resolver o problema com arquivos de tamanho maior do que o uint.

Deve haver compressão ZIP64 para os tamanhos ulong.

3. Você não sabe exatamente como os dados MT5 são comprimidos

É possível que arquivos grandes (mesmo de tamanho uint)

arquivos grandes ( mesmo tamanho uint ) serão comprimidos para HOURS!

4. Para "encher" os arquivos em um arquivo, você terá que manter um grande volume de informações em

muitas informações na memória - haverá HARDWARE!

Eu desaconselho vivamente....

 

Provavelmente estou pensando à moda antiga, mas para mim o arquivamento é interessante para acelerar a transferência de dados na Internet. Localmente com grandes discos rígidos, o tamanho do arquivo perde sua relevância, e o banco de dados será para uma gama limitada de pessoas, e a sua implementação é cara, pois exigirá conhecimentos adicionais do programador e do usuário.

É verdade que o fecho é consideravelmente inferior ao raro na compressão, especialmente do texto - o que é um pouco triste.

 
Mikalas:

Vasiliy!

A embalagem ZIP é necessária?

Acho que não vale a pena.

Eu penso o contrário.

Mikalas:

1. Se você quiser construir um banco de dados com base no ZIP, ele não será relevante.

Em breve a MQ adicionará funções padrão para trabalhar com banco de dados (Renat fez uma pesquisa)

Não, o zip não é interessante como alternativa ao DB. Não é por isso que vale a pena se preocupar com o zíper.

Mikalas:

2. Você não pode resolver o problema com arquivos de tamanho maior do que o uint.

Deve haver compressão ZIP64 para os tamanhos ulong.

Não tenho nenhum objetivo de criar um análogo do WinZip ou do WinRar. Somente os arquivos mais básicos. Ninguém pensará sequer em comprimir arquivos maiores do que 4 GB.

Mikalas:

3. Você não sabe exatamente como os dados MT5 são compactados.

É possível que os arquivos grandes (mesmo de tamanho uint) sejam

mesmo tamanho uint) será comprimido para HOUR!

4. Para "encher" os arquivos em um arquivo, você terá que manter um grande volume de informações em

muitas informações na memória - haverá HARDWARE!

Eu desaconselho vivamente....

1. MQ não faz funções lentas, e se faz, as otimiza de forma oportuna, com base nas solicitações do servicedesk. Estou de alguma forma confiante de que a CryptEncode voará.

2. Não haverá lentidão. Você não sabe o que uma MQL5 moderna é capaz de fazer em termos de desempenho. Os computadores de hoje têm muita memória. Para baixar e embalar um arquivo de algumas centenas de megabytes é canja, e você não precisa de mais. Para estas são outras tarefas.

 
Mikalas:

Vasiliy!

A embalagem ZIP é necessária?

Acho que não vale a pena.

Você sabia que a implementação de arquivos zipados, por exemplo, abre o caminho para criar arquivos docx e xmlx. Isso significa que diretamente de seu Expert Advisor você pode criar uma planilha Excel com o relatório e enviá-lo pelo correio, por exemplo. Esta será apenas a funcionalidade padrão, sem o uso de DLLs. Tais bibliotecas podem ser distribuídas como parte dos produtos Marketplace. Este é apenas um exemplo.
 
C-4:

Eu penso o contrário.

Não, o zip não é interessante como alternativa ao DB. Não é por isso que vale a pena se preocupar com o zíper.

Não tenho nenhum objetivo de criar um análogo do WinZip ou do WinRar. Somente os arquivos mais básicos. Ninguém pensaria sequer em comprimir arquivos maiores do que 4 GB.

1. MQ não faz recursos lentos, e se fizer, otimizará seu trabalho de forma oportuna, com base nas solicitações da central de serviço. Estou de alguma forma confiante de que a CryptEncode voará.

2. Não haverá lentidão. Você não sabe o que uma MQL5 moderna é capaz de fazer em termos de desempenho. Os computadores de hoje têm muita memória. Para baixar e embalar um arquivo de algumas centenas de megabytes é canja, e você não precisa de mais. Para estas são outras tarefas.

Boa sorte!
 
-Aleks-:

Provavelmente estou pensando à moda antiga, mas para mim o arquivamento é interessante para acelerar a transferência de dados na Internet. Localmente com grandes discos rígidos, o tamanho do arquivo perde sua relevância, e o banco de dados será para uma gama limitada de pessoas, e a sua implementação é cara, pois exigirá conhecimentos adicionais do programador e do usuário.

O verdadeiro fecho é significativamente inferior em compressão, especialmente de texto, raro - o que é um pouco triste.

É bem verdade. A comunicação com um servidor de terceiros via WebRequest será muito mais rápida utilizando a embalagem das informações enviadas. Esta é outra idéia porque recarregar a embalagem é uma boa solução.

-Aleks-:

Entretanto, o zíper é significativamente inferior ao raro em compressão, especialmente de texto - o que é um pouco infeliz.

Apreciar o que nos foi dado. Acredite em mim, a capacidade de trabalhar com o formato de compressão mais popular cobre 90% de todas as tarefas. 80% da redundância é eliminada com sucesso com zíper. O que vem em seguida é perseguir papagaios que ninguém precisa.

 
Mikalas:
Boa viagem!
Eu investiguei o formato do arquivo zip padrão. Não é complicado. Tudo o que você precisa fazer para "aprender" como embalar é escrever duas estruturas extras no final do arquivo, semelhante a uma estrutura de cabeçalho. Portanto, vale claramente a pena o esforço.