CryptDecode con modificador CRYPT_ARCH_ZIP - ¿Cómo utilizarlo? - página 10

 

¡Vasiliy!

No esperé una respuesta tuya. (no sé si MQ tuvo tiempo de aplicar los cambios en la compilación 1100)

Descodificador:

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


Llamadas:

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

No esperé una respuesta tuya. (no sé si MQ tuvo tiempo de aplicar los cambios en la compilación 1100)

Descodificador:

Llamadas:

No tenía tiempo. El Bild 1100 se presentó antes de que comenzara nuestro debate.
 
-Aleks-:

Mikalas, ¿es posible hacer el código de decodificación y codificación como una biblioteca con una comprobación de la finalización del desempaquetado?

Sí, por supuesto. Eso es lo que haré en un futuro próximo. Habrá que empaquetar y desempaquetar. Añadir y eliminar ficheros del archivo. Siempre y cuando CryptDecode no falle.
 
C-4:
Claro que sí. Eso es lo que haré en un futuro próximo. Habrá que empaquetar y desempaquetar. Añadir y eliminar ficheros del archivo. Lo principal es que CryptDecode no falle.

¡Vasiliy!

¿Es necesario el embalaje ZIP?

No creo que valga la pena.

1. Si quieres construir una base de datos basada en ZIP, no será relevante.

Pronto MQ añadirá funciones estándar para trabajar con la base de datos (Renat hizo un estudio).

2. No se puede resolver el problema con tamaños de archivo superiores a uint.

Debería haber compresión ZIP64 para tamaños ultralargos.

3. No sabes exactamente cómo se comprimen los datos de MT5

Es posible que los archivos de gran tamaño ( incluso de tamaño uint )

los archivos de gran tamaño (incluso los de tamaño pequeño) se comprimirán durante HORAS.

4. Para "atiborrar" los ficheros en un archivo, tendrá que guardar bastante información en

mucha información en la memoria - ¡habrá HARDWARE!

Se lo desaconsejo totalmente....

 

Probablemente estoy pensando a la antigua, pero para mí el archivo es interesante para acelerar la transferencia de datos en Internet. Localmente, con discos duros grandes , el tamaño del archivo pierde su relevancia, y la base de datos será para un rango limitado de personas, y es costosa de implementar, ya que requerirá conocimientos adicionales del programador y del usuario.

Es cierto que zip es considerablemente inferior a rar en la compresión, especialmente de texto - lo que es un poco triste.

 
Mikalas:

¡Vasiliy!

¿Es necesario el embalaje ZIP?

No creo que valga la pena.

Yo pienso lo contrario.

Mikalas:

1. Si quieres construir una base de datos basada en ZIP, no será relevante.

Pronto MQ añadirá funciones estándar para trabajar con la base de datos (Renat hizo un estudio)

No, zip no es interesante como alternativa a DB. Por eso no vale la pena molestarse con la cremallera.

Mikalas:

2. No se puede resolver el problema con tamaños de archivo superiores a uint.

Debe haber compresión ZIP64 para el tamaño ulong.

No tengo el objetivo de crear un análogo de WinZip o WinRar. Sólo los archivos más básicos. A nadie se le ocurre comprimir archivos de más de 4 GB.

Mikalas:

3. No sabes cómo se comprimen exactamente los datos de MT5.

Es posible que los archivos grandes (incluso de tamaño uint) sean

¡incluso de tamaño uint) se comprimirá por HORAS!

4. Para "atiborrar" los ficheros en un archivo, tendrá que guardar bastante información en

mucha información en la memoria - ¡habrá HARDWARE!

Aconsejo encarecidamente contra....

1. MQ no realiza funciones lentas, y si lo hace, las optimiza oportunamente, basándose en las peticiones de servicedesk. De alguna manera confío en que CryptEncode volará.

2. No habrá ralentizaciones. No sabes de qué es capaz un MQL5 moderno en términos de rendimiento. Los ordenadores actuales tienen demasiada memoria. Descargar y empaquetar un archivo de un par de cientos de megabytes es pan comido, y no necesitas más. Porque estas son otras tareas.

 
Mikalas:

¡Vasiliy!

¿Es necesario el embalaje ZIP?

No creo que valga la pena.

Sabías que la implementación de archivos comprimidos, por ejemplo, abre el camino para crear archivos docx y xmlx. Significa que directamente desde tu Expert Advisor puedes crear una hoja de cálculo Excel con el informe y enviarlo por correo, por ejemplo. Esto será sólo la funcionalidad estándar, sin el uso de DLLs. Estas bibliotecas pueden distribuirse como parte de los productos del mercado. Este es sólo un ejemplo.
 
C-4:

Yo pienso lo contrario.

No, zip no es interesante como alternativa a DB. Por eso no vale la pena molestarse con la cremallera.

No tengo el objetivo de crear un análogo de WinZip o WinRar. Sólo los archivos más básicos. A nadie se le ocurriría comprimir archivos de más de 4 GB.

1. MQ no hace funciones lentas, y si lo hace, optimizará su trabajo de manera oportuna, basándose en las peticiones del servicio de asistencia. De alguna manera confío en que CryptEncode volará.

2. No habrá ralentizaciones. No sabes de qué es capaz un MQL5 moderno en términos de rendimiento. Los ordenadores actuales tienen demasiada memoria. Descargar y empaquetar un archivo de un par de cientos de megabytes es pan comido, y no necesitas más. Porque estas son otras tareas.

¡Que Dios te acompañe!
 
-Aleks-:

Probablemente estoy pensando a la antigua, pero para mí el archivo es interesante para acelerar la transferencia de datos en Internet. Localmente, con discos duros grandes, el tamaño del archivo pierde su relevancia, y la base de datos será para un rango limitado de personas, y es costosa de implementar, ya que requerirá conocimientos adicionales del programador y del usuario.

El verdadero zip es significativamente inferior en la compresión, especialmente el texto, rar - que es un poco triste.

Muy cierto. La comunicación con un servidor de terceros a través de WebRequest será mucho más rápida utilizando el empaquetamiento de la información enviada. Esta es otra idea por la que recargar el envase es una buena solución.

-Aleks-:

Sin embargo, zip es significativamente inferior a rar en cuanto a compresión, especialmente de texto, lo que es un poco desafortunado.

Apreciar lo que se nos ha dado. Créame, la capacidad de trabajar con el formato de compresión más popular cubre el 90% de las tareas. El 80% de la redundancia se elimina con éxito con la cremallera. Lo que viene después es perseguir loros que nadie necesita.

 
Mikalas:
¡Que te vaya bien!
He investigado el formato del archivo zip estándar. No es complicado. Todo lo que hay que hacer para "aprender" a empaquetar es escribir dos estructuras adicionales al final del archivo, similares a una estructura de cabecera. Así que está claro que merece la pena el juego.
Razón de la queja: