8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 18:43:02 +01:00

Post-improvement for CORE-5970: added 3 useful related helper functions: base64_encode/decode and crc32

This commit is contained in:
AlexPeshkoff 2019-01-05 18:29:03 +03:00
parent 61a905e096
commit 38823d0184
6 changed files with 235 additions and 13 deletions

View File

@ -177,6 +177,21 @@ Example:
select atanh(x) from y; select atanh(x) from y;
-----------------------------
BASE64_ENCODE / BASE64_DECODE
-----------------------------
Function:
Encodes / decodes input data to / from BASE64 representation. Works with character strings and blobs.
Format:
BASE64_ENCODE( <binary data> )
BASE64_DECODE( <base64 data> )
Example:
select base64_encode(public_key) from clients;
------- -------
BIN_AND BIN_AND
------- -------
@ -346,6 +361,20 @@ Example:
select cot(x) from y; select cot(x) from y;
-----
CRC32
-----
Function:
Returns CRC-32 with the polynomial 0x04C11DB7. Accepts argument of any type.
Format:
CRC32( <any value> )
Example:
select crc32(job_title) from job;
------- -------
DATEADD DATEADD
------- -------

View File

@ -448,6 +448,8 @@ using namespace Firebird;
%token <metaNamePtr> ASIN %token <metaNamePtr> ASIN
%token <metaNamePtr> ATAN %token <metaNamePtr> ATAN
%token <metaNamePtr> ATAN2 %token <metaNamePtr> ATAN2
%token <metaNamePtr> BASE64_DECODE
%token <metaNamePtr> BASE64_ENCODE
%token <metaNamePtr> BIN_AND %token <metaNamePtr> BIN_AND
%token <metaNamePtr> BIN_OR %token <metaNamePtr> BIN_OR
%token <metaNamePtr> BIN_SHL %token <metaNamePtr> BIN_SHL
@ -458,6 +460,7 @@ using namespace Firebird;
%token <metaNamePtr> COS %token <metaNamePtr> COS
%token <metaNamePtr> COSH %token <metaNamePtr> COSH
%token <metaNamePtr> COT %token <metaNamePtr> COT
%token <metaNamePtr> CRC32
%token <metaNamePtr> DATEADD %token <metaNamePtr> DATEADD
%token <metaNamePtr> DATEDIFF %token <metaNamePtr> DATEDIFF
%token <metaNamePtr> DECODE %token <metaNamePtr> DECODE
@ -7881,6 +7884,8 @@ system_function_std_syntax
| ATAN | ATAN
| ATAN2 | ATAN2
| ATANH | ATANH
| BASE64_DECODE
| BASE64_ENCODE
| BIN_AND | BIN_AND
| BIN_NOT | BIN_NOT
| BIN_OR | BIN_OR
@ -7892,6 +7897,7 @@ system_function_std_syntax
| COS | COS
| COSH | COSH
| COT | COT
| CRC32
| EXP | EXP
| FLOOR | FLOOR
| GEN_UUID | GEN_UUID
@ -8813,6 +8819,9 @@ non_reserved_word
| RSA_VERIFY | RSA_VERIFY
| SALT_LENGTH | SALT_LENGTH
| SIGNATURE | SIGNATURE
| BASE64_DECODE
| BASE64_ENCODE
| CRC32
; ;
%% %%

View File

