support for delphi 11.1
This commit is contained in:
666
contrib/mORMot/SQLite3/amalgamation/ciphers/cipher_common.c
Normal file
666
contrib/mORMot/SQLite3/amalgamation/ciphers/cipher_common.c
Normal file
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
** Name: cipher_common.c
|
||||
** Purpose: Implementation of SQLite codecs
|
||||
** Author: Ulrich Telle
|
||||
** Created: 2020-02-02
|
||||
** Copyright: (c) 2006-2020 Ulrich Telle
|
||||
** License: MIT
|
||||
*/
|
||||
|
||||
#include "cipher_common.h"
|
||||
|
||||
static unsigned char padding[] =
|
||||
"\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
|
||||
|
||||
/* --- Codec Descriptor Table --- */
|
||||
|
||||
/*
|
||||
** Common configuration parameters
|
||||
**
|
||||
** - cipher : default cipher type
|
||||
** - hmac_check : flag whether page hmac should be verified on read
|
||||
*/
|
||||
|
||||
static CipherParams commonParams[] =
|
||||
{
|
||||
{ "cipher", CODEC_TYPE, CODEC_TYPE, 1, CODEC_TYPE_MAX },
|
||||
{ "hmac_check", 1, 1, 0, 1 },
|
||||
CIPHER_PARAMS_SENTINEL
|
||||
};
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetCipherParameter(CipherParams* cipherParams, const char* paramName)
|
||||
{
|
||||
int value = -1;
|
||||
for (; strlen(cipherParams->m_name) > 0; ++cipherParams)
|
||||
{
|
||||
if (sqlite3_stricmp(paramName, cipherParams->m_name) == 0) break;
|
||||
}
|
||||
if (strlen(cipherParams->m_name) > 0)
|
||||
{
|
||||
value = cipherParams->m_value;
|
||||
cipherParams->m_value = cipherParams->m_default;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static CodecParameter globalCodecParameterTable[] =
|
||||
{
|
||||
{ "global", CODEC_TYPE_UNKNOWN, commonParams },
|
||||
#if HAVE_CIPHER_AES_128_CBC
|
||||
{ "aes128cbc", CODEC_TYPE_AES128, mcAES128Params },
|
||||
#endif
|
||||
#if HAVE_CIPHER_AES_256_CBC
|
||||
{ "aes256cbc", CODEC_TYPE_AES256, mcAES256Params },
|
||||
#endif
|
||||
#if HAVE_CIPHER_CHACHA20
|
||||
{ "chacha20", CODEC_TYPE_CHACHA20, mcChaCha20Params },
|
||||
#endif
|
||||
#if HAVE_CIPHER_SQLCIPHER
|
||||
{ "sqlcipher", CODEC_TYPE_SQLCIPHER, mcSQLCipherParams },
|
||||
#endif
|
||||
#if HAVE_CIPHER_RC4
|
||||
{ "rc4", CODEC_TYPE_RC4, mcRC4Params },
|
||||
#endif
|
||||
{ "", CODEC_TYPE_UNKNOWN, NULL }
|
||||
};
|
||||
|
||||
#define CODEC_TYPE_UNKNOWN 0
|
||||
#define CODEC_TYPE_AES128 1
|
||||
#define CODEC_TYPE_AES256 2
|
||||
#define CODEC_TYPE_CHACHA20 3
|
||||
#define CODEC_TYPE_SQLCIPHER 4
|
||||
#define CODEC_TYPE_RC4 5
|
||||
|
||||
SQLITE_PRIVATE CodecParameter*
|
||||
sqlite3mcCloneCodecParameterTable()
|
||||
{
|
||||
/* Count number of codecs and cipher parameters */
|
||||
int nTables = 0;
|
||||
int nParams = 0;
|
||||
int j, k, n;
|
||||
CipherParams* cloneCipherParams;
|
||||
CodecParameter* cloneCodecParams;
|
||||
|
||||
for (j = 0; strlen(globalCodecParameterTable[j].m_name) > 0; ++j)
|
||||
{
|
||||
CipherParams* params = globalCodecParameterTable[j].m_params;
|
||||
for (k = 0; strlen(params[k].m_name) > 0; ++k);
|
||||
nParams += k;
|
||||
}
|
||||
nTables = j;
|
||||
|
||||
/* Allocate memory for cloned codec parameter tables (including sentinel for each table) */
|
||||
cloneCipherParams = (CipherParams*) sqlite3_malloc((nParams + nTables) * sizeof(CipherParams));
|
||||
cloneCodecParams = (CodecParameter*) sqlite3_malloc((nTables + 1) * sizeof(CodecParameter));
|
||||
|
||||
/* Create copy of tables */
|
||||
if (cloneCodecParams != NULL)
|
||||
{
|
||||
int offset = 0;
|
||||
for (j = 0; j < nTables; ++j)
|
||||
{
|
||||
CipherParams* params = globalCodecParameterTable[j].m_params;
|
||||
cloneCodecParams[j].m_name = globalCodecParameterTable[j].m_name;
|
||||
cloneCodecParams[j].m_params = &cloneCipherParams[offset];
|
||||
for (n = 0; strlen(params[n].m_name) > 0; ++n);
|
||||
/* Copy all parameters of the current table (including sentinel) */
|
||||
for (k = 0; k <= n; ++k)
|
||||
{
|
||||
cloneCipherParams[offset + k].m_name = params[k].m_name;
|
||||
cloneCipherParams[offset + k].m_value = params[k].m_value;
|
||||
cloneCipherParams[offset + k].m_default = params[k].m_default;
|
||||
cloneCipherParams[offset + k].m_minValue = params[k].m_minValue;
|
||||
cloneCipherParams[offset + k].m_maxValue = params[k].m_maxValue;
|
||||
}
|
||||
offset += (n + 1);
|
||||
}
|
||||
cloneCodecParams[nTables].m_name = globalCodecParameterTable[nTables].m_name;
|
||||
cloneCodecParams[nTables].m_params = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlite3_free(cloneCipherParams);
|
||||
}
|
||||
return cloneCodecParams;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcFreeCodecParameterTable(CodecParameter* codecParams)
|
||||
{
|
||||
sqlite3_free(codecParams[0].m_params);
|
||||
sqlite3_free(codecParams);
|
||||
}
|
||||
|
||||
static const CipherDescriptor mcSentinelDescriptor =
|
||||
{
|
||||
"", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static const CipherDescriptor mcDummyDescriptor =
|
||||
{
|
||||
"@dummy@", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static const CipherDescriptor* codecDescriptorTable[] =
|
||||
{
|
||||
#if HAVE_CIPHER_AES_128_CBC
|
||||
&mcAES128Descriptor,
|
||||
#else
|
||||
&mcDummyDescriptor,
|
||||
#endif
|
||||
#if HAVE_CIPHER_AES_256_CBC
|
||||
&mcAES256Descriptor,
|
||||
#else
|
||||
&mcDummyDescriptor,
|
||||
#endif
|
||||
#if HAVE_CIPHER_CHACHA20
|
||||
&mcChaCha20Descriptor,
|
||||
#else
|
||||
&mcDummyDescriptor,
|
||||
#endif
|
||||
#if HAVE_CIPHER_SQLCIPHER
|
||||
&mcSQLCipherDescriptor,
|
||||
#else
|
||||
&mcDummyDescriptor,
|
||||
#endif
|
||||
#if HAVE_CIPHER_RC4
|
||||
&mcRC4Descriptor,
|
||||
#else
|
||||
&mcDummyDescriptor,
|
||||
#endif
|
||||
&mcSentinelDescriptor
|
||||
};
|
||||
|
||||
/* --- Codec --- */
|
||||
|
||||
SQLITE_PRIVATE CodecParameter*
|
||||
sqlite3mcGetCodecParams(sqlite3* db);
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetCipherType(sqlite3* db)
|
||||
{
|
||||
CodecParameter* codecParams = (db != NULL) ? sqlite3mcGetCodecParams(db) : globalCodecParameterTable;
|
||||
CipherParams* cipherParamTable = (codecParams != NULL) ? codecParams[0].m_params : commonParams;
|
||||
int cipherType = CODEC_TYPE;
|
||||
CipherParams* cipher = cipherParamTable;
|
||||
for (; strlen(cipher->m_name) > 0; ++cipher)
|
||||
{
|
||||
if (sqlite3_stricmp("cipher", cipher->m_name) == 0) break;
|
||||
}
|
||||
if (strlen(cipher->m_name) > 0)
|
||||
{
|
||||
cipherType = cipher->m_value;
|
||||
cipher->m_value = cipher->m_default;
|
||||
}
|
||||
return cipherType;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE CipherParams*
|
||||
sqlite3mcGetCipherParams(sqlite3* db, int cypherType)
|
||||
{
|
||||
CodecParameter* codecParams = (db != NULL) ? sqlite3mcGetCodecParams(db) : globalCodecParameterTable;
|
||||
CipherParams* cipherParamTable = (codecParams != NULL) ? codecParams[cypherType].m_params : globalCodecParameterTable[cypherType].m_params;
|
||||
return cipherParamTable;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcCodecInit(Codec* codec)
|
||||
{
|
||||
int rc = SQLITE_OK;
|
||||
if (codec != NULL)
|
||||
{
|
||||
codec->m_isEncrypted = 0;
|
||||
codec->m_hmacCheck = 1;
|
||||
|
||||
codec->m_hasReadCipher = 0;
|
||||
codec->m_readCipherType = CODEC_TYPE_UNKNOWN;
|
||||
codec->m_readCipher = NULL;
|
||||
codec->m_readReserved = -1;
|
||||
|
||||
codec->m_hasWriteCipher = 0;
|
||||
codec->m_writeCipherType = CODEC_TYPE_UNKNOWN;
|
||||
codec->m_writeCipher = NULL;
|
||||
codec->m_writeReserved = -1;
|
||||
|
||||
codec->m_db = NULL;
|
||||
codec->m_bt = NULL;
|
||||
codec->m_btShared = NULL;
|
||||
memset(codec->m_page, 0, sizeof(codec->m_page));
|
||||
codec->m_pageSize = 0;
|
||||
codec->m_reserved = 0;
|
||||
codec->m_hasKeySalt = 0;
|
||||
memset(codec->m_keySalt, 0, sizeof(codec->m_keySalt));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcCodecTerm(Codec* codec)
|
||||
{
|
||||
if (codec->m_readCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_readCipherType - 1]->m_freeCipher(codec->m_readCipher);
|
||||
codec->m_readCipher = NULL;
|
||||
}
|
||||
if (codec->m_writeCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType - 1]->m_freeCipher(codec->m_writeCipher);
|
||||
codec->m_writeCipher = NULL;
|
||||
}
|
||||
memset(codec, 0, sizeof(Codec));
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcClearKeySalt(Codec* codec)
|
||||
{
|
||||
codec->m_hasKeySalt = 0;
|
||||
memset(codec->m_keySalt, 0, sizeof(codec->m_keySalt));
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcCodecSetup(Codec* codec, int cipherType, char* userPassword, int passwordLength)
|
||||
{
|
||||
int rc = SQLITE_OK;
|
||||
CipherParams* globalParams = sqlite3mcGetCipherParams(codec->m_db, 0);
|
||||
codec->m_isEncrypted = 1;
|
||||
codec->m_hmacCheck = sqlite3mcGetCipherParameter(globalParams, "hmac_check");
|
||||
codec->m_hasReadCipher = 1;
|
||||
codec->m_hasWriteCipher = 1;
|
||||
codec->m_readCipherType = cipherType;
|
||||
codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType-1]->m_allocateCipher(codec->m_db);
|
||||
if (codec->m_readCipher != NULL)
|
||||
{
|
||||
unsigned char* keySalt = (codec->m_hasKeySalt != 0) ? codec->m_keySalt : NULL;
|
||||
sqlite3mcGenerateReadKey(codec, userPassword, passwordLength, keySalt);
|
||||
rc = sqlite3mcCopyCipher(codec, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcSetupWriteCipher(Codec* codec, int cipherType, char* userPassword, int passwordLength)
|
||||
{
|
||||
int rc = SQLITE_OK;
|
||||
CipherParams* globalParams = sqlite3mcGetCipherParams(codec->m_db, 0);
|
||||
if (codec->m_writeCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType-1]->m_freeCipher(codec->m_writeCipher);
|
||||
}
|
||||
codec->m_isEncrypted = 1;
|
||||
codec->m_hmacCheck = sqlite3mcGetCipherParameter(globalParams, "hmac_check");
|
||||
codec->m_hasWriteCipher = 1;
|
||||
codec->m_writeCipherType = cipherType;
|
||||
codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType-1]->m_allocateCipher(codec->m_db);
|
||||
if (codec->m_writeCipher != NULL)
|
||||
{
|
||||
unsigned char* keySalt = (codec->m_hasKeySalt != 0) ? codec->m_keySalt : NULL;
|
||||
sqlite3mcGenerateWriteKey(codec, userPassword, passwordLength, keySalt);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetIsEncrypted(Codec* codec, int isEncrypted)
|
||||
{
|
||||
codec->m_isEncrypted = isEncrypted;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetReadCipherType(Codec* codec, int cipherType)
|
||||
{
|
||||
codec->m_readCipherType = cipherType;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetWriteCipherType(Codec* codec, int cipherType)
|
||||
{
|
||||
codec->m_writeCipherType = cipherType;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetHasReadCipher(Codec* codec, int hasReadCipher)
|
||||
{
|
||||
codec->m_hasReadCipher = hasReadCipher;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetHasWriteCipher(Codec* codec, int hasWriteCipher)
|
||||
{
|
||||
codec->m_hasWriteCipher = hasWriteCipher;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetDb(Codec* codec, sqlite3* db)
|
||||
{
|
||||
codec->m_db = db;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetBtree(Codec* codec, Btree* bt)
|
||||
{
|
||||
codec->m_bt = bt;
|
||||
codec->m_btShared = bt->pBt;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetReadReserved(Codec* codec, int reserved)
|
||||
{
|
||||
codec->m_readReserved = reserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetWriteReserved(Codec* codec, int reserved)
|
||||
{
|
||||
codec->m_writeReserved = reserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcIsEncrypted(Codec* codec)
|
||||
{
|
||||
return codec->m_isEncrypted;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcHasReadCipher(Codec* codec)
|
||||
{
|
||||
return codec->m_hasReadCipher;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcHasWriteCipher(Codec* codec)
|
||||
{
|
||||
return codec->m_hasWriteCipher;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE Btree*
|
||||
sqlite3mcGetBtree(Codec* codec)
|
||||
{
|
||||
return codec->m_bt;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE BtShared*
|
||||
sqlite3mcGetBtShared(Codec* codec)
|
||||
{
|
||||
return codec->m_btShared;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetPageSize(Codec* codec)
|
||||
{
|
||||
return codec->m_btShared->pageSize;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetReadReserved(Codec* codec)
|
||||
{
|
||||
return codec->m_readReserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetWriteReserved(Codec* codec)
|
||||
{
|
||||
return codec->m_writeReserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE unsigned char*
|
||||
sqlite3mcGetPageBuffer(Codec* codec)
|
||||
{
|
||||
return &codec->m_page[4];
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetLegacyReadCipher(Codec* codec)
|
||||
{
|
||||
int legacy = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType - 1]->m_getLegacy(codec->m_readCipher) : 0;
|
||||
return legacy;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetLegacyWriteCipher(Codec* codec)
|
||||
{
|
||||
int legacy = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getLegacy(codec->m_writeCipher) : -1;
|
||||
return legacy;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetPageSizeReadCipher(Codec* codec)
|
||||
{
|
||||
int pageSize = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType - 1]->m_getPageSize(codec->m_readCipher) : 0;
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetPageSizeWriteCipher(Codec* codec)
|
||||
{
|
||||
int pageSize = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getPageSize(codec->m_writeCipher) : -1;
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetReservedReadCipher(Codec* codec)
|
||||
{
|
||||
int reserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType-1]->m_getReserved(codec->m_readCipher) : -1;
|
||||
return reserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetReservedWriteCipher(Codec* codec)
|
||||
{
|
||||
int reserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType-1]->m_getReserved(codec->m_writeCipher) : -1;
|
||||
return reserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcReservedEqual(Codec* codec)
|
||||
{
|
||||
int readReserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType-1]->m_getReserved(codec->m_readCipher) : -1;
|
||||
int writeReserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType-1]->m_getReserved(codec->m_writeCipher) : -1;
|
||||
return (readReserved == writeReserved);
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE unsigned char*
|
||||
sqlite3mcGetSaltWriteCipher(Codec* codec)
|
||||
{
|
||||
unsigned char* salt = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getSalt(codec->m_writeCipher) : NULL;
|
||||
return salt;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcCodecCopy(Codec* codec, Codec* other)
|
||||
{
|
||||
int rc = SQLITE_OK;
|
||||
codec->m_isEncrypted = other->m_isEncrypted;
|
||||
codec->m_hmacCheck = other->m_hmacCheck;
|
||||
codec->m_hasReadCipher = other->m_hasReadCipher;
|
||||
codec->m_hasWriteCipher = other->m_hasWriteCipher;
|
||||
codec->m_readCipherType = other->m_readCipherType;
|
||||
codec->m_writeCipherType = other->m_writeCipherType;
|
||||
codec->m_readCipher = NULL;
|
||||
codec->m_writeCipher = NULL;
|
||||
codec->m_readReserved = other->m_readReserved;
|
||||
codec->m_writeReserved = other->m_writeReserved;
|
||||
|
||||
if (codec->m_hasReadCipher)
|
||||
{
|
||||
codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType - 1]->m_allocateCipher(codec->m_db);
|
||||
if (codec->m_readCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_readCipherType - 1]->m_cloneCipher(codec->m_readCipher, other->m_readCipher);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if (codec->m_hasWriteCipher)
|
||||
{
|
||||
codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType - 1]->m_allocateCipher(codec->m_db);
|
||||
if (codec->m_writeCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType - 1]->m_cloneCipher(codec->m_writeCipher, other->m_writeCipher);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
codec->m_db = other->m_db;
|
||||
codec->m_bt = other->m_bt;
|
||||
codec->m_btShared = other->m_btShared;
|
||||
return rc;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcCodecCompare(Codec* codec1, Codec* codec2)
|
||||
{
|
||||
int equal = 0;
|
||||
if (codec1->m_hasReadCipher == codec2->m_hasReadCipher &&
|
||||
codec1->m_hasWriteCipher == codec2->m_hasWriteCipher)
|
||||
{
|
||||
int eqRead = (codec1->m_hasReadCipher) ? codec1->m_readCipherType == codec2->m_readCipherType : 1;
|
||||
int eqWrite = (codec1->m_hasWriteCipher) ? codec1->m_writeCipherType == codec2->m_writeCipherType : 1;
|
||||
if (eqRead && eqWrite)
|
||||
{
|
||||
eqRead = (codec1->m_hasReadCipher) ? codecDescriptorTable[codec1->m_readCipherType - 1]->m_compareCipher(codec1->m_readCipher, codec2->m_readCipher) : 1;
|
||||
eqWrite = (codec1->m_hasWriteCipher) ? codecDescriptorTable[codec1->m_writeCipherType - 1]->m_compareCipher(codec1->m_writeCipher, codec2->m_writeCipher) : 1;
|
||||
equal = eqRead && eqWrite;
|
||||
}
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcCopyCipher(Codec* codec, int read2write)
|
||||
{
|
||||
int rc = SQLITE_OK;
|
||||
if (read2write)
|
||||
{
|
||||
if (codec->m_writeCipher != NULL && codec->m_writeCipherType != codec->m_readCipherType)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType-1]->m_freeCipher(codec->m_writeCipher);
|
||||
codec->m_writeCipher = NULL;
|
||||
}
|
||||
if (codec->m_writeCipher == NULL)
|
||||
{
|
||||
codec->m_writeCipherType = codec->m_readCipherType;
|
||||
codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType-1]->m_allocateCipher(codec->m_db);
|
||||
}
|
||||
if (codec->m_writeCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType-1]->m_cloneCipher(codec->m_writeCipher, codec->m_readCipher);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (codec->m_readCipher != NULL && codec->m_readCipherType != codec->m_writeCipherType)
|
||||
{
|
||||
codecDescriptorTable[codec->m_readCipherType-1]->m_freeCipher(codec->m_readCipher);
|
||||
codec->m_readCipher = NULL;
|
||||
}
|
||||
if (codec->m_readCipher == NULL)
|
||||
{
|
||||
codec->m_readCipherType = codec->m_writeCipherType;
|
||||
codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType-1]->m_allocateCipher(codec->m_db);
|
||||
}
|
||||
if (codec->m_readCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_readCipherType-1]->m_cloneCipher(codec->m_readCipher, codec->m_writeCipher);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcPadPassword(char* password, int pswdlen, unsigned char pswd[32])
|
||||
{
|
||||
int j;
|
||||
int p = 0;
|
||||
int m = pswdlen;
|
||||
if (m > 32) m = 32;
|
||||
|
||||
for (j = 0; j < m; j++)
|
||||
{
|
||||
pswd[p++] = (unsigned char) password[j];
|
||||
}
|
||||
for (j = 0; p < 32 && j < 32; j++)
|
||||
{
|
||||
pswd[p++] = padding[j];
|
||||
}
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcGenerateReadKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt)
|
||||
{
|
||||
codecDescriptorTable[codec->m_readCipherType-1]->m_generateKey(codec->m_readCipher, codec->m_btShared, userPassword, passwordLength, 0, cipherSalt);
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcGenerateWriteKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType-1]->m_generateKey(codec->m_writeCipher, codec->m_btShared, userPassword, passwordLength, 1, cipherSalt);
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcEncrypt(Codec* codec, int page, unsigned char* data, int len, int useWriteKey)
|
||||
{
|
||||
int cipherType = (useWriteKey) ? codec->m_writeCipherType : codec->m_readCipherType;
|
||||
void* cipher = (useWriteKey) ? codec->m_writeCipher : codec->m_readCipher;
|
||||
int reserved = (useWriteKey) ? (codec->m_writeReserved >= 0) ? codec->m_writeReserved : codec->m_reserved
|
||||
: (codec->m_readReserved >= 0) ? codec->m_readReserved : codec->m_reserved;
|
||||
return codecDescriptorTable[cipherType-1]->m_encryptPage(cipher, page, data, len, reserved);
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcDecrypt(Codec* codec, int page, unsigned char* data, int len)
|
||||
{
|
||||
int cipherType = codec->m_readCipherType;
|
||||
void* cipher = codec->m_readCipher;
|
||||
int reserved = (codec->m_readReserved >= 0) ? codec->m_readReserved : codec->m_reserved;
|
||||
return codecDescriptorTable[cipherType-1]->m_decryptPage(cipher, page, data, len, reserved, codec->m_hmacCheck);
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcConfigureSQLCipherVersion(sqlite3* db, int configDefault, int legacyVersion)
|
||||
{
|
||||
static char* stdNames[] = { "legacy_page_size", "kdf_iter", "hmac_use", "kdf_algorithm", "hmac_algorithm", NULL };
|
||||
static char* defNames[] = { "default:legacy_page_size", "default:kdf_iter", "default:hmac_use", "default:kdf_algorithm", "default:hmac_algorithm", NULL };
|
||||
static int versionParams[SQLCIPHER_VERSION_MAX][5] =
|
||||
{
|
||||
{ 1024, 4000, 0, SQLCIPHER_KDF_ALGORITHM_SHA1, SQLCIPHER_HMAC_ALGORITHM_SHA1 },
|
||||
{ 1024, 4000, 1, SQLCIPHER_KDF_ALGORITHM_SHA1, SQLCIPHER_HMAC_ALGORITHM_SHA1 },
|
||||
{ 1024, 64000, 1, SQLCIPHER_KDF_ALGORITHM_SHA1, SQLCIPHER_HMAC_ALGORITHM_SHA1 },
|
||||
{ 4096, 256000, 1, SQLCIPHER_KDF_ALGORITHM_SHA512, SQLCIPHER_HMAC_ALGORITHM_SHA512 }
|
||||
};
|
||||
if (legacyVersion > 0 && legacyVersion <= SQLCIPHER_VERSION_MAX)
|
||||
{
|
||||
char** names = (configDefault != 0) ? defNames : stdNames;
|
||||
int* values = &versionParams[legacyVersion - 1][0];
|
||||
int j;
|
||||
for (j = 0; names[j] != NULL; ++j)
|
||||
{
|
||||
sqlite3mc_config_cipher(db, "sqlcipher", names[j], values[j]);
|
||||
}
|
||||
}
|
||||
}
|
233
contrib/mORMot/SQLite3/amalgamation/ciphers/cipher_common.h
Normal file
233
contrib/mORMot/SQLite3/amalgamation/ciphers/cipher_common.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
** Name: cipher_common.h
|
||||
** Purpose: Header for the ciphers of SQLite3 Multiple Ciphers
|
||||
** Author: Ulrich Telle
|
||||
** Created: 2020-02-02
|
||||
** Copyright: (c) 2006-2020 Ulrich Telle
|
||||
** License: MIT
|
||||
*/
|
||||
|
||||
#ifndef CIPHER_COMMON_H_
|
||||
#define CIPHER_COMMON_H_
|
||||
|
||||
#include "sqlite3mc.h"
|
||||
|
||||
/*
|
||||
// ATTENTION: Macro similar to that in pager.c
|
||||
// TODO: Check in case of new version of SQLite
|
||||
*/
|
||||
#define WX_PAGER_MJ_PGNO(x) ((PENDING_BYTE/(x))+1)
|
||||
|
||||
#define CODEC_TYPE_DEFAULT CODEC_TYPE_CHACHA20
|
||||
|
||||
#ifndef CODEC_TYPE
|
||||
#define CODEC_TYPE CODEC_TYPE_DEFAULT
|
||||
#endif
|
||||
|
||||
#if CODEC_TYPE < 1 || CODEC_TYPE > CODEC_TYPE_MAX
|
||||
#error "Invalid codec type selected"
|
||||
#endif
|
||||
|
||||
#define MAXKEYLENGTH 32
|
||||
#define KEYLENGTH_AES128 16
|
||||
#define KEYLENGTH_AES256 32
|
||||
#define KEYSALT_LENGTH 16
|
||||
|
||||
#define CODEC_SHA_ITER 4001
|
||||
|
||||
typedef struct _Codec
|
||||
{
|
||||
int m_isEncrypted;
|
||||
int m_hmacCheck;
|
||||
/* Read cipher */
|
||||
int m_hasReadCipher;
|
||||
int m_readCipherType;
|
||||
void* m_readCipher;
|
||||
int m_readReserved;
|
||||
/* Write cipher */
|
||||
int m_hasWriteCipher;
|
||||
int m_writeCipherType;
|
||||
void* m_writeCipher;
|
||||
int m_writeReserved;
|
||||
|
||||
sqlite3* m_db; /* Pointer to DB */
|
||||
Btree* m_bt; /* Pointer to B-tree used by DB */
|
||||
BtShared* m_btShared; /* Pointer to shared B-tree used by DB */
|
||||
unsigned char m_page[SQLITE_MAX_PAGE_SIZE + 24];
|
||||
int m_pageSize;
|
||||
int m_reserved;
|
||||
int m_hasKeySalt;
|
||||
unsigned char m_keySalt[KEYSALT_LENGTH];
|
||||
} Codec;
|
||||
|
||||
#define CIPHER_PARAMS_SENTINEL { "", 0, 0, 0, 0 }
|
||||
#define CIPHER_PAGE1_OFFSET 24
|
||||
|
||||
typedef struct _CipherParams
|
||||
{
|
||||
char* m_name;
|
||||
int m_value;
|
||||
int m_default;
|
||||
int m_minValue;
|
||||
int m_maxValue;
|
||||
} CipherParams;
|
||||
|
||||
typedef struct _CodecParameter
|
||||
{
|
||||
char* m_name;
|
||||
int m_id;
|
||||
CipherParams* m_params;
|
||||
} CodecParameter;
|
||||
|
||||
typedef void* (*AllocateCipher_t)(sqlite3* db);
|
||||
typedef void (*FreeCipher_t)(void* cipher);
|
||||
typedef void (*CloneCipher_t)(void* cipherTo, void* cipherFrom);
|
||||
typedef int (*CompareCipher_t)(void* cipher1, void* cipher2);
|
||||
typedef int (*GetLegacy_t)(void* cipher);
|
||||
typedef int (*GetPageSize_t)(void* cipher);
|
||||
typedef int (*GetReserved_t)(void* cipher);
|
||||
typedef unsigned char* (*GetSalt_t)(void* cipher);
|
||||
typedef void (*GenerateKey_t)(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt);
|
||||
typedef int (*EncryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved);
|
||||
typedef int (*DecryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved, int hmacCheck);
|
||||
|
||||
typedef struct _CodecDescriptor
|
||||
{
|
||||
char m_name[32];
|
||||
AllocateCipher_t m_allocateCipher;
|
||||
FreeCipher_t m_freeCipher;
|
||||
CloneCipher_t m_cloneCipher;
|
||||
CompareCipher_t m_compareCipher;
|
||||
GetLegacy_t m_getLegacy;
|
||||
GetPageSize_t m_getPageSize;
|
||||
GetReserved_t m_getReserved;
|
||||
GetSalt_t m_getSalt;
|
||||
GenerateKey_t m_generateKey;
|
||||
EncryptPage_t m_encryptPage;
|
||||
DecryptPage_t m_decryptPage;
|
||||
} CipherDescriptor;
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcGetCipherParameter(CipherParams* cipherParams, const char* paramName);
|
||||
SQLITE_PRIVATE int sqlite3mcGetCipherType(sqlite3* db);
|
||||
SQLITE_PRIVATE CipherParams* sqlite3mcGetCipherParams(sqlite3* db, int cypherType);
|
||||
SQLITE_PRIVATE int sqlite3mcCodecInit(Codec* codec);
|
||||
SQLITE_PRIVATE void sqlite3mcCodecTerm(Codec* codec);
|
||||
SQLITE_PRIVATE void sqlite3mcClearKeySalt(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcCodecSetup(Codec* codec, int cipherType, char* userPassword, int passwordLength);
|
||||
SQLITE_PRIVATE int sqlite3mcSetupWriteCipher(Codec* codec, int cipherType, char* userPassword, int passwordLength);
|
||||
SQLITE_PRIVATE void sqlite3mcSetIsEncrypted(Codec* codec, int isEncrypted);
|
||||
SQLITE_PRIVATE void sqlite3mcSetReadCipherType(Codec* codec, int cipherType);
|
||||
SQLITE_PRIVATE void sqlite3mcSetWriteCipherType(Codec* codec, int cipherType);
|
||||
SQLITE_PRIVATE void sqlite3mcSetHasReadCipher(Codec* codec, int hasReadCipher);
|
||||
SQLITE_PRIVATE void sqlite3mcSetHasWriteCipher(Codec* codec, int hasWriteCipher);
|
||||
SQLITE_PRIVATE void sqlite3mcSetDb(Codec* codec, sqlite3* db);
|
||||
SQLITE_PRIVATE void sqlite3mcSetBtree(Codec* codec, Btree* bt);
|
||||
SQLITE_PRIVATE void sqlite3mcSetReadReserved(Codec* codec, int reserved);
|
||||
SQLITE_PRIVATE void sqlite3mcSetWriteReserved(Codec* codec, int reserved);
|
||||
SQLITE_PRIVATE int sqlite3mcIsEncrypted(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcHasReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcHasWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE Btree* sqlite3mcGetBtree(Codec* codec);
|
||||
SQLITE_PRIVATE BtShared* sqlite3mcGetBtShared(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSize(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReadReserved(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetWriteReserved(Codec* codec);
|
||||
SQLITE_PRIVATE unsigned char* sqlite3mcGetPageBuffer(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetLegacyReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetLegacyWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSizeReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSizeWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReservedReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReservedWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcReservedEqual(Codec* codec);
|
||||
SQLITE_PRIVATE unsigned char* sqlite3mcGetSaltWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcCodecCopy(Codec* codec, Codec* other);
|
||||
SQLITE_PRIVATE int sqlite3mcCodecCompare(Codec* codec1, Codec* codec2);
|
||||
|
||||
SQLITE_PRIVATE void sqlite3mcGenerateReadKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt);
|
||||
|
||||
SQLITE_PRIVATE void sqlite3mcGenerateWriteKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcEncrypt(Codec* codec, int page, unsigned char* data, int len, int useWriteKey);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcDecrypt(Codec* codec, int page, unsigned char* data, int len);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcCopyCipher(Codec* codec, int read2write);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcCodecSetup(Codec* codec, int cipherType, char* userPassword, int passwordLength);
|
||||
SQLITE_PRIVATE int sqlite3mcSetupWriteCipher(Codec* codec, int cipherType, char* userPassword, int passwordLength);
|
||||
|
||||
SQLITE_PRIVATE void sqlite3mcSetIsEncrypted(Codec* codec, int isEncrypted);
|
||||
SQLITE_PRIVATE void sqlite3mcSetReadCipherType(Codec* codec, int cipherType);
|
||||
SQLITE_PRIVATE void sqlite3mcSetWriteCipherType(Codec* codec, int cipherType);
|
||||
SQLITE_PRIVATE void sqlite3mcSetHasReadCipher(Codec* codec, int hasReadCipher);
|
||||
SQLITE_PRIVATE void sqlite3mcSetHasWriteCipher(Codec* codec, int hasWriteCipher);
|
||||
SQLITE_PRIVATE void sqlite3mcSetDb(Codec* codec, sqlite3* db);
|
||||
SQLITE_PRIVATE void sqlite3mcSetBtree(Codec* codec, Btree* bt);
|
||||
SQLITE_PRIVATE void sqlite3mcSetReadReserved(Codec* codec, int reserved);
|
||||
SQLITE_PRIVATE void sqlite3mcSetWriteReserved(Codec* codec, int reserved);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcIsEncrypted(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcHasReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcHasWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE Btree* sqlite3mcGetBtree(Codec* codec);
|
||||
SQLITE_PRIVATE BtShared* sqlite3mcGetBtShared(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSize(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReadReserved(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetWriteReserved(Codec* codec);
|
||||
SQLITE_PRIVATE unsigned char* sqlite3mcGetPageBuffer(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetLegacyReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetLegacyWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSizeReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSizeWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReservedReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReservedWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcReservedEqual(Codec* codec);
|
||||
|
||||
SQLITE_PRIVATE void sqlite3mcPadPassword(char* password, int pswdlen, unsigned char pswd[32]);
|
||||
SQLITE_PRIVATE void sqlite3mcRC4(unsigned char* key, int keylen, unsigned char* textin, int textlen, unsigned char* textout);
|
||||
SQLITE_PRIVATE void sqlite3mcGetMD5Binary(unsigned char* data, int length, unsigned char* digest);
|
||||
SQLITE_PRIVATE void sqlite3mcGetSHABinary(unsigned char* data, int length, unsigned char* digest);
|
||||
SQLITE_PRIVATE void sqlite3mcGenerateInitialVector(int seed, unsigned char iv[16]);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcIsHexKey(const unsigned char* hex, int len);
|
||||
SQLITE_PRIVATE int sqlite3mcConvertHex2Int(char c);
|
||||
SQLITE_PRIVATE void sqlite3mcConvertHex2Bin(const unsigned char* hex, int len, unsigned char* bin);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcConfigureFromUri(sqlite3* db, const char *zDbName, int configDefault);
|
||||
SQLITE_PRIVATE void sqlite3mcConfigureSQLCipherVersion(sqlite3* db, int configDefault, int legacyVersion);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcCodecAttach(sqlite3* db, int nDb, const char* zPath, const void* zKey, int nKey);
|
||||
SQLITE_PRIVATE void sqlite3mcCodecGetKey(sqlite3* db, int nDb, void** zKey, int* nKey);
|
||||
|
||||
/* Debugging */
|
||||
|
||||
#if 0
|
||||
#define SQLITE3MC_DEBUG
|
||||
#define SQLITE3MC_DEBUG_DATA
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE3MC_DEBUG
|
||||
#define SQLITE3MC_DEBUG_LOG(...) { fprintf(stdout, __VA_ARGS__); fflush(stdout); }
|
||||
#else
|
||||
#define SQLITE3MC_DEBUG_LOG(...)
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE3MC_DEBUG_DATA
|
||||
#define SQLITE3MC_DEBUG_HEX(DESC,BUFFER,LEN) \
|
||||
{ \
|
||||
int count; \
|
||||
printf(DESC); \
|
||||
for (count = 0; count < LEN; ++count) \
|
||||
{ \
|
||||
if (count % 16 == 0) printf("\n%05x: ", count); \
|
||||
printf("%02x ", ((unsigned char*) BUFFER)[count]); \
|
||||
} \
|
||||
printf("\n"); \
|
||||
fflush(stdout); \
|
||||
}
|
||||
#else
|
||||
#define SQLITE3MC_DEBUG_HEX(DESC,BUFFER,LEN)
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -1,7 +1,10 @@
|
||||
@echo off
|
||||
|
||||
set DST2=..\..\..\lib2\static\delphi\sqlite3.obj
|
||||
|
||||
attrib -r ..\sqlite3.obj
|
||||
del ..\sqlite3.obj
|
||||
del %DST2%
|
||||
|
||||
set bcc=d:\dev\DelphiXE7
|
||||
rem set bcc=d:\dev\bcc
|
||||
@@ -10,9 +13,9 @@ echo ---------------------------------------------------
|
||||
echo Compiling for Delphi Win32 using %bcc%
|
||||
|
||||
%bcc%\bin\bcc32 -6 -Oi -O2 -c -d -u- sqlite3mc.c
|
||||
copy sqlite3mc.obj ..\sqlite3.obj
|
||||
del sqlite3mc.obj
|
||||
|
||||
copy sqlite3mc.obj ..\sqlite3.obj
|
||||
copy sqlite3mc.obj %DST2%
|
||||
attrib +r ..\sqlite3.obj
|
||||
|
||||
rem pause
|
||||
|
@@ -1,17 +1,21 @@
|
||||
@echo off
|
||||
|
||||
set DST2=..\..\..\lib2\static\delphi\sqlite3.o
|
||||
|
||||
attrib -r ..\sqlite3.o
|
||||
del ..\sqlite3.o
|
||||
del %DST2%
|
||||
|
||||
set bcc=d:\dev\DelphiXE7
|
||||
rem set bcc=d:\Dev\bcc64ce
|
||||
rem set bcc=d:\Dev\bcc\bcc64ce
|
||||
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for Delphi Win64 using %bcc%
|
||||
|
||||
%bcc%\bin\bcc64 -isystem "%bcc%\include" -isystem "%bcc%\include\windows\sdk" -isystem "%bcc%\include\dinkumware64" -isystem "%bcc%\include\windows\crtl" -O2 -c -DWIN64 sqlite3mc.c
|
||||
%bcc%\bin\bcc64 -Wno-pointer-sign -isystem "%bcc%\include" -isystem "%bcc%\include\windows\sdk" -isystem "%bcc%\include\dinkumware64" -isystem "%bcc%\include\windows\crtl" -O2 -c -DWIN64 sqlite3mc.c
|
||||
|
||||
copy sqlite3mc.o ..\sqlite3.o
|
||||
del sqlite3mc.o
|
||||
copy sqlite3mc.o %DST2%
|
||||
attrib +r ..\sqlite3.o
|
||||
|
||||
rem pause
|
||||
|
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
|
||||
ARCH=aarch64-android
|
||||
|
||||
CROSS=/home/ab/fpcup/cross/bin/all-android/bin
|
||||
GCC=$CROSS/clang
|
||||
DST=../../static/$ARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$ARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$ARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $ARCH using $GCC
|
||||
$GCC --target=aarch64-linux-android21 -static -fPIC -Wno-pointer-sign -O2 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
# -fPIC is needed for proper linking
|
||||
|
||||
#$CROSS/llvm-strip sqlite3-$ARCH.o
|
||||
# striping remove all exported symbols :(
|
||||
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
cp sqlite3-$ARCH.o $DST2
|
||||
|
@@ -5,13 +5,19 @@ ARCH=aarch64-linux
|
||||
CROSS=/home/ab/fpcup/cross/bin/$ARCH
|
||||
GCC=$CROSS/$ARCH-gcc
|
||||
DST=../../static/$ARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$ARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$ARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $ARCH using $GCC
|
||||
$GCC -static -O1 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
|
||||
$CROSS/$ARCH-strip -d -x sqlite3-$ARCH.o
|
||||
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
cp sqlite3-$ARCH.o $DST2
|
||||
|
||||
|
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
ARCH=arm-android
|
||||
|
||||
CROSS=/home/ab/fpcup/cross/bin/all-android
|
||||
GCC=$CROSS/bin/clang
|
||||
DST=../../static/$ARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$ARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$ARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $ARCH using $GCC
|
||||
$GCC --target=armv7a-linux-androideabi21 -static -O2 -Wno-pointer-sign -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -D__ARM_PCS_VFP -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
|
||||
#$CROSS/bin/llvm-strip sqlite3-$ARCH.o
|
||||
# striping remove all exported symbols :(
|
||||
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
cp sqlite3-$ARCH.o $DST2
|
||||
|
@@ -5,13 +5,19 @@ ARCH=arm-linux
|
||||
CROSS=/home/ab/fpcup/cross/bin/$ARCH
|
||||
GCC=$CROSS/arm-linux-gnueabihf-gcc
|
||||
DST=../../static/$ARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$ARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$ARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $ARCH using $GCC
|
||||
$GCC -static -O1 -marm -march=armv7-a+fp -I$CROSS/include -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -D__ARM_PCS_VFP -mfloat-abi=hard -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
|
||||
$CROSS/arm-linux-gnueabihf-strip -d -x sqlite3-$ARCH.o
|
||||
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
cp sqlite3-$ARCH.o $DST2
|
||||
|
||||
|
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
ARCH=i386-android
|
||||
|
||||
CROSS=/home/ab/fpcup/cross/bin/all-android
|
||||
GCC=$CROSS/bin/clang
|
||||
DST=../../static/$ARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$ARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$ARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $ARCH using $GCC
|
||||
$GCC --target=i686-linux-androideabi21 -static -Wno-pointer-sign -O2 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -D__ARM_PCS_VFP -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
|
||||
#$CROSS/bin/llvm-strip sqlite3-$ARCH.o
|
||||
# strip blows all external symbols
|
||||
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
cp sqlite3-$ARCH.o $DST2
|
||||
|
@@ -2,18 +2,24 @@
|
||||
|
||||
ARCH=i386-darwin
|
||||
DST=../../static/$ARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$ARCH/sqlite3.o
|
||||
|
||||
CROSS=/home/ab/fpcup/cross
|
||||
#CROSS=/home/ab/fpcup/cross
|
||||
# use older but working fpcupdeluxe cross compiler
|
||||
CROSS=/home/abouchez/fpcupdeluxe/__darwin
|
||||
SDK=$CROSS/lib/x86-darwin/MacOSX10.11.sdk\usr
|
||||
GCC=$CROSS/bin/x86-darwin/i386-apple-darwin15
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$ARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $ARCH using $GCC
|
||||
$GCC-clang -static -target i386-apple-darwin15 -O2 -m32 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -I$SDK/include -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
$GCC-clang -static -target i386-apple-darwin15 -Wno-pointer-sign -O2 -m32 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -I$SDK/include -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
cp sqlite3-$ARCH.o $DST2
|
||||
|
||||
$GCC-libtool -static sqlite3-$ARCH.o -o ../../static/$ARCH/libsqlite3.a
|
||||
$GCC-libtool -static sqlite3-$ARCH.o -o ../../../lib2/static/$ARCH/libsqlite3.a
|
||||
|
@@ -5,13 +5,19 @@ FPCARCHVERSION=12
|
||||
CROSS=/home/ab/fpcup/cross/bin/$FPCARCH
|
||||
GCC=$CROSS/$FPCARCH$FPCARCHVERSION-gcc
|
||||
DST=../../static/$FPCARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$FPCARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$FPCARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $FPCARCH using $GCC
|
||||
$GCC -static -O2 -m32 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
|
||||
$CROSS/$FPCARCH$FPCARCHVERSION-strip -d -x sqlite3-$FPCARCH.o
|
||||
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
cp sqlite3-$FPCARCH.o $DST2
|
||||
|
||||
|
@@ -6,15 +6,19 @@ set GCCPATH=d:\fpcup\__win\bin\%FPCARCH%
|
||||
|
||||
set GCC=%FPCARCH%-gcc
|
||||
set DST=..\..\static\%FPCARCH%\sqlite3.o
|
||||
set DST2=..\..\..\lib2\static\%FPCARCH%\sqlite3.o
|
||||
set path=%path%;%GCCPATH%
|
||||
|
||||
del %DST%
|
||||
del %DST2%
|
||||
del sqlite3-%FPCARCH%.o
|
||||
|
||||
echo.
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on %FPCARCH% using %GCC%
|
||||
%GCC% -static -w -O2 -m32 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-%FPCARCH%.o
|
||||
|
||||
copy sqlite3-%FPCARCH%.o %DST%
|
||||
copy sqlite3-%FPCARCH%.o %DST2%
|
||||
|
||||
rem pause
|
@@ -3,13 +3,19 @@
|
||||
FPCARCH=i386-linux
|
||||
GCC=gcc-7
|
||||
DST=../../static/$FPCARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$FPCARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$FPCARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $FPCARCH using $GCC
|
||||
$GCC -static -O2 -m32 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
|
||||
strip -d -x sqlite3-$FPCARCH.o
|
||||
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
cp sqlite3-$FPCARCH.o $DST2
|
||||
|
||||
|
@@ -5,13 +5,19 @@ FPCARCHVERSION=
|
||||
CROSS=/home/ab/fpcup/cross/bin/$FPCARCH
|
||||
GCC=$CROSS/$FPCARCH$FPCARCHVERSION-gcc
|
||||
DST=../../static/$FPCARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$FPCARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$FPCARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $FPCARCH using $GCC
|
||||
$GCC -static -O2 -m32 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
|
||||
$CROSS/$FPCARCH$FPCARCHVERSION-strip -d -x sqlite3-$FPCARCH.o
|
||||
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
cp sqlite3-$FPCARCH.o $DST2
|
||||
|
||||
|
@@ -3,13 +3,18 @@
|
||||
ARCH=i386-win32
|
||||
GCC=i686-w64-mingw32-gcc
|
||||
DST=../../static/$ARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$ARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$ARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $ARCH using $GCC
|
||||
$GCC -O2 -m32 -DWIN32 -DNDEBUG -D_WINDOWS -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
|
||||
i686-w64-mingw32-strip -d -x sqlite3-$ARCH.o
|
||||
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
cp sqlite3-$ARCH.o $DST2
|
||||
|
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
ARCH=x86_64-android
|
||||
|
||||
CROSS=/home/ab/fpcup/cross/bin/all-android/bin
|
||||
GCC=$CROSS/clang
|
||||
DST=../../static/$ARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$ARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$ARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $ARCH using $GCC
|
||||
$GCC --target=x86_64-linux-android21 -static -O2 -Wno-pointer-sign -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
|
||||
#$CROSS/llvm-strip sqlite3-$ARCH.o
|
||||
# striping remove all exported symbols :(
|
||||
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
cp sqlite3-$ARCH.o $DST2
|
||||
|
@@ -2,18 +2,24 @@
|
||||
|
||||
ARCH=x86_64-darwin
|
||||
DST=../../static/$ARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$ARCH/sqlite3.o
|
||||
|
||||
CROSS=/home/ab/fpcup/cross
|
||||
#CROSS=/home/ab/fpcup/cross
|
||||
# use older but working fpcupdeluxe cross compiler
|
||||
CROSS=/home/abouchez/fpcupdeluxe/__darwin
|
||||
SDK=$CROSS/lib/x86-darwin/MacOSX10.11.sdk\usr
|
||||
GCC=$CROSS/bin/x86-darwin/x86_64-apple-darwin15
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$ARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $ARCH using $GCC
|
||||
$GCC-clang -static -target x86_64-apple-darwin15 -O2 -m64 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -I$SDK/include -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
$GCC-clang -static -target x86_64-apple-darwin15 -O2 -m64 -Wno-pointer-sign -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -I$SDK/include -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
cp sqlite3-$ARCH.o $DST2
|
||||
|
||||
$GCC-libtool -static sqlite3-$ARCH.o -o ../../static/$ARCH/libsqlite3.a
|
||||
$GCC-libtool -static sqlite3-$ARCH.o -o ../../../lib2/static/$ARCH/libsqlite3.a
|
||||
|
@@ -5,13 +5,19 @@ FPCARCHVERSION=12
|
||||
CROSS=/home/ab/fpcup/cross/bin/$FPCARCH
|
||||
GCC=$CROSS/$FPCARCH$FPCARCHVERSION-gcc
|
||||
DST=../../static/$FPCARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$FPCARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$FPCARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $FPCARCH using $GCC
|
||||
$GCC -static -O2 -m64 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
|
||||
$CROSS/$FPCARCH$FPCARCHVERSION-strip -d -x sqlite3-$FPCARCH.o
|
||||
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
cp sqlite3-$FPCARCH.o $DST2
|
||||
|
||||
|
@@ -6,15 +6,21 @@ set GCCPATH=d:\fpcup\__win\bin\%FPCARCH%
|
||||
|
||||
set GCC=%FPCARCH%-gcc
|
||||
set DST=..\..\static\%FPCARCH%\sqlite3.o
|
||||
set DST2=..\..\..\lib2\static\%FPCARCH%\sqlite3.o
|
||||
set path=%path%;%GCCPATH%
|
||||
|
||||
del %DST%
|
||||
del %DST2%
|
||||
del sqlite3-%FPCARCH%.o
|
||||
|
||||
echo.
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on %FPCARCH% using %GCC%
|
||||
%GCC% -static -w -O2 -fno-pic -fno-stack-protector -m64 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-%FPCARCH%.o
|
||||
%GCC% -static -w -O2 -fno-pic -fno-stack-protector -fomit-frame-pointer -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables -m64 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-%FPCARCH%.o
|
||||
|
||||
%FPCARCH%-strip -x sqlite3-%FPCARCH%.o
|
||||
|
||||
copy sqlite3-%FPCARCH%.o %DST%
|
||||
copy sqlite3-%FPCARCH%.o %DST2%
|
||||
|
||||
rem pause
|
@@ -3,13 +3,18 @@
|
||||
FPCARCH=x86_64-linux
|
||||
GCC=gcc-7
|
||||
DST=../../static/$FPCARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$FPCARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$FPCARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $FPCARCH using $GCC
|
||||
$GCC -static -fno-pic -fno-stack-protector -O2 -m64 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
|
||||
strip -d -x sqlite3-$FPCARCH.o
|
||||
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
cp sqlite3-$FPCARCH.o $DST2
|
||||
|
@@ -5,13 +5,19 @@ FPCARCHVERSION=
|
||||
CROSS=/home/ab/fpcup/cross/bin/$FPCARCH
|
||||
GCC=$CROSS/$FPCARCH$FPCARCHVERSION-gcc
|
||||
DST=../../static/$FPCARCH/sqlite3.o
|
||||
DST2=../../../lib2/static/$FPCARCH/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$FPCARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling for FPC on $FPCARCH using $GCC
|
||||
$GCC -static -O2 -m64 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
|
||||
$CROSS/$FPCARCH$FPCARCHVERSION-strip -d -x sqlite3-$FPCARCH.o
|
||||
|
||||
cp sqlite3-$FPCARCH.o $DST
|
||||
cp sqlite3-$FPCARCH.o $DST2
|
||||
|
||||
|
@@ -3,25 +3,40 @@
|
||||
ARCH=x86_64-win64
|
||||
GCC=x86_64-w64-mingw32-gcc
|
||||
STATIC=../../static/$ARCH
|
||||
LIB2=../../../lib2/static
|
||||
STATIC2=$LIB2/$ARCH
|
||||
STATIC2DELPHI=$LIB2/delphi
|
||||
DST=$STATIC/sqlite3.o
|
||||
DST2=$STATIC2/sqlite3.o
|
||||
|
||||
rm $DST
|
||||
rm $DST2
|
||||
rm sqlite3-$ARCH.o
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling static for FPC on $ARCH using $GCC
|
||||
$GCC -O2 -static -DWIN64 -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -m64 -DNDEBUG -D_WINDOWS -c sqlite3mc.c -o sqlite3-$ARCH.o
|
||||
|
||||
x86_64-w64-mingw32-strip -d -x sqlite3-$ARCH.o
|
||||
|
||||
cp sqlite3-$ARCH.o $DST
|
||||
cp sqlite3-$ARCH.o $DST2
|
||||
|
||||
DLL=sqlite3-64.dll
|
||||
rm $DLL
|
||||
rm $STATIC/$DLL
|
||||
rm $STATIC2DELPHI/$DLL
|
||||
A=libsqlite3-64.a
|
||||
rm $STATIC/$A
|
||||
rm $STATIC2/$A
|
||||
|
||||
echo
|
||||
echo ---------------------------------------------------
|
||||
echo Compiling $DLL using $GCC
|
||||
$GCC -O2 -shared -DSQLITE_MMAP_READWRITE -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS4 -DDSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_DESERIALIZE -DWIN64 -DNDEBUG -D_WINDOWS -D_USRDLL -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_THREADSAFE=1 -DTEMP_STORE=1 -m64 sqlite3.c -o $DLL -Wl,--out-implib,libsqlite3-64.a
|
||||
$GCC -O2 -shared -DSQLITE_MMAP_READWRITE -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_RBU -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_DESERIALIZE -DWIN64 -DNDEBUG -D_WINDOWS -D_USRDLL -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_THREADSAFE=1 -DTEMP_STORE=1 -m64 sqlite3.c -o $DLL -Wl,--out-implib,libsqlite3-64.a
|
||||
cp $DLL $STATIC
|
||||
cp libsqlite3-64.a $STATIC
|
||||
cp $DLL $STATIC2DELPHI
|
||||
cp $A $STATIC
|
||||
cp $A $STATIC2
|
||||
|
||||
|
@@ -49,3 +49,11 @@ echo Use Native fpcupdeluxe cross-compilers for FPC OpenBSD i386/x64
|
||||
|
||||
./compile-fpc-i386-openbsd.sh
|
||||
./compile-fpc-x86_64-openbsd.sh
|
||||
|
||||
echo
|
||||
echo Use Native fpcupdeluxe cross-compilers for FPC Android arm/aarch64/i386/x64-android
|
||||
|
||||
./compile-fpc-arm-android.sh
|
||||
./compile-fpc-aarch64-android.sh
|
||||
./compile-fpc-i386-android.sh
|
||||
./compile-fpc-x86_64-android.sh
|
||||
|
760
contrib/mORMot/SQLite3/amalgamation/regexp.c
Normal file
760
contrib/mORMot/SQLite3/amalgamation/regexp.c
Normal file
@@ -0,0 +1,760 @@
|
||||
/*
|
||||
** 2012-11-13
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** The code in this file implements a compact but reasonably
|
||||
** efficient regular-expression matcher for posix extended regular
|
||||
** expressions against UTF8 text.
|
||||
**
|
||||
** This file is an SQLite extension. It registers a single function
|
||||
** named "regexp(A,B)" where A is the regular expression and B is the
|
||||
** string to be matched. By registering this function, SQLite will also
|
||||
** then implement the "B regexp A" operator. Note that with the function
|
||||
** the regular expression comes first, but with the operator it comes
|
||||
** second.
|
||||
**
|
||||
** The following regular expression syntax is supported:
|
||||
**
|
||||
** X* zero or more occurrences of X
|
||||
** X+ one or more occurrences of X
|
||||
** X? zero or one occurrences of X
|
||||
** X{p,q} between p and q occurrences of X
|
||||
** (X) match X
|
||||
** X|Y X or Y
|
||||
** ^X X occurring at the beginning of the string
|
||||
** X$ X occurring at the end of the string
|
||||
** . Match any single character
|
||||
** \c Character c where c is one of \{}()[]|*+?.
|
||||
** \c C-language escapes for c in afnrtv. ex: \t or \n
|
||||
** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
|
||||
** \xXX Where XX is exactly 2 hex digits, unicode value XX
|
||||
** [abc] Any single character from the set abc
|
||||
** [^abc] Any single character not in the set abc
|
||||
** [a-z] Any single character in the range a-z
|
||||
** [^a-z] Any single character not in the range a-z
|
||||
** \b Word boundary
|
||||
** \w Word character. [A-Za-z0-9_]
|
||||
** \W Non-word character
|
||||
** \d Digit
|
||||
** \D Non-digit
|
||||
** \s Whitespace character
|
||||
** \S Non-whitespace character
|
||||
**
|
||||
** A nondeterministic finite automaton (NFA) is used for matching, so the
|
||||
** performance is bounded by O(N*M) where N is the size of the regular
|
||||
** expression and M is the size of the input string. The matcher never
|
||||
** exhibits exponential behavior. Note that the X{p,q} operator expands
|
||||
** to p copies of X following by q-p copies of X? and that the size of the
|
||||
** regular expression in the O(N*M) performance bound is computed after
|
||||
** this expansion.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
|
||||
/*
|
||||
** The following #defines change the names of some functions implemented in
|
||||
** this file to prevent name collisions with C-library functions of the
|
||||
** same name.
|
||||
*/
|
||||
#define re_match sqlite3re_match
|
||||
#define re_compile sqlite3re_compile
|
||||
#define re_free sqlite3re_free
|
||||
|
||||
/* The end-of-input character */
|
||||
#define RE_EOF 0 /* End of input */
|
||||
|
||||
/* The NFA is implemented as sequence of opcodes taken from the following
|
||||
** set. Each opcode has a single integer argument.
|
||||
*/
|
||||
#define RE_OP_MATCH 1 /* Match the one character in the argument */
|
||||
#define RE_OP_ANY 2 /* Match any one character. (Implements ".") */
|
||||
#define RE_OP_ANYSTAR 3 /* Special optimized version of .* */
|
||||
#define RE_OP_FORK 4 /* Continue to both next and opcode at iArg */
|
||||
#define RE_OP_GOTO 5 /* Jump to opcode at iArg */
|
||||
#define RE_OP_ACCEPT 6 /* Halt and indicate a successful match */
|
||||
#define RE_OP_CC_INC 7 /* Beginning of a [...] character class */
|
||||
#define RE_OP_CC_EXC 8 /* Beginning of a [^...] character class */
|
||||
#define RE_OP_CC_VALUE 9 /* Single value in a character class */
|
||||
#define RE_OP_CC_RANGE 10 /* Range of values in a character class */
|
||||
#define RE_OP_WORD 11 /* Perl word character [A-Za-z0-9_] */
|
||||
#define RE_OP_NOTWORD 12 /* Not a perl word character */
|
||||
#define RE_OP_DIGIT 13 /* digit: [0-9] */
|
||||
#define RE_OP_NOTDIGIT 14 /* Not a digit */
|
||||
#define RE_OP_SPACE 15 /* space: [ \t\n\r\v\f] */
|
||||
#define RE_OP_NOTSPACE 16 /* Not a digit */
|
||||
#define RE_OP_BOUNDARY 17 /* Boundary between word and non-word */
|
||||
|
||||
/* Each opcode is a "state" in the NFA */
|
||||
typedef unsigned short ReStateNumber;
|
||||
|
||||
/* Because this is an NFA and not a DFA, multiple states can be active at
|
||||
** once. An instance of the following object records all active states in
|
||||
** the NFA. The implementation is optimized for the common case where the
|
||||
** number of actives states is small.
|
||||
*/
|
||||
typedef struct ReStateSet {
|
||||
unsigned nState; /* Number of current states */
|
||||
ReStateNumber *aState; /* Current states */
|
||||
} ReStateSet;
|
||||
|
||||
/* An input string read one character at a time.
|
||||
*/
|
||||
typedef struct ReInput ReInput;
|
||||
struct ReInput {
|
||||
const unsigned char *z; /* All text */
|
||||
int i; /* Next byte to read */
|
||||
int mx; /* EOF when i>=mx */
|
||||
};
|
||||
|
||||
/* A compiled NFA (or an NFA that is in the process of being compiled) is
|
||||
** an instance of the following object.
|
||||
*/
|
||||
typedef struct ReCompiled ReCompiled;
|
||||
struct ReCompiled {
|
||||
ReInput sIn; /* Regular expression text */
|
||||
const char *zErr; /* Error message to return */
|
||||
char *aOp; /* Operators for the virtual machine */
|
||||
int *aArg; /* Arguments to each operator */
|
||||
unsigned (*xNextChar)(ReInput*); /* Next character function */
|
||||
unsigned char zInit[12]; /* Initial text to match */
|
||||
int nInit; /* Number of characters in zInit */
|
||||
unsigned nState; /* Number of entries in aOp[] and aArg[] */
|
||||
unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */
|
||||
};
|
||||
|
||||
/* Add a state to the given state set if it is not already there */
|
||||
static void re_add_state(ReStateSet *pSet, int newState){
|
||||
unsigned i;
|
||||
for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
|
||||
pSet->aState[pSet->nState++] = (ReStateNumber)newState;
|
||||
}
|
||||
|
||||
/* Extract the next unicode character from *pzIn and return it. Advance
|
||||
** *pzIn to the first byte past the end of the character returned. To
|
||||
** be clear: this routine converts utf8 to unicode. This routine is
|
||||
** optimized for the common case where the next character is a single byte.
|
||||
*/
|
||||
static unsigned re_next_char(ReInput *p){
|
||||
unsigned c;
|
||||
if( p->i>=p->mx ) return 0;
|
||||
c = p->z[p->i++];
|
||||
if( c>=0x80 ){
|
||||
if( (c&0xe0)==0xc0 && p->i<p->mx && (p->z[p->i]&0xc0)==0x80 ){
|
||||
c = (c&0x1f)<<6 | (p->z[p->i++]&0x3f);
|
||||
if( c<0x80 ) c = 0xfffd;
|
||||
}else if( (c&0xf0)==0xe0 && p->i+1<p->mx && (p->z[p->i]&0xc0)==0x80
|
||||
&& (p->z[p->i+1]&0xc0)==0x80 ){
|
||||
c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f);
|
||||
p->i += 2;
|
||||
if( c<=0x7ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
|
||||
}else if( (c&0xf8)==0xf0 && p->i+3<p->mx && (p->z[p->i]&0xc0)==0x80
|
||||
&& (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){
|
||||
c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6)
|
||||
| (p->z[p->i+2]&0x3f);
|
||||
p->i += 3;
|
||||
if( c<=0xffff || c>0x10ffff ) c = 0xfffd;
|
||||
}else{
|
||||
c = 0xfffd;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
static unsigned re_next_char_nocase(ReInput *p){
|
||||
unsigned c = re_next_char(p);
|
||||
if( c>='A' && c<='Z' ) c += 'a' - 'A';
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Return true if c is a perl "word" character: [A-Za-z0-9_] */
|
||||
static int re_word_char(int c){
|
||||
return (c>='0' && c<='9') || (c>='a' && c<='z')
|
||||
|| (c>='A' && c<='Z') || c=='_';
|
||||
}
|
||||
|
||||
/* Return true if c is a "digit" character: [0-9] */
|
||||
static int re_digit_char(int c){
|
||||
return (c>='0' && c<='9');
|
||||
}
|
||||
|
||||
/* Return true if c is a perl "space" character: [ \t\r\n\v\f] */
|
||||
static int re_space_char(int c){
|
||||
return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
|
||||
}
|
||||
|
||||
/* Run a compiled regular expression on the zero-terminated input
|
||||
** string zIn[]. Return true on a match and false if there is no match.
|
||||
*/
|
||||
static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
|
||||
ReStateSet aStateSet[2], *pThis, *pNext;
|
||||
ReStateNumber aSpace[100];
|
||||
ReStateNumber *pToFree;
|
||||
unsigned int i = 0;
|
||||
unsigned int iSwap = 0;
|
||||
int c = RE_EOF+1;
|
||||
int cPrev = 0;
|
||||
int rc = 0;
|
||||
ReInput in;
|
||||
|
||||
in.z = zIn;
|
||||
in.i = 0;
|
||||
in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn);
|
||||
|
||||
/* Look for the initial prefix match, if there is one. */
|
||||
if( pRe->nInit ){
|
||||
unsigned char x = pRe->zInit[0];
|
||||
while( in.i+pRe->nInit<=in.mx
|
||||
&& (zIn[in.i]!=x ||
|
||||
strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
|
||||
){
|
||||
in.i++;
|
||||
}
|
||||
if( in.i+pRe->nInit>in.mx ) return 0;
|
||||
}
|
||||
|
||||
if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
|
||||
pToFree = 0;
|
||||
aStateSet[0].aState = aSpace;
|
||||
}else{
|
||||
pToFree = sqlite3_malloc64( sizeof(ReStateNumber)*2*pRe->nState );
|
||||
if( pToFree==0 ) return -1;
|
||||
aStateSet[0].aState = pToFree;
|
||||
}
|
||||
aStateSet[1].aState = &aStateSet[0].aState[pRe->nState];
|
||||
pNext = &aStateSet[1];
|
||||
pNext->nState = 0;
|
||||
re_add_state(pNext, 0);
|
||||
while( c!=RE_EOF && pNext->nState>0 ){
|
||||
cPrev = c;
|
||||
c = pRe->xNextChar(&in);
|
||||
pThis = pNext;
|
||||
pNext = &aStateSet[iSwap];
|
||||
iSwap = 1 - iSwap;
|
||||
pNext->nState = 0;
|
||||
for(i=0; i<pThis->nState; i++){
|
||||
int x = pThis->aState[i];
|
||||
switch( pRe->aOp[x] ){
|
||||
case RE_OP_MATCH: {
|
||||
if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_ANY: {
|
||||
re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_WORD: {
|
||||
if( re_word_char(c) ) re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_NOTWORD: {
|
||||
if( !re_word_char(c) ) re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_DIGIT: {
|
||||
if( re_digit_char(c) ) re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_NOTDIGIT: {
|
||||
if( !re_digit_char(c) ) re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_SPACE: {
|
||||
if( re_space_char(c) ) re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_NOTSPACE: {
|
||||
if( !re_space_char(c) ) re_add_state(pNext, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_BOUNDARY: {
|
||||
if( re_word_char(c)!=re_word_char(cPrev) ) re_add_state(pThis, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_ANYSTAR: {
|
||||
re_add_state(pNext, x);
|
||||
re_add_state(pThis, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_FORK: {
|
||||
re_add_state(pThis, x+pRe->aArg[x]);
|
||||
re_add_state(pThis, x+1);
|
||||
break;
|
||||
}
|
||||
case RE_OP_GOTO: {
|
||||
re_add_state(pThis, x+pRe->aArg[x]);
|
||||
break;
|
||||
}
|
||||
case RE_OP_ACCEPT: {
|
||||
rc = 1;
|
||||
goto re_match_end;
|
||||
}
|
||||
case RE_OP_CC_INC:
|
||||
case RE_OP_CC_EXC: {
|
||||
int j = 1;
|
||||
int n = pRe->aArg[x];
|
||||
int hit = 0;
|
||||
for(j=1; j>0 && j<n; j++){
|
||||
if( pRe->aOp[x+j]==RE_OP_CC_VALUE ){
|
||||
if( pRe->aArg[x+j]==c ){
|
||||
hit = 1;
|
||||
j = -1;
|
||||
}
|
||||
}else{
|
||||
if( pRe->aArg[x+j]<=c && pRe->aArg[x+j+1]>=c ){
|
||||
hit = 1;
|
||||
j = -1;
|
||||
}else{
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
|
||||
if( hit ) re_add_state(pNext, x+n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0; i<pNext->nState; i++){
|
||||
if( pRe->aOp[pNext->aState[i]]==RE_OP_ACCEPT ){ rc = 1; break; }
|
||||
}
|
||||
re_match_end:
|
||||
sqlite3_free(pToFree);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Resize the opcode and argument arrays for an RE under construction.
|
||||
*/
|
||||
static int re_resize(ReCompiled *p, int N){
|
||||
char *aOp;
|
||||
int *aArg;
|
||||
aOp = sqlite3_realloc64(p->aOp, N*sizeof(p->aOp[0]));
|
||||
if( aOp==0 ) return 1;
|
||||
p->aOp = aOp;
|
||||
aArg = sqlite3_realloc64(p->aArg, N*sizeof(p->aArg[0]));
|
||||
if( aArg==0 ) return 1;
|
||||
p->aArg = aArg;
|
||||
p->nAlloc = N;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Insert a new opcode and argument into an RE under construction. The
|
||||
** insertion point is just prior to existing opcode iBefore.
|
||||
*/
|
||||
static int re_insert(ReCompiled *p, int iBefore, int op, int arg){
|
||||
int i;
|
||||
if( p->nAlloc<=p->nState && re_resize(p, p->nAlloc*2) ) return 0;
|
||||
for(i=p->nState; i>iBefore; i--){
|
||||
p->aOp[i] = p->aOp[i-1];
|
||||
p->aArg[i] = p->aArg[i-1];
|
||||
}
|
||||
p->nState++;
|
||||
p->aOp[iBefore] = (char)op;
|
||||
p->aArg[iBefore] = arg;
|
||||
return iBefore;
|
||||
}
|
||||
|
||||
/* Append a new opcode and argument to the end of the RE under construction.
|
||||
*/
|
||||
static int re_append(ReCompiled *p, int op, int arg){
|
||||
return re_insert(p, p->nState, op, arg);
|
||||
}
|
||||
|
||||
/* Make a copy of N opcodes starting at iStart onto the end of the RE
|
||||
** under construction.
|
||||
*/
|
||||
static void re_copy(ReCompiled *p, int iStart, int N){
|
||||
if( p->nState+N>=p->nAlloc && re_resize(p, p->nAlloc*2+N) ) return;
|
||||
memcpy(&p->aOp[p->nState], &p->aOp[iStart], N*sizeof(p->aOp[0]));
|
||||
memcpy(&p->aArg[p->nState], &p->aArg[iStart], N*sizeof(p->aArg[0]));
|
||||
p->nState += N;
|
||||
}
|
||||
|
||||
/* Return true if c is a hexadecimal digit character: [0-9a-fA-F]
|
||||
** If c is a hex digit, also set *pV = (*pV)*16 + valueof(c). If
|
||||
** c is not a hex digit *pV is unchanged.
|
||||
*/
|
||||
static int re_hex(int c, int *pV){
|
||||
if( c>='0' && c<='9' ){
|
||||
c -= '0';
|
||||
}else if( c>='a' && c<='f' ){
|
||||
c -= 'a' - 10;
|
||||
}else if( c>='A' && c<='F' ){
|
||||
c -= 'A' - 10;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
*pV = (*pV)*16 + (c & 0xff);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* A backslash character has been seen, read the next character and
|
||||
** return its interpretation.
|
||||
*/
|
||||
static unsigned re_esc_char(ReCompiled *p){
|
||||
static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]";
|
||||
static const char zTrans[] = "\a\f\n\r\t\v";
|
||||
int i, v = 0;
|
||||
char c;
|
||||
if( p->sIn.i>=p->sIn.mx ) return 0;
|
||||
c = p->sIn.z[p->sIn.i];
|
||||
if( c=='u' && p->sIn.i+4<p->sIn.mx ){
|
||||
const unsigned char *zIn = p->sIn.z + p->sIn.i;
|
||||
if( re_hex(zIn[1],&v)
|
||||
&& re_hex(zIn[2],&v)
|
||||
&& re_hex(zIn[3],&v)
|
||||
&& re_hex(zIn[4],&v)
|
||||
){
|
||||
p->sIn.i += 5;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
if( c=='x' && p->sIn.i+2<p->sIn.mx ){
|
||||
const unsigned char *zIn = p->sIn.z + p->sIn.i;
|
||||
if( re_hex(zIn[1],&v)
|
||||
&& re_hex(zIn[2],&v)
|
||||
){
|
||||
p->sIn.i += 3;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
for(i=0; zEsc[i] && zEsc[i]!=c; i++){}
|
||||
if( zEsc[i] ){
|
||||
if( i<6 ) c = zTrans[i];
|
||||
p->sIn.i++;
|
||||
}else{
|
||||
p->zErr = "unknown \\ escape";
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
static const char *re_subcompile_string(ReCompiled*);
|
||||
|
||||
/* Peek at the next byte of input */
|
||||
static unsigned char rePeek(ReCompiled *p){
|
||||
return p->sIn.i<p->sIn.mx ? p->sIn.z[p->sIn.i] : 0;
|
||||
}
|
||||
|
||||
/* Compile RE text into a sequence of opcodes. Continue up to the
|
||||
** first unmatched ")" character, then return. If an error is found,
|
||||
** return a pointer to the error message string.
|
||||
*/
|
||||
static const char *re_subcompile_re(ReCompiled *p){
|
||||
const char *zErr;
|
||||
int iStart, iEnd, iGoto;
|
||||
iStart = p->nState;
|
||||
zErr = re_subcompile_string(p);
|
||||
if( zErr ) return zErr;
|
||||
while( rePeek(p)=='|' ){
|
||||
iEnd = p->nState;
|
||||
re_insert(p, iStart, RE_OP_FORK, iEnd + 2 - iStart);
|
||||
iGoto = re_append(p, RE_OP_GOTO, 0);
|
||||
p->sIn.i++;
|
||||
zErr = re_subcompile_string(p);
|
||||
if( zErr ) return zErr;
|
||||
p->aArg[iGoto] = p->nState - iGoto;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compile an element of regular expression text (anything that can be
|
||||
** an operand to the "|" operator). Return NULL on success or a pointer
|
||||
** to the error message if there is a problem.
|
||||
*/
|
||||
static const char *re_subcompile_string(ReCompiled *p){
|
||||
int iPrev = -1;
|
||||
int iStart;
|
||||
unsigned c;
|
||||
const char *zErr;
|
||||
while( (c = p->xNextChar(&p->sIn))!=0 ){
|
||||
iStart = p->nState;
|
||||
switch( c ){
|
||||
case '|':
|
||||
case '$':
|
||||
case ')': {
|
||||
p->sIn.i--;
|
||||
return 0;
|
||||
}
|
||||
case '(': {
|
||||
zErr = re_subcompile_re(p);
|
||||
if( zErr ) return zErr;
|
||||
if( rePeek(p)!=')' ) return "unmatched '('";
|
||||
p->sIn.i++;
|
||||
break;
|
||||
}
|
||||
case '.': {
|
||||
if( rePeek(p)=='*' ){
|
||||
re_append(p, RE_OP_ANYSTAR, 0);
|
||||
p->sIn.i++;
|
||||
}else{
|
||||
re_append(p, RE_OP_ANY, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '*': {
|
||||
if( iPrev<0 ) return "'*' without operand";
|
||||
re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1);
|
||||
re_append(p, RE_OP_FORK, iPrev - p->nState + 1);
|
||||
break;
|
||||
}
|
||||
case '+': {
|
||||
if( iPrev<0 ) return "'+' without operand";
|
||||
re_append(p, RE_OP_FORK, iPrev - p->nState);
|
||||
break;
|
||||
}
|
||||
case '?': {
|
||||
if( iPrev<0 ) return "'?' without operand";
|
||||
re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
|
||||
break;
|
||||
}
|
||||
case '{': {
|
||||
int m = 0, n = 0;
|
||||
int sz, j;
|
||||
if( iPrev<0 ) return "'{m,n}' without operand";
|
||||
while( (c=rePeek(p))>='0' && c<='9' ){ m = m*10 + c - '0'; p->sIn.i++; }
|
||||
n = m;
|
||||
if( c==',' ){
|
||||
p->sIn.i++;
|
||||
n = 0;
|
||||
while( (c=rePeek(p))>='0' && c<='9' ){ n = n*10 + c-'0'; p->sIn.i++; }
|
||||
}
|
||||
if( c!='}' ) return "unmatched '{'";
|
||||
if( n>0 && n<m ) return "n less than m in '{m,n}'";
|
||||
p->sIn.i++;
|
||||
sz = p->nState - iPrev;
|
||||
if( m==0 ){
|
||||
if( n==0 ) return "both m and n are zero in '{m,n}'";
|
||||
re_insert(p, iPrev, RE_OP_FORK, sz+1);
|
||||
n--;
|
||||
}else{
|
||||
for(j=1; j<m; j++) re_copy(p, iPrev, sz);
|
||||
}
|
||||
for(j=m; j<n; j++){
|
||||
re_append(p, RE_OP_FORK, sz+1);
|
||||
re_copy(p, iPrev, sz);
|
||||
}
|
||||
if( n==0 && m>0 ){
|
||||
re_append(p, RE_OP_FORK, -sz);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '[': {
|
||||
int iFirst = p->nState;
|
||||
if( rePeek(p)=='^' ){
|
||||
re_append(p, RE_OP_CC_EXC, 0);
|
||||
p->sIn.i++;
|
||||
}else{
|
||||
re_append(p, RE_OP_CC_INC, 0);
|
||||
}
|
||||
while( (c = p->xNextChar(&p->sIn))!=0 ){
|
||||
if( c=='[' && rePeek(p)==':' ){
|
||||
return "POSIX character classes not supported";
|
||||
}
|
||||
if( c=='\\' ) c = re_esc_char(p);
|
||||
if( rePeek(p)=='-' ){
|
||||
re_append(p, RE_OP_CC_RANGE, c);
|
||||
p->sIn.i++;
|
||||
c = p->xNextChar(&p->sIn);
|
||||
if( c=='\\' ) c = re_esc_char(p);
|
||||
re_append(p, RE_OP_CC_RANGE, c);
|
||||
}else{
|
||||
re_append(p, RE_OP_CC_VALUE, c);
|
||||
}
|
||||
if( rePeek(p)==']' ){ p->sIn.i++; break; }
|
||||
}
|
||||
if( c==0 ) return "unclosed '['";
|
||||
p->aArg[iFirst] = p->nState - iFirst;
|
||||
break;
|
||||
}
|
||||
case '\\': {
|
||||
int specialOp = 0;
|
||||
switch( rePeek(p) ){
|
||||
case 'b': specialOp = RE_OP_BOUNDARY; break;
|
||||
case 'd': specialOp = RE_OP_DIGIT; break;
|
||||
case 'D': specialOp = RE_OP_NOTDIGIT; break;
|
||||
case 's': specialOp = RE_OP_SPACE; break;
|
||||
case 'S': specialOp = RE_OP_NOTSPACE; break;
|
||||
case 'w': specialOp = RE_OP_WORD; break;
|
||||
case 'W': specialOp = RE_OP_NOTWORD; break;
|
||||
}
|
||||
if( specialOp ){
|
||||
p->sIn.i++;
|
||||
re_append(p, specialOp, 0);
|
||||
}else{
|
||||
c = re_esc_char(p);
|
||||
re_append(p, RE_OP_MATCH, c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
re_append(p, RE_OP_MATCH, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
iPrev = iStart;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free and reclaim all the memory used by a previously compiled
|
||||
** regular expression. Applications should invoke this routine once
|
||||
** for every call to re_compile() to avoid memory leaks.
|
||||
*/
|
||||
static void re_free(ReCompiled *pRe){
|
||||
if( pRe ){
|
||||
sqlite3_free(pRe->aOp);
|
||||
sqlite3_free(pRe->aArg);
|
||||
sqlite3_free(pRe);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Compile a textual regular expression in zIn[] into a compiled regular
|
||||
** expression suitable for us by re_match() and return a pointer to the
|
||||
** compiled regular expression in *ppRe. Return NULL on success or an
|
||||
** error message if something goes wrong.
|
||||
*/
|
||||
static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
|
||||
ReCompiled *pRe;
|
||||
const char *zErr;
|
||||
int i, j;
|
||||
|
||||
*ppRe = 0;
|
||||
pRe = sqlite3_malloc( sizeof(*pRe) );
|
||||
if( pRe==0 ){
|
||||
return "out of memory";
|
||||
}
|
||||
memset(pRe, 0, sizeof(*pRe));
|
||||
pRe->xNextChar = noCase ? re_next_char_nocase : re_next_char;
|
||||
if( re_resize(pRe, 30) ){
|
||||
re_free(pRe);
|
||||
return "out of memory";
|
||||
}
|
||||
if( zIn[0]=='^' ){
|
||||
zIn++;
|
||||
}else{
|
||||
re_append(pRe, RE_OP_ANYSTAR, 0);
|
||||
}
|
||||
pRe->sIn.z = (unsigned char*)zIn;
|
||||
pRe->sIn.i = 0;
|
||||
pRe->sIn.mx = (int)strlen(zIn);
|
||||
zErr = re_subcompile_re(pRe);
|
||||
if( zErr ){
|
||||
re_free(pRe);
|
||||
return zErr;
|
||||
}
|
||||
if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){
|
||||
re_append(pRe, RE_OP_MATCH, RE_EOF);
|
||||
re_append(pRe, RE_OP_ACCEPT, 0);
|
||||
*ppRe = pRe;
|
||||
}else if( pRe->sIn.i>=pRe->sIn.mx ){
|
||||
re_append(pRe, RE_OP_ACCEPT, 0);
|
||||
*ppRe = pRe;
|
||||
}else{
|
||||
re_free(pRe);
|
||||
return "unrecognized character";
|
||||
}
|
||||
|
||||
/* The following is a performance optimization. If the regex begins with
|
||||
** ".*" (if the input regex lacks an initial "^") and afterwards there are
|
||||
** one or more matching characters, enter those matching characters into
|
||||
** zInit[]. The re_match() routine can then search ahead in the input
|
||||
** string looking for the initial match without having to run the whole
|
||||
** regex engine over the string. Do not worry able trying to match
|
||||
** unicode characters beyond plane 0 - those are very rare and this is
|
||||
** just an optimization. */
|
||||
if( pRe->aOp[0]==RE_OP_ANYSTAR ){
|
||||
for(j=0, i=1; j<sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
|
||||
unsigned x = pRe->aArg[i];
|
||||
if( x<=127 ){
|
||||
pRe->zInit[j++] = (unsigned char)x;
|
||||
}else if( x<=0xfff ){
|
||||
pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
|
||||
pRe->zInit[j++] = 0x80 | (x&0x3f);
|
||||
}else if( x<=0xffff ){
|
||||
pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12));
|
||||
pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
|
||||
pRe->zInit[j++] = 0x80 | (x&0x3f);
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( j>0 && pRe->zInit[j-1]==0 ) j--;
|
||||
pRe->nInit = j;
|
||||
}
|
||||
return pRe->zErr;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the regexp() SQL function. This function implements
|
||||
** the build-in REGEXP operator. The first argument to the function is the
|
||||
** pattern and the second argument is the string. So, the SQL statements:
|
||||
**
|
||||
** A REGEXP B
|
||||
**
|
||||
** is implemented as regexp(B,A).
|
||||
*/
|
||||
static void re_sql_func(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
ReCompiled *pRe; /* Compiled regular expression */
|
||||
const char *zPattern; /* The regular expression */
|
||||
const unsigned char *zStr;/* String being searched */
|
||||
const char *zErr; /* Compile error message */
|
||||
int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
|
||||
|
||||
pRe = sqlite3_get_auxdata(context, 0);
|
||||
if( pRe==0 ){
|
||||
zPattern = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zPattern==0 ) return;
|
||||
zErr = re_compile(&pRe, zPattern, 0);
|
||||
if( zErr ){
|
||||
re_free(pRe);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
return;
|
||||
}
|
||||
if( pRe==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
setAux = 1;
|
||||
}
|
||||
zStr = (const unsigned char*)sqlite3_value_text(argv[1]);
|
||||
if( zStr!=0 ){
|
||||
sqlite3_result_int(context, re_match(pRe, zStr, -1));
|
||||
}
|
||||
if( setAux ){
|
||||
sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Invoke this routine to register the regexp() function with the
|
||||
** SQLite database connection.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_regexp_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
|
||||
0, re_sql_func, 0, 0);
|
||||
return rc;
|
||||
}
|
@@ -1,53 +1,109 @@
|
||||
/*
|
||||
** Wrapper around SQlite3 amalgamation file with proper options and code
|
||||
** Wrapper around SQlite3 amalgamation file for mORMot use
|
||||
**
|
||||
** Please download and put sqlite3.c in amalgamation/ sub-folder
|
||||
** from https://sqlite.org/download.html
|
||||
** then run ./patch.sh
|
||||
** then follow the amalgamation/ReadMe.md instructions
|
||||
*/
|
||||
|
||||
/*
|
||||
** Define all symbols expected by SynSQLite3Static.pas
|
||||
** Define conditionals / extensions specially tuned for mORMot
|
||||
**
|
||||
** See also https://www.sqlite.org/compile.html#recommended_compile_time_options
|
||||
*/
|
||||
|
||||
#define SQLITE_DEFAULT_MEMSTATUS 0
|
||||
// don't need any debug here, and don't even define sqlite3_status()
|
||||
#define SQLITE_THREADSAFE 1
|
||||
|
||||
// assuming multi-thread safety is made by caller - in our framework, there is
|
||||
// only one thread using the database connection at the same time, but there could
|
||||
// be multiple database connection at the same time (previous was 0 could be unsafe)
|
||||
// - this option is also needed by codecext.c
|
||||
// be multiple database connection at the same time
|
||||
// * 0 = single-thread = all mutexes disabled - seems unsafe
|
||||
// * 1 = serialized = all calls serialized - seems overkill
|
||||
// * 2 = multi-thread = thread-safe by connection - fine for our purpose
|
||||
// - note that we keep 1=serialized at compile time (to allow all modes)
|
||||
// but SQLITE_CONFIG_MULTITHREAD is set in TSqlite3Library.BeforeInitialization
|
||||
// and rely on TSqlDataBase to do explicit Lock/LockJson/UnLock calls
|
||||
#if SQLITE_NO_THREAD
|
||||
# define SQLITE_THREADSAFE 0
|
||||
#else
|
||||
# define SQLITE_THREADSAFE 1
|
||||
#endif
|
||||
|
||||
#define SQLITE_OMIT_SHARED_CACHE 1
|
||||
// no need of shared cache in a threadsafe calling model
|
||||
|
||||
#define SQLITE_OMIT_AUTOINIT 1
|
||||
// sqlite3_initialize() is done in unit initialization -> no AUTOINIT
|
||||
// sqlite3_initialize() is done in unit initialization -> no AUTOINIT
|
||||
|
||||
#define SQLITE_OMIT_DEPRECATED 1
|
||||
// spare some code size
|
||||
// spare some code size
|
||||
|
||||
|
||||
#define SQLITE_LIKE_DOESNT_MATCH_BLOBS 1
|
||||
// historical function, never used
|
||||
|
||||
#define SQLITE_ENABLE_FTS3 1
|
||||
#define SQLITE_ENABLE_FTS3_PARENTHESIS 1
|
||||
#define SQLITE_ENABLE_FTS4 1
|
||||
#define SQLITE_ENABLE_FTS5 1
|
||||
// enable all FTS engines
|
||||
#define SQLITE_ENABLE_RBU 1
|
||||
// "Resumable Bulk Update" (or OTA) is not used/published yet
|
||||
// enable all FTS engines https://www.sqlite.org/fts3.html https://www.sqlite.org/fts5.html
|
||||
|
||||
#define SQLITE_ENABLE_JSON1 1
|
||||
// add JSON extension
|
||||
// enable JSON https://www.sqlite.org/json1.html
|
||||
|
||||
#define SQLITE_MAX_EXPR_DEPTH 0
|
||||
// no SQL depth limit, since we trust the input and expect the best performance
|
||||
#define SQLITE_OMIT_LOAD_EXTENSION 1
|
||||
// we don't need/allow extension in an embedded engine
|
||||
#define SQLITE_OMIT_COMPILEOPTION_DIAGS 1
|
||||
// we don't need Compilation Options Diagnostics in our embedded engine
|
||||
#define SQLITE_OMIT_PROGRESS_CALLBACK 1
|
||||
// we don't need sqlite3_progress_handler() API function
|
||||
#define SQLITE_ENABLE_RTREE 1
|
||||
// the RTREE extension is now (from v.1.8/3.7) compiled into the engine
|
||||
|
||||
#define SQLITE_ENABLE_DESERIALIZE
|
||||
// enables sqlite3_serialize() and sqlite3_deserialize()
|
||||
// enable sqlite3_serialize() and sqlite3_deserialize()
|
||||
|
||||
#define SQLITE_ENABLE_RTREE 1
|
||||
// enable RTREE https://sqlite.org/rtree.html
|
||||
|
||||
#define SQLITE_ENABLE_GEOPOLY 1
|
||||
// enable GeoJSON over RTREE https://sqlite.org/geopoly.html
|
||||
|
||||
#define SQLITE_ENABLE_REGEXP 1
|
||||
// enable the compact https://www.sqlite.org/src/file?name=ext/misc/regexp.c
|
||||
// - can be overloaded with any other implementation
|
||||
|
||||
#define SQLITE_ENABLE_RBU 1
|
||||
// enable "Resumable Bulk Update" (or OTA) https://www.sqlite.org/rbu.html
|
||||
|
||||
#define SQLITE_ENABLE_SESSION 1
|
||||
#define SQLITE_ENABLE_PREUPDATE_HOOK 1
|
||||
// enable Sessions https://sqlite.org/sessionintro.html
|
||||
|
||||
#define SQLITE_ENABLE_NORMALIZE 1
|
||||
// enable all https://sqlite.org/c3ref/expanded_sql.html functions
|
||||
|
||||
#define YYTRACKMAXSTACKDEPTH 1
|
||||
// enable SQLITE_STATUS_PARSER_STACK support
|
||||
|
||||
#define SQLITE_ENABLE_COLUMN_METADATA 1
|
||||
//enable column_database_name, column_table_name and column_origin_name support
|
||||
|
||||
#define SQLITE_ENABLE_STMT_SCANSTATUS 1
|
||||
// enable stmt_scanstatus and stmt_scanstatus_reset support
|
||||
|
||||
#define SQLITE_ENABLE_SNAPSHOT 1
|
||||
// support the sqlite3_snapshot object
|
||||
|
||||
#define SQLITE_ENABLE_UNLOCK_NOTIFY 1
|
||||
// enable sqlite3_unlock_notify
|
||||
|
||||
/*
|
||||
** Disabled conditionals / extensions
|
||||
*/
|
||||
|
||||
// #define SQLITE_ENABLE_ICU
|
||||
// disabled because induces a huge dependency - use WIN32NOCASE (which calls
|
||||
// ICU on POSIX) or even better the UNICODENOCASE as available in mORMot 2
|
||||
|
||||
// #define SQLITE_ENABLE_STAT4
|
||||
// adds additional logic to the ANALYZE command and to the Query Planner
|
||||
|
||||
|
||||
/*
|
||||
** Define function for extra initilization
|
||||
@@ -229,6 +285,18 @@ static unsigned char* CodecGetPageBuffer(Codec* codec)
|
||||
|
||||
#include "codecext.c"
|
||||
|
||||
/*
|
||||
** REGEXP
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_REGEXP
|
||||
/* Prototype for initialization function of REGEXP extension */
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_regexp_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi);
|
||||
#include "regexp.c"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Multi cipher VFS
|
||||
*/
|
||||
@@ -259,6 +327,17 @@ sqlite3mc_initialize(const char* arg)
|
||||
}
|
||||
rc = sqlite3mc_vfs_initialize(vfsDefault, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Can be overloaded later with any other REGEXP engine
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_REGEXP
|
||||
if (rc == SQLITE_OK)
|
||||
{
|
||||
rc = sqlite3_auto_extension((void(*)(void)) sqlite3_regexp_init);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user