2026-09-01 12:16:15 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| Main.mqh |
|
| | | //| Copyright 2026, Niquel Mendoza |
|
| | | //| https://www.mql5.com |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2026, Niquel Mendoza"
|
| | | #property link "https://www.mql5.com"
|
| | | #property strict
|
| | |
|
| | | #ifndef CRYPTOBYLEO_SRC_FERNET_MAIN_MQH
|
| | | #define CRYPTOBYLEO_SRC_FERNET_MAIN_MQH
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-09-01 17:55:59 -05:00 | | | #include "Def.mqh"
|
2026-09-01 12:16:15 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | namespace TSN
|
| | | {
|
2026-09-02 11:55:03 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | /*
|
| | | Notas imporantes:
|
| | | - Los archivos como maximo pueden pesar menos bytes que INT_MAX lo ideal quizas 1.5gb a menos o 1.7gb
|
| | | la cosa e sque debe sobra algo de 64 bytes para el IV, KEY etc...
|
| | | Esto por limitaciones del lengauje en el numero de elemtnos INT_MAX sobre un array que podemos procesar
|
| | |
|
2026-09-14 08:14:16 -05:00 | | | - DecryptRaw y Encrypt RAW el array "out" su tamaño ArraySize() es ligeralmetne mas grande o igual que el tamaño "en si r"
|
2026-09-02 11:55:03 -05:00 | | | Se le da la elecccion al usuario para que este pueda recortar su tamaño (trim) o quizas si trabaj
|
2026-09-14 08:14:16 -05:00 | | | con un "int size" pueda setearlo.. con el int
|
2026-09-02 11:55:03 -05:00 | | | Aparte estas funciones retornan -1 en caso de error
|
| | |
|
2026-09-14 08:14:16 -05:00 | | | Aparte en las verions de DecyrptFIle SIEMPRE se reduce el tamaño.. siempre (el ArrayResize)
|
| | |
|
2026-09-02 11:55:03 -05:00 | | | */
|
| | |
|
2026-09-01 12:16:15 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | class CFernet
|
| | | {
|
| | | private:
|
2026-09-01 17:55:59 -05:00 | | | //---
|
2026-09-01 12:16:15 -05:00 | | | CAes m_aes;
|
| | | CHMac m_hmac;
|
| | |
|
2026-09-01 17:55:59 -05:00 | | | //---
|
| | | ENUM_CRYPTOBYLEO_FERNAT_ERR m_last_err;
|
| | |
|
| | |
|
2026-09-01 12:16:15 -05:00 | | | public:
|
2026-09-02 10:54:31 -05:00 | | | CFernet(void);
|
2026-09-01 17:55:59 -05:00 | | | ~CFernet(void) {}
|
2026-09-01 12:16:15 -05:00 | | |
|
| | | //--- Seteo de key
|
2026-09-02 10:01:34 -05:00 | | | bool Key(const uchar& key[]);
|
2026-09-02 10:54:31 -05:00 | | | // auto solo eliges el generador y ya se hace todo auto
|
| | | // CORRECCION INLINE POR BUG DEL COMPILADOR
|
| | | template <typename TCryptoRandomFunc>
|
| | | void Key()
|
| | | {
|
| | | uchar key[CRYPTOBYLEO_FERNET_KEYBYTES];
|
| | | TCryptoRandomFunc::RandomCryptoBytes(key, CRYPTOBYLEO_FERNET_KEYBYTES, 0);
|
| | |
|
| | | //---
|
| | | // m_hmac.CheckKeyReserve(16);
|
| | | // opt: Dado que por defecto la reserva es de 128 no hace falta vamos d esobra
|
| | | m_hmac.m_key_s = ArrayCopy(m_hmac.m_key, key, 0, 0, CRYPTOBYLEO_FERNET_HMAC_KEY_BYTES);
|
2026-09-02 11:55:03 -05:00 | | | m_hmac.OnKeyUpdate();
|
2026-09-02 10:54:31 -05:00 | | | // ahora toca copiar para la parte alta (empezamos desde el final de hmac)
|
| | | m_aes.Init(key, CRYPTOBYLEO_FERNET_HMAC_KEY_BYTES);
|
| | | }
|
2026-09-01 12:16:15 -05:00 | | |
|
2026-09-01 17:55:59 -05:00 | | | //--- EncryptRaw \ DecryptRaw (genericos basicos)
|
| | | template <typename TCryptoRandomFunc>
|
2026-09-02 11:55:03 -05:00 | | | int EncryptRaw(const uchar& in[], uchar& token[], datetime time)
|
2026-09-02 10:54:31 -05:00 | | | {
|
| | | // La idea con este es esquema es zero copyes la copia de in es invetiable dado que neceistmao mutar en aes
|
| | | //---
|
| | | const int data_t = ArraySize(in);
|
| | |
|
| | | //--- estimacion de tamaoño
|
2026-09-02 11:55:03 -05:00 | | | const int fs = 1 + 8 + AES_BLOCKLEN + data_t + AES_BLOCKLEN + CRYPTOBYLEO_SHA256_SIZET_FHASH;
|
2026-09-02 10:54:31 -05:00 | | | if(fs > ArraySize(token))
|
| | | ArrayResize(token, fs);
|
| | | // armado
|
| | | int w = 0;
|
| | | token[w++] = CRYPTOBYLEO_FERNET_VER;
|
2026-09-02 11:55:03 -05:00 | | | w = CNumberUtils::SValueToBytesBE(time, token, w); // -1defautl exacto, timstap
|
2026-09-02 10:54:31 -05:00 | | | TCryptoRandomFunc::RandomCryptoBytes(m_aes.m_iv, AES_BLOCKLEN, 0); // El iv lo copiamos al CBC de aes
|
| | | w += ArrayCopy(token, m_aes.m_iv, w, 0, AES_BLOCKLEN); // y tambien lo copiamos el token
|
| | |
|
| | |
|
| | | // Copiamos los datos al final
|
| | | ArrayCopy(token, in, w, 0, data_t); // #1 copia de los datos
|
| | |
|
| | |
|
| | | //---
|
| | | const int t = CAes::PKCS7_CorrectPadding(token, data_t, w) - w; // tamaño exacto
|
| | | m_aes.CbcCifrado(token, t, w); // ciframos [w(inicio de datos) : t (datos con el padding)]
|
| | | w += t; // movemos el puntero
|
2026-09-26 21:47:11 -05:00 | | | //Print(w);
|
2026-09-02 10:54:31 -05:00 | | | m_hmac.Update(token, w); // hmac
|
2026-09-02 11:55:03 -05:00 | | | w += ArrayCopy(token, m_hmac.m_out, w, 0, CRYPTOBYLEO_SHA256_SIZET_FHASH); // Copiamos el digest luego (append al final)
|
| | | return w; // retorna cuando a encryptado (w) tamaño final
|
2026-09-02 10:54:31 -05:00 | | | }
|
| | |
|
| | | //---
|
2026-09-02 11:55:03 -05:00 | | | // Retorna el tamaño final de msg
|
| | | int DecryptRaw(const uchar& in[], int t, uchar& msg[], int ttl);
|
2026-09-01 12:16:15 -05:00 | | |
|
2026-09-14 08:14:16 -05:00 | | | //--- Files (Agregados para facilidad)
|
| | | //-- enc
|
2026-09-01 17:55:59 -05:00 | | | template <typename TCryptoRandomFunc>
|
2026-09-02 11:55:03 -05:00 | | | bool EncryptFile(const string& file_name, bool common_flag, bool delete_prev_file, datetime time, string ext_encrypt = "");
|
2026-09-14 08:14:16 -05:00 | | |
|
| | | //-- dec
|
2026-09-01 17:55:59 -05:00 | | | bool DecryptFile(const string& file_name, bool common_flag, bool delete_prev_file, int ttl, string ext_decrypt = "");
|
| | | bool DecryptFile(const string& file_name, bool common_flag, bool delete_prev_file, uchar& res_data[], int ttl);
|
2026-09-14 08:14:16 -05:00 | | | bool DecryptFile(const string &file_name, bool common_flag, bool delete_prev_file,
|
| | | string &res_data, int ttl, uint cp = CP_ACP);
|
2026-09-01 12:16:15 -05:00 | | |
|
| | | //--- Extract timestap
|
| | | datetime ExtractTimestap(const uchar& token[]);
|
2026-09-01 17:55:59 -05:00 | | |
|
| | | //---
|
| | | __forceinline ENUM_CRYPTOBYLEO_FERNAT_ERR LastErr() const { return m_last_err; }
|
2026-09-01 12:16:15 -05:00 | | | };
|
| | |
|
2026-09-02 10:54:31 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | // AES: 128
|
| | | // HMAC-256 (SHA2 256)
|
| | | CFernet::CFernet(void)
|
| | | : m_aes(AES_CRYPTH_128), m_hmac(CCryptoHashMeta::TSN_CRYPTO_HASH_TYPE_SHA256)
|
| | | {
|
| | | }
|
| | |
|
2026-09-02 10:01:34 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | // Se asume key de 32 bits
|
| | | bool CFernet::Key(const uchar &key[])
|
| | | {
|
| | | if(ArraySize(key) < CRYPTOBYLEO_FERNET_KEYBYTES)
|
| | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_KEY_INVALID_SIZE;
|
| | | return false;
|
| | | }
|
2026-09-14 08:14:16 -05:00 | | |
|
2026-09-02 10:01:34 -05:00 | | | //---
|
| | | // m_hmac.CheckKeyReserve(16);
|
| | | // opt: Dado que por defecto la reserva es de 128 no hace falta vamos d esobra
|
| | | m_hmac.m_key_s = ArrayCopy(m_hmac.m_key, key, 0, 0, CRYPTOBYLEO_FERNET_HMAC_KEY_BYTES);
|
2026-09-02 11:55:03 -05:00 | | | m_hmac.OnKeyUpdate();
|
2026-09-02 10:01:34 -05:00 | | | // ahora toca copiar para la parte alta (empezamos desde el final de hmac)
|
| | | m_aes.Init(key, CRYPTOBYLEO_FERNET_HMAC_KEY_BYTES);
|
| | | return true;
|
| | | }
|
| | |
|
2026-09-01 12:16:15 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
2026-09-01 17:55:59 -05:00 | | | //+------------------------------------------------------------------+
|
2026-09-02 11:55:03 -05:00 | | | int CFernet::DecryptRaw(const uchar &in[], int t, uchar &msg[], int ttl)
|
2026-09-01 17:55:59 -05:00 | | | {
|
| | | int r = 0;
|
| | | if(in[r++] != CRYPTOBYLEO_FERNET_VER)
|
| | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_DEC_INVALID_VER;
|
2026-09-02 11:55:03 -05:00 | | | return -1;
|
2026-09-01 17:55:59 -05:00 | | | }
|
| | | // tiempo
|
| | | datetime time;
|
| | | r = CNumberUtils::SVAlaueFromBytesBE(time, in, r);
|
| | | if(TimeGMT() - time >= ttl)
|
| | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_DEC_EXPIRED;
|
2026-09-02 11:55:03 -05:00 | | | return -1;
|
2026-09-01 17:55:59 -05:00 | | | }
|
| | | // ahora obteenmos el HMAC de
|
2026-09-02 11:55:03 -05:00 | | | int msi = t - CRYPTOBYLEO_SHA256_SIZET_FHASH;
|
2026-09-01 17:55:59 -05:00 | | | m_hmac.Update(in, msi);
|
| | | // ahora si comparammos
|
| | | // msi tambien detecta el inicio
|
2026-09-02 11:55:03 -05:00 | | | if(!m_hmac.CompareRaw(in, CRYPTOBYLEO_SHA256_SIZET_FHASH, msi))
|
2026-09-01 17:55:59 -05:00 | | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_DEC_HMAC_CORRUPTED;
|
2026-09-02 11:55:03 -05:00 | | | return -1;
|
2026-09-01 17:55:59 -05:00 | | | }
|
| | | // descifrado
|
2026-09-02 11:55:03 -05:00 | | | r += ArrayCopy(m_aes.m_iv, in, 0, r, AES_BLOCKLEN); // ahora r apunta justo en chiper text
|
| | | msi -= AES_BLOCKLEN + 8 + 1; // (iv) - (datetime) - (version)
|
| | |
|
2026-09-01 17:55:59 -05:00 | | | // aqui ocurre el resize exacto
|
2026-09-02 11:55:03 -05:00 | | | ArrayCopy(msg, in, 0, r, msi); // solo copiamos desde [r:msi, osea desde donde empiza chiper hasta donde temrina]
|
| | | m_aes.CbcDescifra(msg, msi);
|
| | |
|
| | | //---
|
| | | r = CAes::PKCS7_QuitarPadding(msg, msi);
|
| | | if(r == -1) // padding invalido
|
| | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_DEC_INVALID_PADDING;
|
| | | return -1;
|
| | | }
|
| | | return r; // termino
|
2026-09-01 17:55:59 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-09-02 10:01:34 -05:00 | | | datetime CFernet::ExtractTimestap(const uchar &token[])
|
2026-09-01 17:55:59 -05:00 | | | {
|
| | | //---
|
| | | if(token[0] != CRYPTOBYLEO_FERNET_VER)
|
| | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_DEC_INVALID_VER;
|
| | | return 0;
|
| | | }
|
| | | // tiempo
|
| | | datetime time;
|
| | | CNumberUtils::SVAlaueFromBytesBE(time, token, 1);
|
| | | return time;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | template <typename TCryptoRandomFunc>
|
2026-09-02 11:55:03 -05:00 | | | bool CFernet::EncryptFile(const string &file_name, bool common_flag, bool delete_prev_file, datetime time, string ext_encrypt = "")
|
2026-09-01 12:16:15 -05:00 | | | {
|
2026-09-01 17:55:59 -05:00 | | | //----- file
|
| | | ::ResetLastError();
|
| | | const int common_file_flag = (common_flag ? FILE_COMMON : 0);
|
| | | int fh = FileOpen(file_name, FILE_BIN | FILE_READ | common_file_flag);
|
| | | if(fh == INVALID_HANDLE)
|
| | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_OPEN_FILE;
|
| | | return false;
|
| | | }
|
| | |
|
| | | //---
|
| | | uchar token[];
|
| | | const int data_t = (int)FileSize(fh);
|
| | |
|
| | | //----- fernat start
|
| | |
|
| | | //--- estimacion de tamaoño
|
2026-09-02 11:55:03 -05:00 | | | const int fs = 1 + 8 + AES_BLOCKLEN + data_t + AES_BLOCKLEN + CRYPTOBYLEO_SHA256_SIZET_FHASH;
|
2026-09-01 17:55:59 -05:00 | | | if(fs > ArraySize(token))
|
| | | ArrayResize(token, fs);
|
| | | // armado
|
2026-09-01 12:16:15 -05:00 | | | int w = 0;
|
| | | token[w++] = CRYPTOBYLEO_FERNET_VER;
|
2026-09-02 11:55:03 -05:00 | | | w = CNumberUtils::SValueToBytesBE(time, token, w); // -1defautl exacto, timstap
|
2026-09-02 10:54:31 -05:00 | | | TCryptoRandomFunc::RandomCryptoBytes(m_aes.m_iv, AES_BLOCKLEN, 0); // El iv lo copiamos al CBC de aes
|
2026-09-01 17:55:59 -05:00 | | | w += ArrayCopy(token, m_aes.m_iv, w, 0, AES_BLOCKLEN); // y tambien lo copiamos el token
|
| | |
|
| | |
|
| | | // Copiamos los datos al final
|
| | | FileReadArray(fh, token, w, data_t); // #1 copia de los datos
|
| | | FileClose(fh);
|
| | |
|
| | | //---
|
| | | const int t = CAes::PKCS7_CorrectPadding(token, data_t, w) - w; // tamaño exacto
|
| | | m_aes.CbcCifrado(token, t, w); // ciframos
|
| | | w += t; // movemos el puntero
|
| | | m_hmac.Update(token, w); // hmac
|
2026-09-02 12:50:09 -05:00 | | | w += ArrayCopy(token, m_hmac.m_out, w, 0, CRYPTOBYLEO_SHA256_SIZET_FHASH); // Copiamos el digest luego (append al final)
|
2026-09-02 11:55:03 -05:00 | | |
|
| | | //--- trim
|
| | | ArrayResize(token, w);
|
2026-09-01 17:55:59 -05:00 | | |
|
| | |
|
| | | //----- fin fermat
|
| | | const string fn_final = file_name + (ext_encrypt.Length() > 2 ? ext_encrypt : "");
|
| | | if(!FileSave(fn_final, token, common_file_flag))
|
| | | {
|
2026-09-02 12:50:09 -05:00 | | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_SAVE_CRYPTHF_ILE;
|
2026-09-01 17:55:59 -05:00 | | | return false;
|
| | | }
|
| | |
|
| | | //--- solo eleiminos si se nos pide y el archivo cambio de nombre no tiene sentido eliminiarlo
|
| | | // si se mantine (Eliminamso el encriptado)
|
| | | if(delete_prev_file && fn_final != file_name && !FileDelete(file_name, common_file_flag))
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_DEL_FILE_IN_CRYPT;
|
| | |
|
| | | //--- ahora si
|
| | | return true;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-09-02 10:01:34 -05:00 | | | bool CFernet::DecryptFile(const string &file_name, bool common_flag, bool delete_prev_file, uchar &res_data[], int ttl)
|
2026-09-01 17:55:59 -05:00 | | | {
|
| | | uchar in[];
|
| | | const int common_file_flag = (common_flag ? FILE_COMMON : 0);
|
| | | ::ResetLastError();
|
2026-09-02 11:55:03 -05:00 | | | const int bytes = (int)FileLoad(file_name, in, common_file_flag);
|
| | | if(bytes == -1)
|
2026-09-01 17:55:59 -05:00 | | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_DEC_FILE_LOAD_ERR;
|
| | | return false;
|
| | | }
|
| | |
|
| | | //---
|
2026-09-14 08:14:16 -05:00 | | | const int t = DecryptRaw(in, bytes, res_data, ttl);
|
| | | if(t == -1)
|
2026-09-01 17:55:59 -05:00 | | | return false;
|
| | |
|
2026-09-14 08:14:16 -05:00 | | | //---
|
| | | ArrayResize(res_data, t);
|
| | |
|
2026-09-01 17:55:59 -05:00 | | | //---
|
| | | ::ResetLastError();
|
| | | if(delete_prev_file && !FileDelete(file_name, common_file_flag))
|
| | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_DEC_FILE_DEL_ERR;
|
| | | }
|
| | |
|
| | | //---
|
| | | return true;
|
| | | }
|
| | |
|
2026-09-14 08:14:16 -05:00 | | | //+------------------------------------------------------------------+
|
| | | bool CFernet::DecryptFile(const string &file_name, bool common_flag, bool delete_prev_file,
|
| | | string &res_data, int ttl, uint cp = CP_ACP)
|
| | | {
|
| | | uchar res[];
|
| | | if(!DecryptFile(file_name, common_flag, delete_prev_file, res, ttl))
|
| | | return false;
|
| | | res_data = CharArrayToString(res, 0, WHOLE_ARRAY, cp);
|
| | | return true;
|
| | | }
|
| | |
|
2026-09-01 17:55:59 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| Desencripta un archivo |
|
| | | //| file_name : ruta del archivo encriptado |
|
| | | //| common_flag : true = carpeta Common, false = carpeta Files\ |
|
| | | //| delete_prev_file: true = elimina el archivo encriptado original |
|
| | | //| ext_decrypt : controla el nombre del archivo de salida: |
|
| | | //| - "" = sobreescribe el mismo archivo |
|
| | | //| - ".ext" = agrega extension file.enc → file.enc.ext |
|
| | | //| - "-" = quita la ultima extension file.enc → file |
|
| | | //| - ".ext-" = reemplaza ultima ext file.enc → file.ext |
|
| | | //+------------------------------------------------------------------+
|
2026-09-02 10:01:34 -05:00 | | | bool CFernet::DecryptFile(const string &file_name, bool common_flag, bool delete_prev_file, int ttl, string ext_decrypt = "")
|
2026-09-01 17:55:59 -05:00 | | | {
|
| | | uchar in[];
|
| | | const int common_file_flag = (common_flag ? FILE_COMMON : 0);
|
| | | ::ResetLastError();
|
2026-09-02 11:55:03 -05:00 | | | const int bytes = (int)FileLoad(file_name, in, common_file_flag);
|
| | | if(bytes == -1)
|
2026-09-01 17:55:59 -05:00 | | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_DEC_FILE_LOAD_ERR;
|
| | | return false;
|
| | | }
|
| | |
|
| | | //---
|
| | | uchar res_data[];
|
2026-09-02 11:55:03 -05:00 | | | const int t = DecryptRaw(in, bytes, res_data, ttl);
|
| | | if(t == -1)
|
2026-09-01 17:55:59 -05:00 | | | return false;
|
2026-09-02 11:55:03 -05:00 | | | //---
|
| | | ArrayResize(res_data, t);
|
2026-09-14 08:14:16 -05:00 | | | const int ext_decrypt_l = StringLen(ext_decrypt);
|
2026-09-01 17:55:59 -05:00 | | |
|
| | | //--- Creamos el archivo destino (o sobreescribimos si ext = "")
|
| | | // si ext_decrypt contiene el . entonces es exntesion si no el nombre del archivo out
|
| | | string out_file_name = "";
|
2026-09-14 08:14:16 -05:00 | | | if(CStringFunc::FindCh(ext_decrypt, '.', ext_decrypt_l))
|
2026-09-01 17:55:59 -05:00 | | | {
|
| | | const uint len = (ext_decrypt.Length());
|
| | | if(ext_decrypt[len - 1] == '-') // -. quiere decir elimina la extension previa y añade esta nueva
|
| | | {
|
| | | ext_decrypt.Truncate(len - 1); // quitamos el - final eg si tiewnmaos extdecurp como .txt- queda .txt
|
2026-09-14 08:14:16 -05:00 | | | out_file_name = CPathUtils::FileRemoveExtension(file_name) + ext_decrypt;
|
2026-09-01 17:55:59 -05:00 | | | }
|
| | | else
|
2026-09-14 08:14:16 -05:00 | | | {
|
2026-09-01 17:55:59 -05:00 | | | out_file_name = file_name + ext_decrypt;
|
| | | }
|
| | | }
|
| | | else
|
2026-09-14 08:14:16 -05:00 | | | if(CStringFunc::FindCh(ext_decrypt, '-', ext_decrypt_l)) // quiere decir solo quita la extension que ya tenia
|
2026-09-01 17:55:59 -05:00 | | | {
|
2026-09-14 08:14:16 -05:00 | | | out_file_name = CPathUtils::FileRemoveExtension(file_name); // Removes la primera extension (volvemos al extado original)
|
2026-09-01 17:55:59 -05:00 | | | }
|
| | | else
|
| | | {
|
| | | out_file_name = file_name; // lo mismo sobrescribe
|
| | | }
|
2026-09-01 12:16:15 -05:00 | | |
|
2026-09-01 17:55:59 -05:00 | | | //--- primero guardamos
|
| | | ::ResetLastError();
|
| | | if(!FileSave(out_file_name, res_data, common_file_flag))
|
| | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_DEC_FILE_SAVE_ERR;
|
| | | return false;
|
| | | }
|
2026-09-01 12:16:15 -05:00 | | |
|
2026-09-01 17:55:59 -05:00 | | | //--- Ahora si eliminamos el archivo previo si es que se pide
|
| | | ::ResetLastError();
|
| | | if(delete_prev_file && !FileDelete(file_name, common_file_flag))
|
| | | {
|
| | | m_last_err = CRYPTOBYLEO_FERNAT_ERR_DEC_FILE_DEL_ERR;
|
| | | }
|
2026-09-01 12:16:15 -05:00 | | |
|
2026-09-01 17:55:59 -05:00 | | | //---
|
| | | return true;
|
2026-09-01 12:16:15 -05:00 | | | }
|
| | |
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | #endif // CRYPTOBYLEO_SRC_FERNET_MAIN_MQH
|