@ -218,10 +218,10 @@ void makeBin(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* r
void makeBinShift(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeBinShift(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeCeilFloor(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeCeilFloor(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeDateAdd(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeDateAdd(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeEncrypt(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeDecode64(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeEncode64(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeDecrypt(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeDecrypt(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeRsaEncrypt(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeEncrypt(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeRsaDecrypt(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeFirstLastDayResult(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeFirstLastDayResult(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeGetSetContext(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeGetSetContext(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeGetTranCN(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeGetTranCN(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
@ -234,6 +234,8 @@ void makePi(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* re
void makeReplace(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeReplace(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeReverse(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeReverse(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeRound(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeRound(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeRsaDecrypt(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeRsaEncrypt(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeRsaPrivate(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeRsaPrivate(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeRsaPublic(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeRsaPublic(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
void makeRsaSign(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeRsaSign(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args);
@ -253,8 +255,11 @@ dsc* evlBin(thread_db* tdbb, const SysFunction* function, const NestValueArray&
dsc* evlBinShift(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlBinShift(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlCeil(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlCeil(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlCharToUuid(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlCharToUuid(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlCrc32(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlDateAdd(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlDateAdd(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlDateDiff(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlDateDiff(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlDecode64(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlEncode64(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlDecrypt(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlDecrypt(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlEncrypt(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlEncrypt(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlRsaDecrypt(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlRsaDecrypt(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
@ -1228,6 +1233,56 @@ void makeHash(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc*
} }
void raise(const char* x)
{
(Arg::Gds(isc_random) << x).raise();
}
unsigned decodeLen(unsigned len)
{
if (len % 4 || !len)
raise("Invalid parameter length");
len = len / 4 * 3;
return len;
}
void makeDecode64(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args)
{
fb_assert(argsCount == 1);
if (args[0]->isBlob())
result->makeBlob(isc_blob_untyped, ttype_binary);
else if (args[0]->isText())
result->makeVarying(decodeLen(args[0]->getStringLength()), ttype_binary);
else
raise("Invalid parameter datatype - need string or blob");
result->setNullable(args[0]->isNullable());
}
unsigned encodeLen(unsigned len)
{
len = (len + 2) / 3 * 4;
return len;
}
void makeEncode64(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args)
{
fb_assert(argsCount == 1);
if (args[0]->isBlob())
result->makeBlob(isc_blob_text, ttype_ascii);
else if (args[0]->isText())
result->makeVarying(encodeLen(args[0]->dsc_length), ttype_ascii);
else
raise("Invalid parameter datatype - need string or blob");
result->setNullable(args[0]->isNullable());
}
void makeEncrypt(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, void makeEncrypt(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result,
int argsCount, const dsc** args) int argsCount, const dsc** args)
{ {
@ -2361,12 +2416,6 @@ dsc* evlDateAdd(thread_db* tdbb, const SysFunction* function, const NestValueArr
return &impure->vlu_desc; return &impure->vlu_desc;
} }
void raise(const char* x)
{
(Arg::Gds(isc_random) << x).raise();
}
// Prepare tomcrypt library // Prepare tomcrypt library
class TomcryptInitializer class TomcryptInitializer
@ -2449,7 +2498,9 @@ private:
InitInstance<PseudoRandom> prng; InitInstance<PseudoRandom> prng;
// Data exchanger between tommath and firebird // Data exchange between tommath and firebird
const UCHAR streamBpb[] = {isc_bpb_version1, isc_bpb_type, 1, isc_bpb_type_stream};
class DataPipe class DataPipe
{ {
@ -2477,11 +2528,11 @@ public:
try try
{ {
const UCHAR bpb[] = {isc_bpb_version1, isc_bpb_type, 1, isc_bpb_type_stream}; const UCHAR streamBpb[] = {isc_bpb_version1, isc_bpb_type, 1, isc_bpb_type_stream};
newBlob = blb::create2(tdbb, tdbb->getRequest()->req_transaction, &impure->vlu_misc.vlu_bid, newBlob = blb::create2(tdbb, tdbb->getRequest()->req_transaction, &impure->vlu_misc.vlu_bid,
sizeof(bpb), bpb); sizeof(streamBpb), streamBpb);
blob = blb::open2(tdbb, tdbb->getRequest()->req_transaction, reinterpret_cast<bid*>(desc->dsc_address), blob = blb::open2(tdbb, tdbb->getRequest()->req_transaction, reinterpret_cast<bid*>(desc->dsc_address),
sizeof(bpb), bpb); sizeof(streamBpb), streamBpb);
ptr = inBuf.getBuffer(BLOB_STEP); ptr = inBuf.getBuffer(BLOB_STEP);
len = blob->BLB_get_data(tdbb, inBuf.begin(), inBuf.getCount(), false); len = blob->BLB_get_data(tdbb, inBuf.begin(), inBuf.getCount(), false);
@ -2910,6 +2961,118 @@ dsc* evlDecrypt(thread_db* tdbb, const SysFunction* function, const NestValueArr
} }
dsc* evlEncodeDecode64(thread_db* tdbb, bool encodeFlag, const SysFunction* function, const NestValueArray& args, impure_value* impure)
{
const dsc* arg = EVL_expr(tdbb, tdbb->getRequest(), args[0]);
if (!arg) // return NULL if value is NULL
return NULL;
UCharBuffer in;
if (arg->isBlob())
{
AutoPtr<blb> blob(blb::open2(tdbb, tdbb->getRequest()->req_transaction, reinterpret_cast<const bid*>(arg->dsc_address),
sizeof(streamBpb), streamBpb));
UCHAR buf[4096];
in.clear();
for(;;)
{
const unsigned l = blob->BLB_get_data(tdbb, buf, sizeof buf, false);
if (!l)
break;
in.append(buf, l);
}
blob->BLB_close(tdbb);
blob.release();
}
else
{
unsigned len;
const UCHAR* ptr = CVT_get_bytes(arg, len);
in.assign(ptr, len);
}
UCharBuffer out;
unsigned long outLen = encodeFlag ? encodeLen(in.getCount()) + 1 : decodeLen(in.getCount());
auto* func = encodeFlag ? base64_encode : base64_decode;
auto* msg = encodeFlag ? "encoding BASE64" : "decoding BASE64";
tomCheck(func(in.begin(), in.getCount(), out.getBuffer(outLen), &outLen), msg);
out.resize(outLen);
dsc result;
if (arg->isBlob())
{
AutoPtr<blb> blob(blb::create2(tdbb, tdbb->getRequest()->req_transaction, &impure->vlu_misc.vlu_bid,
sizeof(streamBpb), streamBpb));
blob->BLB_put_data(tdbb, out.begin(), out.getCount());
blob->BLB_close(tdbb);
blob.release();
result.makeBlob(encodeFlag ? isc_blob_text : isc_blob_untyped, encodeFlag ? ttype_ascii : ttype_binary,
(ISC_QUAD*)&impure->vlu_misc.vlu_bid);
}
else
result.makeText(out.getCount(), encodeFlag ? ttype_ascii : ttype_binary, const_cast<UCHAR*>(out.begin()));
EVL_make_value(tdbb, &result, impure);
return &impure->vlu_desc;
}
dsc* evlDecode64(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure)
{
return evlEncodeDecode64(tdbb, false, function, args, impure);
}
dsc* evlEncode64(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure)
{
return evlEncodeDecode64(tdbb, true, function, args, impure);
}
dsc* evlCrc32(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure)
{
crc32_state ctx;
crc32_init(&ctx);
const dsc* arg = EVL_expr(tdbb, tdbb->getRequest(), args[0]);
if (!arg) // return NULL if value is NULL
return NULL;
if (arg->isBlob())
{
blb* blob = blb::open2(tdbb, tdbb->getRequest()->req_transaction, reinterpret_cast<const bid*>(arg->dsc_address),
sizeof(streamBpb), streamBpb);
UCHAR buf[4096];
for(;;)
{
const unsigned l = blob->BLB_get_data(tdbb, buf, sizeof buf, false);
if (!l)
break;
crc32_update(&ctx, buf, l);
}
blob->BLB_close(tdbb);
}
else
{
unsigned len;
const UCHAR* ptr = CVT_get_bytes(arg, len);
crc32_update(&ctx, ptr, len);
}
SLONG hash;
crc32_finish(&ctx, &hash, sizeof hash);
dsc result;
result.makeLong(0, &hash);
EVL_make_value(tdbb, &result, impure);
return &impure->vlu_desc;
}
dsc* evlRsaEncryptDecrypt(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, dsc* evlRsaEncryptDecrypt(thread_db* tdbb, const SysFunction* function, const NestValueArray& args,
impure_value* impure, bool encryptFlag) impure_value* impure, bool encryptFlag)
{ {
@ -5687,6 +5850,9 @@ const SysFunction SysFunction::functions[] =
{"ATAN", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfAtan}, {"ATAN", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfAtan},
{"ATANH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfAtanh}, {"ATANH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfAtanh},
{"ATAN2", 2, 2, setParamsDouble, makeDoubleResult, evlAtan2, NULL}, {"ATAN2", 2, 2, setParamsDouble, makeDoubleResult, evlAtan2, NULL},
{"BASE64_DECODE", 1, 1, NULL, makeDecode64, evlDecode64, NULL},
{"BASE64_ENCODE", 1, 1, NULL, makeEncode64, evlEncode64, NULL},
{"CRC32", 1, 1, NULL, makeLongResult, evlCrc32, NULL},
{"BIN_AND", 2, -1, setParamsInteger, makeBin, evlBin, (void*) funBinAnd}, {"BIN_AND", 2, -1, setParamsInteger, makeBin, evlBin, (void*) funBinAnd},
{"BIN_NOT", 1, 1, setParamsInteger, makeBin, evlBin, (void*) funBinNot}, {"BIN_NOT", 1, 1, setParamsInteger, makeBin, evlBin, (void*) funBinNot},
{"BIN_OR", 2, -1, setParamsInteger, makeBin, evlBin, (void*) funBinOr}, {"BIN_OR", 2, -1, setParamsInteger, makeBin, evlBin, (void*) funBinOr},

View File

@ -2969,3 +2969,8 @@ void blb::storeToPage(USHORT* length, Firebird::Array<UCHAR>& buffer, const UCHA
} }
} }
} }
void blb::BLB_cancel()
{
BLB_cancel(JRD_get_thread_data());
}

View File

@ -33,6 +33,7 @@
#include "../jrd/EngineInterface.h" #include "../jrd/EngineInterface.h"
#include "../common/classes/array.h" #include "../common/classes/array.h"
#include "../common/classes/File.h" #include "../common/classes/File.h"
#include "../common/classes/auto.h"
#include "firebird/Interface.h" #include "firebird/Interface.h"
#include "../common/classes/ImplementHelper.h" #include "../common/classes/ImplementHelper.h"
@ -97,6 +98,7 @@ public:
// end inline // end inline
void BLB_cancel(thread_db* tdbb); void BLB_cancel(thread_db* tdbb);
void BLB_cancel();
void BLB_check_well_formed(thread_db*, const dsc* desc); void BLB_check_well_formed(thread_db*, const dsc* desc);
bool BLB_close(thread_db*); bool BLB_close(thread_db*);
static blb* create(thread_db*, jrd_tra*, bid*); static blb* create(thread_db*, jrd_tra*, bid*);
@ -245,4 +247,12 @@ inline USHORT blb::getMaxSegment() const
} //namespace Jrd } //namespace Jrd
template <>
inline void Firebird::SimpleDelete<Jrd::blb>::clear(Jrd::blb* b)
{
if (b)
b->BLB_cancel();
}
#endif // JRD_BLB_H #endif // JRD_BLB_H

View File

@ -84,6 +84,8 @@ static const TOK tokens[] =
{TOK_AUTONOMOUS, "AUTONOMOUS", true}, {TOK_AUTONOMOUS, "AUTONOMOUS", true},
{TOK_AVG, "AVG", false}, {TOK_AVG, "AVG", false},
{TOK_BACKUP, "BACKUP", true}, {TOK_BACKUP, "BACKUP", true},
{TOK_BASE64_DECODE, "BASE64_DECODE", true},
{TOK_BASE64_ENCODE, "BASE64_ENCODE", true},
{TOK_BEFORE, "BEFORE", true}, {TOK_BEFORE, "BEFORE", true},
{TOK_BEGIN, "BEGIN", false}, {TOK_BEGIN, "BEGIN", false},
{TOK_BETWEEN, "BETWEEN", false}, {TOK_BETWEEN, "BETWEEN", false},
@ -143,6 +145,7 @@ static const TOK tokens[] =
{TOK_COUNTER, "COUNTER", true}, {TOK_COUNTER, "COUNTER", true},
{TOK_COVAR_POP, "COVAR_POP", false}, {TOK_COVAR_POP, "COVAR_POP", false},
{TOK_COVAR_SAMP, "COVAR_SAMP", false}, {TOK_COVAR_SAMP, "COVAR_SAMP", false},
{TOK_CRC32, "CRC32", true},
{TOK_CREATE, "CREATE", false}, {TOK_CREATE, "CREATE", false},
{TOK_CROSS, "CROSS", false}, {TOK_CROSS, "CROSS", false},
{TOK_CSTRING, "CSTRING", true}, {TOK_CSTRING, "CSTRING", true},