mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 00:03:02 +01:00
Fixed CORE-4811: Make user names behave according to SQL identifiers rules
This commit is contained in:
parent
ebdf793154
commit
1b6632ac8b
@ -31,6 +31,10 @@
|
||||
#include "../common/classes/auto.h"
|
||||
#include "../common/SimpleStatusVector.h"
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
|
||||
int CLIB_ROUTINE main(int argc, char* argv[])
|
||||
{
|
||||
@ -44,6 +48,11 @@ int CLIB_ROUTINE main(int argc, char* argv[])
|
||||
* Invoke real gfix main function
|
||||
*
|
||||
**************************************/
|
||||
#ifdef HAVE_LOCALE_H
|
||||
// Pick up the system locale to allow SYSTEM<->UTF8 conversions
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
Firebird::AutoPtr<Firebird::UtilSvc> uSvc(Firebird::UtilSvc::createStandalone(argc, argv));
|
||||
|
@ -342,8 +342,6 @@ int SecurityDatabase::verify(IWriter* authBlock, IServerBlock* sBlock)
|
||||
return IAuth::AUTH_MORE_DATA;
|
||||
}
|
||||
|
||||
login.upper();
|
||||
|
||||
// Look up the user name in the userinfo database and use the parameters
|
||||
// found there. This means that another database must be accessed, and
|
||||
// that means the current context must be saved and restored.
|
||||
|
@ -31,6 +31,9 @@
|
||||
#include "../common/classes/auto.h"
|
||||
#include "../common/SimpleStatusVector.h"
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
int CLIB_ROUTINE main( int argc, char* argv[])
|
||||
{
|
||||
@ -44,6 +47,11 @@ int CLIB_ROUTINE main( int argc, char* argv[])
|
||||
* Invoke real gbak main function
|
||||
*
|
||||
**************************************/
|
||||
#ifdef HAVE_LOCALE_H
|
||||
// Pick up the system locale to allow SYSTEM<->UTF8 conversions
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
Firebird::AutoPtr<Firebird::UtilSvc> uSvc(Firebird::UtilSvc::createStandalone(argc, argv));
|
||||
|
@ -59,6 +59,10 @@
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
static const int mode_read = O_RDONLY;
|
||||
static const int mode_write = O_WRONLY | O_CREAT;
|
||||
static const int mask = 0666;
|
||||
@ -188,6 +192,11 @@ static int write_header(const b_fil*, header_rec, FILE_DESC, TEXT*);
|
||||
|
||||
int main( int argc, char* argv[])
|
||||
{
|
||||
#ifdef HAVE_LOCALE_H
|
||||
// Pick up the system locale to allow SYSTEM<->UTF8 conversions
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
const SCHAR* const prog_name = argv[0];
|
||||
|
||||
if (argc < 2)
|
||||
|
@ -67,7 +67,7 @@ void WriterImplementation::add(Firebird::CheckStatusWrapper* st, const char* nam
|
||||
putLevel();
|
||||
|
||||
current.clear();
|
||||
current.insertString(AuthReader::AUTH_NAME, name);
|
||||
current.insertString(AuthReader::AUTH_NAME, name, strlen(name));
|
||||
fb_assert(plugin.hasData());
|
||||
if (plugin.hasData())
|
||||
{
|
||||
|
@ -85,20 +85,6 @@ public:
|
||||
static ULONG toUpper(Jrd::CharSet* cs, ULONG srcLen, const UCHAR* src, ULONG dstLen, UCHAR* dst,
|
||||
const ULONG* exceptions);
|
||||
|
||||
template <typename STR>
|
||||
static void toUpper(STR& s, Jrd::CharSet* cs = getUtf8CharSet())
|
||||
{
|
||||
HalfStaticArray<UCHAR, BUFFER_SMALL> buffer;
|
||||
FB_SIZE_T len = s.length();
|
||||
ULONG count = toUpper(cs, len, reinterpret_cast<const UCHAR*>(s.c_str()), len * 4,
|
||||
buffer.getBuffer(len * 4), NULL);
|
||||
|
||||
if (count != INTL_BAD_STR_LENGTH)
|
||||
s.assign(reinterpret_cast<const char*>(buffer.begin()), count);
|
||||
else
|
||||
fb_assert(false);
|
||||
}
|
||||
|
||||
static bool readOneChar(Jrd::CharSet* cs, const UCHAR** s, const UCHAR* end, ULONG* size);
|
||||
|
||||
static bool setupIcuAttributes(charset* cs, const string& specificAttributes,
|
||||
|
168
src/common/Tokens.cpp
Normal file
168
src/common/Tokens.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* PROGRAM: String parser
|
||||
* MODULE: Tokens.cpp
|
||||
* DESCRIPTION: Enhanced variant of strtok()
|
||||
*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Alex Peshkov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2015 Alex Peshkov <peshkoff at mail.ru>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../common/Tokens.h"
|
||||
|
||||
#include "../common/StatusArg.h"
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
Tokens::Tokens(FB_SIZE_T length, const char* toParse, const char* spaces, const char* quotes, const Comment* comments)
|
||||
: tokens(getPool()), str(getPool())
|
||||
{
|
||||
if (!length)
|
||||
length = strlen(toParse);
|
||||
str.assign(toParse, length);
|
||||
|
||||
char inStr = 0;
|
||||
Tok* inToken = NULL;
|
||||
FB_SIZE_T startp = 0;
|
||||
FB_SIZE_T origin = 0;
|
||||
|
||||
FB_SIZE_T p = 0;
|
||||
while (p < str.length())
|
||||
{
|
||||
if (comments && !inStr)
|
||||
{
|
||||
for (const Comment* comm = comments; comm->start; ++comm)
|
||||
{
|
||||
if (strncmp(comm->start, &str[p], strlen(comm->start)) == 0)
|
||||
{
|
||||
FB_SIZE_T p2 = p + strlen(comm->start);
|
||||
p2 = str.find(comm->stop, p2);
|
||||
if (p2 == str.npos)
|
||||
error("Missing close comment for %s", comm->start);
|
||||
p2 += strlen(comm->stop);
|
||||
str.erase(p, p2 - p);
|
||||
origin += (p2 - p);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char c = str[p];
|
||||
if (inStr)
|
||||
{
|
||||
if (c == inStr)
|
||||
{
|
||||
++p;
|
||||
++origin;
|
||||
if (p >= str.length() || str[p] != inStr)
|
||||
{
|
||||
inStr = 0;
|
||||
inToken->length = p - startp;
|
||||
inToken = NULL;
|
||||
continue;
|
||||
}
|
||||
// double quote - continue processing string
|
||||
}
|
||||
++p;
|
||||
++origin;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool space = spaces && strchr(spaces, c);
|
||||
if (space)
|
||||
{
|
||||
if (inToken)
|
||||
{
|
||||
inToken->length = p - startp;
|
||||
inToken = NULL;
|
||||
}
|
||||
++p;
|
||||
++origin;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool quote = quotes && strchr(quotes, c);
|
||||
if (quote)
|
||||
{
|
||||
if (inToken)
|
||||
{
|
||||
inToken->length = p - startp;
|
||||
inToken = NULL;
|
||||
}
|
||||
// start string
|
||||
inStr = c;
|
||||
}
|
||||
|
||||
if (!inToken)
|
||||
{
|
||||
// start token
|
||||
startp = p;
|
||||
tokens.grow(tokens.getCount() + 1);
|
||||
inToken = &tokens[tokens.getCount() - 1];
|
||||
inToken->text = &str[p];
|
||||
inToken->origin = origin;
|
||||
}
|
||||
|
||||
// done with char
|
||||
++p;
|
||||
++origin;
|
||||
}
|
||||
|
||||
if (inStr)
|
||||
error("Missing close quote <%c>", inStr);
|
||||
|
||||
if (inToken)
|
||||
inToken->length = p - startp;
|
||||
}
|
||||
|
||||
void Tokens::error(const char* fmt, ...)
|
||||
{
|
||||
string buffer;
|
||||
|
||||
va_list params;
|
||||
va_start(params, fmt);
|
||||
buffer.vprintf(fmt, params);
|
||||
va_end(params);
|
||||
|
||||
(Arg::Gds(isc_random) << "Parse to tokens error" << Arg::Gds(isc_random) << buffer).raise();
|
||||
}
|
||||
|
||||
string Tokens::Tok::stripped() const
|
||||
{
|
||||
string rc;
|
||||
char q = text[0];
|
||||
for (FB_SIZE_T i = 1; i < length - 1; ++i)
|
||||
{
|
||||
if (text[i] == q)
|
||||
++i;
|
||||
rc += text[i];
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Tokens::Comment sqlComments[3] = {
|
||||
{ "/*", "*/" },
|
||||
{ "--", "\n" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
const char* sqlSpaces = " \t\r\n";
|
||||
|
||||
} // namespace Firebird
|
79
src/common/Tokens.h
Normal file
79
src/common/Tokens.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* PROGRAM: String parser
|
||||
* MODULE: Tokens.h
|
||||
* DESCRIPTION: Enhanced variant of strtok()
|
||||
*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Alex Peshkov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2015 Alex Peshkov <peshkoff at mail.ru>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FB_TOKENS_H
|
||||
#define FB_TOKENS_H
|
||||
|
||||
#include "firebird/Interface.h"
|
||||
#include "../common/classes/array.h"
|
||||
#include "../common/classes/fb_string.h"
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
class Tokens : public AutoStorage
|
||||
{
|
||||
public:
|
||||
struct Comment
|
||||
{
|
||||
const char* start;
|
||||
const char* stop;
|
||||
};
|
||||
|
||||
Tokens(FB_SIZE_T length, const char* string, const char* spaces, const char* quotes, const Comment* comments);
|
||||
|
||||
struct Tok
|
||||
{
|
||||
const char* text;
|
||||
FB_SIZE_T length, origin;
|
||||
string stripped() const;
|
||||
};
|
||||
|
||||
const Tok& operator[](FB_SIZE_T pos) const
|
||||
{
|
||||
return tokens[pos];
|
||||
}
|
||||
|
||||
FB_SIZE_T getCount() const
|
||||
{
|
||||
return tokens.getCount();
|
||||
}
|
||||
|
||||
private:
|
||||
static void error(const char* fmt, ...);
|
||||
|
||||
HalfStaticArray<Tok, 16> tokens;
|
||||
string str;
|
||||
};
|
||||
|
||||
extern Tokens::Comment sqlComments[3];
|
||||
extern const char* sqlSpaces;
|
||||
|
||||
} // namespace Firebird
|
||||
|
||||
|
||||
#endif // FB_AUTH_H
|
@ -45,7 +45,6 @@ void ISC_systemToUtf8(Firebird::AbstractString& str);
|
||||
void ISC_utf8ToSystem(Firebird::AbstractString& str);
|
||||
void ISC_escape(Firebird::AbstractString& str);
|
||||
void ISC_unescape(Firebird::AbstractString& str);
|
||||
void ISC_utf8Upper(Firebird::AbstractString& str);
|
||||
|
||||
// This form of ISC_expand_filename makes epp files happy
|
||||
inline bool ISC_expand_filename(const TEXT* unexpanded, USHORT len_unexpanded,
|
||||
|
@ -86,7 +86,6 @@
|
||||
#endif
|
||||
|
||||
#include "../common/config/config.h"
|
||||
#include "../common/unicodeUpper.h"
|
||||
|
||||
const char INET_FLAG = ':';
|
||||
|
||||
@ -1692,12 +1691,10 @@ class Converters
|
||||
public:
|
||||
explicit Converters(MemoryPool& p)
|
||||
: systemToUtf8(p, IConv::SYSTEM, "UTF-8"),
|
||||
utf8ToSystem(p, "UTF-8", IConv::SYSTEM),
|
||||
unicodeToUtf8(p, "UNICODE", "UTF-8"),
|
||||
utf8ToUnicode(p, "UTF-8", "UNICODE")
|
||||
utf8ToSystem(p, "UTF-8", IConv::SYSTEM)
|
||||
{ }
|
||||
|
||||
IConv systemToUtf8, utf8ToSystem, unicodeToUtf8, utf8ToUnicode;
|
||||
IConv systemToUtf8, utf8ToSystem;
|
||||
};
|
||||
|
||||
|
||||
@ -1806,47 +1803,6 @@ private:
|
||||
#endif // WIN_NT
|
||||
|
||||
|
||||
void ISC_utf8Upper(Firebird::AbstractString& str)
|
||||
{
|
||||
if (str.isEmpty())
|
||||
return;
|
||||
|
||||
#if defined(WIN_NT)
|
||||
WideCharBuffer<256> wBuffer;
|
||||
|
||||
bool error = !wBuffer.fromString(CP_UTF8, str);
|
||||
if (!error)
|
||||
{
|
||||
WCHAR* wch = wBuffer.getBuffer();
|
||||
const WCHAR* const end = wch + wBuffer.getLength();
|
||||
for (; wch < end; wch++)
|
||||
*wch = unicodeUpper(*wch);
|
||||
|
||||
error = !wBuffer.toString(CP_UTF8, str);
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
DWORD errCode = GetLastError();
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_bad_conn_str) << Arg::Gds(isc_transliteration_failed) <<
|
||||
Arg::Windows(errCode));
|
||||
}
|
||||
|
||||
#elif defined(HAVE_ICONV_H)
|
||||
iConv().utf8ToUnicode.convert(str);
|
||||
|
||||
{ // aligner scope
|
||||
Firebird::BiAligner<unsigned short> alignedStr(reinterpret_cast<UCHAR*>(str.begin()), str.length());
|
||||
unsigned short* const end = alignedStr + (str.length() / 2);
|
||||
for (unsigned short* begin = alignedStr; begin < end; ++begin)
|
||||
*begin = unicodeUpper(*begin);
|
||||
}
|
||||
|
||||
iConv().unicodeToUtf8.convert(str);
|
||||
#endif // HAVE_ICONV_H
|
||||
}
|
||||
|
||||
// Converts a string from the system charset to UTF-8.
|
||||
void ISC_systemToUtf8(Firebird::AbstractString& str)
|
||||
{
|
||||
|
@ -1,727 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: Firebird generic routine
|
||||
* MODULE: unicodeUpper.cpp
|
||||
* DESCRIPTION: Converts unicode character to uppercase.
|
||||
*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Alex Peshkov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2015 Alex Peshkov <peshkoff at mail.ru>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../common/unicodeUpper.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Conversion table based on:
|
||||
// http://www-01.ibm.com/support/knowledgecenter/ssw_i5_54/nls/rbagslowtoupmaptable.htm
|
||||
|
||||
unsigned short table[] = {
|
||||
0x0061, 0x0041,
|
||||
0x0062, 0x0042,
|
||||
0x0063, 0x0043,
|
||||
0x0064, 0x0044,
|
||||
0x0065, 0x0045,
|
||||
0x0066, 0x0046,
|
||||
0x0067, 0x0047,
|
||||
0x0068, 0x0048,
|
||||
0x0069, 0x0049,
|
||||
0x006A, 0x004A,
|
||||
0x006B, 0x004B,
|
||||
0x006C, 0x004C,
|
||||
0x006D, 0x004D,
|
||||
0x006E, 0x004E,
|
||||
0x006F, 0x004F,
|
||||
0x0070, 0x0050,
|
||||
0x0071, 0x0051,
|
||||
0x0072, 0x0052,
|
||||
0x0073, 0x0053,
|
||||
0x0074, 0x0054,
|
||||
0x0075, 0x0055,
|
||||
0x0076, 0x0056,
|
||||
0x0077, 0x0057,
|
||||
0x0078, 0x0058,
|
||||
0x0079, 0x0059,
|
||||
0x007A, 0x005A,
|
||||
0x00E0, 0x00C0,
|
||||
0x00E1, 0x00C1,
|
||||
0x00E2, 0x00C2,
|
||||
0x00E3, 0x00C3,
|
||||
0x00E4, 0x00C4,
|
||||
0x00E5, 0x00C5,
|
||||
0x00E6, 0x00C6,
|
||||
0x00E7, 0x00C7,
|
||||
0x00E8, 0x00C8,
|
||||
0x00E9, 0x00C9,
|
||||
0x00EA, 0x00CA,
|
||||
0x00EB, 0x00CB,
|
||||
0x00EC, 0x00CC,
|
||||
0x00ED, 0x00CD,
|
||||
0x00EE, 0x00CE,
|
||||
0x00EF, 0x00CF,
|
||||
0x00F0, 0x00D0,
|
||||
0x00F1, 0x00D1,
|
||||
0x00F2, 0x00D2,
|
||||
0x00F3, 0x00D3,
|
||||
0x00F4, 0x00D4,
|
||||
0x00F5, 0x00D5,
|
||||
0x00F6, 0x00D6,
|
||||
0x00F8, 0x00D8,
|
||||
0x00F9, 0x00D9,
|
||||
0x00FA, 0x00DA,
|
||||
0x00FB, 0x00DB,
|
||||
0x00FC, 0x00DC,
|
||||
0x00FD, 0x00DD,
|
||||
0x00FE, 0x00DE,
|
||||
0x00FF, 0x0178,
|
||||
0x0101, 0x0100,
|
||||
0x0103, 0x0102,
|
||||
0x0105, 0x0104,
|
||||
0x0107, 0x0106,
|
||||
0x0109, 0x0108,
|
||||
0x010B, 0x010A,
|
||||
0x010D, 0x010C,
|
||||
0x010F, 0x010E,
|
||||
0x0111, 0x0110,
|
||||
0x0113, 0x0112,
|
||||
0x0115, 0x0114,
|
||||
0x0117, 0x0116,
|
||||
0x0119, 0x0118,
|
||||
0x011B, 0x011A,
|
||||
0x011D, 0x011C,
|
||||
0x011F, 0x011E,
|
||||
0x0121, 0x0120,
|
||||
0x0123, 0x0122,
|
||||
0x0125, 0x0124,
|
||||
0x0127, 0x0126,
|
||||
0x0129, 0x0128,
|
||||
0x012B, 0x012A,
|
||||
0x012D, 0x012C,
|
||||
0x012F, 0x012E,
|
||||
0x0131, 0x0049,
|
||||
0x0133, 0x0132,
|
||||
0x0135, 0x0134,
|
||||
0x0137, 0x0136,
|
||||
0x013A, 0x0139,
|
||||
0x013C, 0x013B,
|
||||
0x013E, 0x013D,
|
||||
0x0140, 0x013F,
|
||||
0x0142, 0x0141,
|
||||
0x0144, 0x0143,
|
||||
0x0146, 0x0145,
|
||||
0x0148, 0x0147,
|
||||
0x014B, 0x014A,
|
||||
0x014D, 0x014C,
|
||||
0x014F, 0x014E,
|
||||
0x0151, 0x0150,
|
||||
0x0153, 0x0152,
|
||||
0x0155, 0x0154,
|
||||
0x0157, 0x0156,
|
||||
0x0159, 0x0158,
|
||||
0x015B, 0x015A,
|
||||
0x015D, 0x015C,
|
||||
0x015F, 0x015E,
|
||||
0x0161, 0x0160,
|
||||
0x0163, 0x0162,
|
||||
0x0165, 0x0164,
|
||||
0x0167, 0x0166,
|
||||
0x0169, 0x0168,
|
||||
0x016B, 0x016A,
|
||||
0x016D, 0x016C,
|
||||
0x016F, 0x016E,
|
||||
0x0171, 0x0170,
|
||||
0x0173, 0x0172,
|
||||
0x0175, 0x0174,
|
||||
0x0177, 0x0176,
|
||||
0x017A, 0x0179,
|
||||
0x017C, 0x017B,
|
||||
0x017E, 0x017D,
|
||||
0x0183, 0x0182,
|
||||
0x0185, 0x0184,
|
||||
0x0188, 0x0187,
|
||||
0x018C, 0x018B,
|
||||
0x0192, 0x0191,
|
||||
0x0199, 0x0198,
|
||||
0x01A1, 0x01A0,
|
||||
0x01A3, 0x01A2,
|
||||
0x01A5, 0x01A4,
|
||||
0x01A8, 0x01A7,
|
||||
0x01AD, 0x01AC,
|
||||
0x01B0, 0x01AF,
|
||||
0x01B4, 0x01B3,
|
||||
0x01B6, 0x01B5,
|
||||
0x01B9, 0x01B8,
|
||||
0x01BD, 0x01BC,
|
||||
0x01C6, 0x01C4,
|
||||
0x01C9, 0x01C7,
|
||||
0x01CC, 0x01CA,
|
||||
0x01CE, 0x01CD,
|
||||
0x01D0, 0x01CF,
|
||||
0x01D2, 0x01D1,
|
||||
0x01D4, 0x01D3,
|
||||
0x01D6, 0x01D5,
|
||||
0x01D8, 0x01D7,
|
||||
0x01DA, 0x01D9,
|
||||
0x01DC, 0x01DB,
|
||||
0x01DF, 0x01DE,
|
||||
0x01E1, 0x01E0,
|
||||
0x01E3, 0x01E2,
|
||||
0x01E5, 0x01E4,
|
||||
0x01E7, 0x01E6,
|
||||
0x01E9, 0x01E8,
|
||||
0x01EB, 0x01EA,
|
||||
0x01ED, 0x01EC,
|
||||
0x01EF, 0x01EE,
|
||||
0x01F3, 0x01F1,
|
||||
0x01F5, 0x01F4,
|
||||
0x01FB, 0x01FA,
|
||||
0x01FD, 0x01FC,
|
||||
0x01FF, 0x01FE,
|
||||
0x0201, 0x0200,
|
||||
0x0203, 0x0202,
|
||||
0x0205, 0x0204,
|
||||
0x0207, 0x0206,
|
||||
0x0209, 0x0208,
|
||||
0x020B, 0x020A,
|
||||
0x020D, 0x020C,
|
||||
0x020F, 0x020E,
|
||||
0x0211, 0x0210,
|
||||
0x0213, 0x0212,
|
||||
0x0215, 0x0214,
|
||||
0x0217, 0x0216,
|
||||
0x0253, 0x0181,
|
||||
0x0254, 0x0186,
|
||||
0x0257, 0x018A,
|
||||
0x0258, 0x018E,
|
||||
0x0259, 0x018F,
|
||||
0x025B, 0x0190,
|
||||
0x0260, 0x0193,
|
||||
0x0263, 0x0194,
|
||||
0x0268, 0x0197,
|
||||
0x0269, 0x0196,
|
||||
0x026F, 0x019C,
|
||||
0x0272, 0x019D,
|
||||
0x0275, 0x019F,
|
||||
0x0283, 0x01A9,
|
||||
0x0288, 0x01AE,
|
||||
0x028A, 0x01B1,
|
||||
0x028B, 0x01B2,
|
||||
0x0292, 0x01B7,
|
||||
0x03AC, 0x0386,
|
||||
0x03AD, 0x0388,
|
||||
0x03AE, 0x0389,
|
||||
0x03AF, 0x038A,
|
||||
0x03B1, 0x0391,
|
||||
0x03B2, 0x0392,
|
||||
0x03B3, 0x0393,
|
||||
0x03B4, 0x0394,
|
||||
0x03B5, 0x0395,
|
||||
0x03B6, 0x0396,
|
||||
0x03B7, 0x0397,
|
||||
0x03B8, 0x0398,
|
||||
0x03B9, 0x0399,
|
||||
0x03BA, 0x039A,
|
||||
0x03BB, 0x039B,
|
||||
0x03BC, 0x039C,
|
||||
0x03BD, 0x039D,
|
||||
0x03BE, 0x039E,
|
||||
0x03BF, 0x039F,
|
||||
0x03C0, 0x03A0,
|
||||
0x03C1, 0x03A1,
|
||||
0x03C3, 0x03A3,
|
||||
0x03C4, 0x03A4,
|
||||
0x03C5, 0x03A5,
|
||||
0x03C6, 0x03A6,
|
||||
0x03C7, 0x03A7,
|
||||
0x03C8, 0x03A8,
|
||||
0x03C9, 0x03A9,
|
||||
0x03CA, 0x03AA,
|
||||
0x03CB, 0x03AB,
|
||||
0x03CC, 0x038C,
|
||||
0x03CD, 0x038E,
|
||||
0x03CE, 0x038F,
|
||||
0x03E3, 0x03E2,
|
||||
0x03E5, 0x03E4,
|
||||
0x03E7, 0x03E6,
|
||||
0x03E9, 0x03E8,
|
||||
0x03EB, 0x03EA,
|
||||
0x03ED, 0x03EC,
|
||||
0x03EF, 0x03EE,
|
||||
0x0430, 0x0410,
|
||||
0x0431, 0x0411,
|
||||
0x0432, 0x0412,
|
||||
0x0433, 0x0413,
|
||||
0x0434, 0x0414,
|
||||
0x0435, 0x0415,
|
||||
0x0436, 0x0416,
|
||||
0x0437, 0x0417,
|
||||
0x0438, 0x0418,
|
||||
0x0439, 0x0419,
|
||||
0x043A, 0x041A,
|
||||
0x043B, 0x041B,
|
||||
0x043C, 0x041C,
|
||||
0x043D, 0x041D,
|
||||
0x043E, 0x041E,
|
||||
0x043F, 0x041F,
|
||||
0x0440, 0x0420,
|
||||
0x0441, 0x0421,
|
||||
0x0442, 0x0422,
|
||||
0x0443, 0x0423,
|
||||
0x0444, 0x0424,
|
||||
0x0445, 0x0425,
|
||||
0x0446, 0x0426,
|
||||
0x0447, 0x0427,
|
||||
0x0448, 0x0428,
|
||||
0x0449, 0x0429,
|
||||
0x044A, 0x042A,
|
||||
0x044B, 0x042B,
|
||||
0x044C, 0x042C,
|
||||
0x044D, 0x042D,
|
||||
0x044E, 0x042E,
|
||||
0x044F, 0x042F,
|
||||
0x0451, 0x0401,
|
||||
0x0452, 0x0402,
|
||||
0x0453, 0x0403,
|
||||
0x0454, 0x0404,
|
||||
0x0455, 0x0405,
|
||||
0x0456, 0x0406,
|
||||
0x0457, 0x0407,
|
||||
0x0458, 0x0408,
|
||||
0x0459, 0x0409,
|
||||
0x045A, 0x040A,
|
||||
0x045B, 0x040B,
|
||||
0x045C, 0x040C,
|
||||
0x045E, 0x040E,
|
||||
0x045F, 0x040F,
|
||||
0x0461, 0x0460,
|
||||
0x0463, 0x0462,
|
||||
0x0465, 0x0464,
|
||||
0x0467, 0x0466,
|
||||
0x0469, 0x0468,
|
||||
0x046B, 0x046A,
|
||||
0x046D, 0x046C,
|
||||
0x046F, 0x046E,
|
||||
0x0471, 0x0470,
|
||||
0x0473, 0x0472,
|
||||
0x0475, 0x0474,
|
||||
0x0477, 0x0476,
|
||||
0x0479, 0x0478,
|
||||
0x047B, 0x047A,
|
||||
0x047D, 0x047C,
|
||||
0x047F, 0x047E,
|
||||
0x0481, 0x0480,
|
||||
0x0491, 0x0490,
|
||||
0x0493, 0x0492,
|
||||
0x0495, 0x0494,
|
||||
0x0497, 0x0496,
|
||||
0x0499, 0x0498,
|
||||
0x049B, 0x049A,
|
||||
0x049D, 0x049C,
|
||||
0x049F, 0x049E,
|
||||
0x04A1, 0x04A0,
|
||||
0x04A3, 0x04A2,
|
||||
0x04A5, 0x04A4,
|
||||
0x04A7, 0x04A6,
|
||||
0x04A9, 0x04A8,
|
||||
0x04AB, 0x04AA,
|
||||
0x04AD, 0x04AC,
|
||||
0x04AF, 0x04AE,
|
||||
0x04B1, 0x04B0,
|
||||
0x04B3, 0x04B2,
|
||||
0x04B5, 0x04B4,
|
||||
0x04B7, 0x04B6,
|
||||
0x04B9, 0x04B8,
|
||||
0x04BB, 0x04BA,
|
||||
0x04BD, 0x04BC,
|
||||
0x04BF, 0x04BE,
|
||||
0x04C2, 0x04C1,
|
||||
0x04C4, 0x04C3,
|
||||
0x04C8, 0x04C7,
|
||||
0x04CC, 0x04CB,
|
||||
0x04D1, 0x04D0,
|
||||
0x04D3, 0x04D2,
|
||||
0x04D5, 0x04D4,
|
||||
0x04D7, 0x04D6,
|
||||
0x04D9, 0x04D8,
|
||||
0x04DB, 0x04DA,
|
||||
0x04DD, 0x04DC,
|
||||
0x04DF, 0x04DE,
|
||||
0x04E1, 0x04E0,
|
||||
0x04E3, 0x04E2,
|
||||
0x04E5, 0x04E4,
|
||||
0x04E7, 0x04E6,
|
||||
0x04E9, 0x04E8,
|
||||
0x04EB, 0x04EA,
|
||||
0x04EF, 0x04EE,
|
||||
0x04F1, 0x04F0,
|
||||
0x04F3, 0x04F2,
|
||||
0x04F5, 0x04F4,
|
||||
0x04F9, 0x04F8,
|
||||
0x0561, 0x0531,
|
||||
0x0562, 0x0532,
|
||||
0x0563, 0x0533,
|
||||
0x0564, 0x0534,
|
||||
0x0565, 0x0535,
|
||||
0x0566, 0x0536,
|
||||
0x0567, 0x0537,
|
||||
0x0568, 0x0538,
|
||||
0x0569, 0x0539,
|
||||
0x056A, 0x053A,
|
||||
0x056B, 0x053B,
|
||||
0x056C, 0x053C,
|
||||
0x056D, 0x053D,
|
||||
0x056E, 0x053E,
|
||||
0x056F, 0x053F,
|
||||
0x0570, 0x0540,
|
||||
0x0571, 0x0541,
|
||||
0x0572, 0x0542,
|
||||
0x0573, 0x0543,
|
||||
0x0574, 0x0544,
|
||||
0x0575, 0x0545,
|
||||
0x0576, 0x0546,
|
||||
0x0577, 0x0547,
|
||||
0x0578, 0x0548,
|
||||
0x0579, 0x0549,
|
||||
0x057A, 0x054A,
|
||||
0x057B, 0x054B,
|
||||
0x057C, 0x054C,
|
||||
0x057D, 0x054D,
|
||||
0x057E, 0x054E,
|
||||
0x057F, 0x054F,
|
||||
0x0580, 0x0550,
|
||||
0x0581, 0x0551,
|
||||
0x0582, 0x0552,
|
||||
0x0583, 0x0553,
|
||||
0x0584, 0x0554,
|
||||
0x0585, 0x0555,
|
||||
0x0586, 0x0556,
|
||||
0x10D0, 0x10A0,
|
||||
0x10D1, 0x10A1,
|
||||
0x10D2, 0x10A2,
|
||||
0x10D3, 0x10A3,
|
||||
0x10D4, 0x10A4,
|
||||
0x10D5, 0x10A5,
|
||||
0x10D6, 0x10A6,
|
||||
0x10D7, 0x10A7,
|
||||
0x10D8, 0x10A8,
|
||||
0x10D9, 0x10A9,
|
||||
0x10DA, 0x10AA,
|
||||
0x10DB, 0x10AB,
|
||||
0x10DC, 0x10AC,
|
||||
0x10DD, 0x10AD,
|
||||
0x10DE, 0x10AE,
|
||||
0x10DF, 0x10AF,
|
||||
0x10E0, 0x10B0,
|
||||
0x10E1, 0x10B1,
|
||||
0x10E2, 0x10B2,
|
||||
0x10E3, 0x10B3,
|
||||
0x10E4, 0x10B4,
|
||||
0x10E5, 0x10B5,
|
||||
0x10E6, 0x10B6,
|
||||
0x10E7, 0x10B7,
|
||||
0x10E8, 0x10B8,
|
||||
0x10E9, 0x10B9,
|
||||
0x10EA, 0x10BA,
|
||||
0x10EB, 0x10BB,
|
||||
0x10EC, 0x10BC,
|
||||
0x10ED, 0x10BD,
|
||||
0x10EE, 0x10BE,
|
||||
0x10EF, 0x10BF,
|
||||
0x10F0, 0x10C0,
|
||||
0x10F1, 0x10C1,
|
||||
0x10F2, 0x10C2,
|
||||
0x10F3, 0x10C3,
|
||||
0x10F4, 0x10C4,
|
||||
0x10F5, 0x10C5,
|
||||
0x1E01, 0x1E00,
|
||||
0x1E03, 0x1E02,
|
||||
0x1E05, 0x1E04,
|
||||
0x1E07, 0x1E06,
|
||||
0x1E09, 0x1E08,
|
||||
0x1E0B, 0x1E0A,
|
||||
0x1E0D, 0x1E0C,
|
||||
0x1E0F, 0x1E0E,
|
||||
0x1E11, 0x1E10,
|
||||
0x1E13, 0x1E12,
|
||||
0x1E15, 0x1E14,
|
||||
0x1E17, 0x1E16,
|
||||
0x1E19, 0x1E18,
|
||||
0x1E1B, 0x1E1A,
|
||||
0x1E1D, 0x1E1C,
|
||||
0x1E1F, 0x1E1E,
|
||||
0x1E21, 0x1E20,
|
||||
0x1E23, 0x1E22,
|
||||
0x1E25, 0x1E24,
|
||||
0x1E27, 0x1E26,
|
||||
0x1E29, 0x1E28,
|
||||
0x1E2B, 0x1E2A,
|
||||
0x1E2D, 0x1E2C,
|
||||
0x1E2F, 0x1E2E,
|
||||
0x1E31, 0x1E30,
|
||||
0x1E33, 0x1E32,
|
||||
0x1E35, 0x1E34,
|
||||
0x1E37, 0x1E36,
|
||||
0x1E39, 0x1E38,
|
||||
0x1E3B, 0x1E3A,
|
||||
0x1E3D, 0x1E3C,
|
||||
0x1E3F, 0x1E3E,
|
||||
0x1E41, 0x1E40,
|
||||
0x1E43, 0x1E42,
|
||||
0x1E45, 0x1E44,
|
||||
0x1E47, 0x1E46,
|
||||
0x1E49, 0x1E48,
|
||||
0x1E4B, 0x1E4A,
|
||||
0x1E4D, 0x1E4C,
|
||||
0x1E4F, 0x1E4E,
|
||||
0x1E51, 0x1E50,
|
||||
0x1E53, 0x1E52,
|
||||
0x1E55, 0x1E54,
|
||||
0x1E57, 0x1E56,
|
||||
0x1E59, 0x1E58,
|
||||
0x1E5B, 0x1E5A,
|
||||
0x1E5D, 0x1E5C,
|
||||
0x1E5F, 0x1E5E,
|
||||
0x1E61, 0x1E60,
|
||||
0x1E63, 0x1E62,
|
||||
0x1E65, 0x1E64,
|
||||
0x1E67, 0x1E66,
|
||||
0x1E69, 0x1E68,
|
||||
0x1E6B, 0x1E6A,
|
||||
0x1E6D, 0x1E6C,
|
||||
0x1E6F, 0x1E6E,
|
||||
0x1E71, 0x1E70,
|
||||
0x1E73, 0x1E72,
|
||||
0x1E75, 0x1E74,
|
||||
0x1E77, 0x1E76,
|
||||
0x1E79, 0x1E78,
|
||||
0x1E7B, 0x1E7A,
|
||||
0x1E7D, 0x1E7C,
|
||||
0x1E7F, 0x1E7E,
|
||||
0x1E81, 0x1E80,
|
||||
0x1E83, 0x1E82,
|
||||
0x1E85, 0x1E84,
|
||||
0x1E87, 0x1E86,
|
||||
0x1E89, 0x1E88,
|
||||
0x1E8B, 0x1E8A,
|
||||
0x1E8D, 0x1E8C,
|
||||
0x1E8F, 0x1E8E,
|
||||
0x1E91, 0x1E90,
|
||||
0x1E93, 0x1E92,
|
||||
0x1E95, 0x1E94,
|
||||
0x1EA1, 0x1EA0,
|
||||
0x1EA3, 0x1EA2,
|
||||
0x1EA5, 0x1EA4,
|
||||
0x1EA7, 0x1EA6,
|
||||
0x1EA9, 0x1EA8,
|
||||
0x1EAB, 0x1EAA,
|
||||
0x1EAD, 0x1EAC,
|
||||
0x1EAF, 0x1EAE,
|
||||
0x1EB1, 0x1EB0,
|
||||
0x1EB3, 0x1EB2,
|
||||
0x1EB5, 0x1EB4,
|
||||
0x1EB7, 0x1EB6,
|
||||
0x1EB9, 0x1EB8,
|
||||
0x1EBB, 0x1EBA,
|
||||
0x1EBD, 0x1EBC,
|
||||
0x1EBF, 0x1EBE,
|
||||
0x1EC1, 0x1EC0,
|
||||
0x1EC3, 0x1EC2,
|
||||
0x1EC5, 0x1EC4,
|
||||
0x1EC7, 0x1EC6,
|
||||
0x1EC9, 0x1EC8,
|
||||
0x1ECB, 0x1ECA,
|
||||
0x1ECD, 0x1ECC,
|
||||
0x1ECF, 0x1ECE,
|
||||
0x1ED1, 0x1ED0,
|
||||
0x1ED3, 0x1ED2,
|
||||
0x1ED5, 0x1ED4,
|
||||
0x1ED7, 0x1ED6,
|
||||
0x1ED9, 0x1ED8,
|
||||
0x1EDB, 0x1EDA,
|
||||
0x1EDD, 0x1EDC,
|
||||
0x1EDF, 0x1EDE,
|
||||
0x1EE1, 0x1EE0,
|
||||
0x1EE3, 0x1EE2,
|
||||
0x1EE5, 0x1EE4,
|
||||
0x1EE7, 0x1EE6,
|
||||
0x1EE9, 0x1EE8,
|
||||
0x1EEB, 0x1EEA,
|
||||
0x1EED, 0x1EEC,
|
||||
0x1EEF, 0x1EEE,
|
||||
0x1EF1, 0x1EF0,
|
||||
0x1EF3, 0x1EF2,
|
||||
0x1EF5, 0x1EF4,
|
||||
0x1EF7, 0x1EF6,
|
||||
0x1EF9, 0x1EF8,
|
||||
0x1F00, 0x1F08,
|
||||
0x1F01, 0x1F09,
|
||||
0x1F02, 0x1F0A,
|
||||
0x1F03, 0x1F0B,
|
||||
0x1F04, 0x1F0C,
|
||||
0x1F05, 0x1F0D,
|
||||
0x1F06, 0x1F0E,
|
||||
0x1F07, 0x1F0F,
|
||||
0x1F10, 0x1F18,
|
||||
0x1F11, 0x1F19,
|
||||
0x1F12, 0x1F1A,
|
||||
0x1F13, 0x1F1B,
|
||||
0x1F14, 0x1F1C,
|
||||
0x1F15, 0x1F1D,
|
||||
0x1F20, 0x1F28,
|
||||
0x1F21, 0x1F29,
|
||||
0x1F22, 0x1F2A,
|
||||
0x1F23, 0x1F2B,
|
||||
0x1F24, 0x1F2C,
|
||||
0x1F25, 0x1F2D,
|
||||
0x1F26, 0x1F2E,
|
||||
0x1F27, 0x1F2F,
|
||||
0x1F30, 0x1F38,
|
||||
0x1F31, 0x1F39,
|
||||
0x1F32, 0x1F3A,
|
||||
0x1F33, 0x1F3B,
|
||||
0x1F34, 0x1F3C,
|
||||
0x1F35, 0x1F3D,
|
||||
0x1F36, 0x1F3E,
|
||||
0x1F37, 0x1F3F,
|
||||
0x1F40, 0x1F48,
|
||||
0x1F41, 0x1F49,
|
||||
0x1F42, 0x1F4A,
|
||||
0x1F43, 0x1F4B,
|
||||
0x1F44, 0x1F4C,
|
||||
0x1F45, 0x1F4D,
|
||||
0x1F51, 0x1F59,
|
||||
0x1F53, 0x1F5B,
|
||||
0x1F55, 0x1F5D,
|
||||
0x1F57, 0x1F5F,
|
||||
0x1F60, 0x1F68,
|
||||
0x1F61, 0x1F69,
|
||||
0x1F62, 0x1F6A,
|
||||
0x1F63, 0x1F6B,
|
||||
0x1F64, 0x1F6C,
|
||||
0x1F65, 0x1F6D,
|
||||
0x1F66, 0x1F6E,
|
||||
0x1F67, 0x1F6F,
|
||||
0x1F80, 0x1F88,
|
||||
0x1F81, 0x1F89,
|
||||
0x1F82, 0x1F8A,
|
||||
0x1F83, 0x1F8B,
|
||||
0x1F84, 0x1F8C,
|
||||
0x1F85, 0x1F8D,
|
||||
0x1F86, 0x1F8E,
|
||||
0x1F87, 0x1F8F,
|
||||
0x1F90, 0x1F98,
|
||||
0x1F91, 0x1F99,
|
||||
0x1F92, 0x1F9A,
|
||||
0x1F93, 0x1F9B,
|
||||
0x1F94, 0x1F9C,
|
||||
0x1F95, 0x1F9D,
|
||||
0x1F96, 0x1F9E,
|
||||
0x1F97, 0x1F9F,
|
||||
0x1FA0, 0x1FA8,
|
||||
0x1FA1, 0x1FA9,
|
||||
0x1FA2, 0x1FAA,
|
||||
0x1FA3, 0x1FAB,
|
||||
0x1FA4, 0x1FAC,
|
||||
0x1FA5, 0x1FAD,
|
||||
0x1FA6, 0x1FAE,
|
||||
0x1FA7, 0x1FAF,
|
||||
0x1FB0, 0x1FB8,
|
||||
0x1FB1, 0x1FB9,
|
||||
0x1FD0, 0x1FD8,
|
||||
0x1FD1, 0x1FD9,
|
||||
0x1FE0, 0x1FE8,
|
||||
0x1FE1, 0x1FE9,
|
||||
0x24D0, 0x24B6,
|
||||
0x24D1, 0x24B7,
|
||||
0x24D2, 0x24B8,
|
||||
0x24D3, 0x24B9,
|
||||
0x24D4, 0x24BA,
|
||||
0x24D5, 0x24BB,
|
||||
0x24D6, 0x24BC,
|
||||
0x24D7, 0x24BD,
|
||||
0x24D8, 0x24BE,
|
||||
0x24D9, 0x24BF,
|
||||
0x24DA, 0x24C0,
|
||||
0x24DB, 0x24C1,
|
||||
0x24DC, 0x24C2,
|
||||
0x24DD, 0x24C3,
|
||||
0x24DE, 0x24C4,
|
||||
0x24DF, 0x24C5,
|
||||
0x24E0, 0x24C6,
|
||||
0x24E1, 0x24C7,
|
||||
0x24E2, 0x24C8,
|
||||
0x24E3, 0x24C9,
|
||||
0x24E4, 0x24CA,
|
||||
0x24E5, 0x24CB,
|
||||
0x24E6, 0x24CC,
|
||||
0x24E7, 0x24CD,
|
||||
0x24E8, 0x24CE,
|
||||
0x24E9, 0x24CF,
|
||||
0xFF41, 0xFF21,
|
||||
0xFF42, 0xFF22,
|
||||
0xFF43, 0xFF23,
|
||||
0xFF44, 0xFF24,
|
||||
0xFF45, 0xFF25,
|
||||
0xFF46, 0xFF26,
|
||||
0xFF47, 0xFF27,
|
||||
0xFF48, 0xFF28,
|
||||
0xFF49, 0xFF29,
|
||||
0xFF4A, 0xFF2A,
|
||||
0xFF4B, 0xFF2B,
|
||||
0xFF4C, 0xFF2C,
|
||||
0xFF4D, 0xFF2D,
|
||||
0xFF4E, 0xFF2E,
|
||||
0xFF4F, 0xFF2F,
|
||||
0xFF50, 0xFF30,
|
||||
0xFF51, 0xFF31,
|
||||
0xFF52, 0xFF32,
|
||||
0xFF53, 0xFF33,
|
||||
0xFF54, 0xFF34,
|
||||
0xFF55, 0xFF35,
|
||||
0xFF56, 0xFF36,
|
||||
0xFF57, 0xFF37,
|
||||
0xFF58, 0xFF38,
|
||||
0xFF59, 0xFF39,
|
||||
0xFF5A, 0xFF3A
|
||||
};
|
||||
|
||||
const unsigned NMAX = FB_NELEM(table) / 2;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
unsigned short unicodeUpper(unsigned short c)
|
||||
{
|
||||
unsigned highBound = NMAX, lowBound = 0;
|
||||
|
||||
while (highBound > lowBound)
|
||||
{
|
||||
const unsigned temp = (highBound + lowBound) >> 1;
|
||||
|
||||
if (table[temp << 1] < c)
|
||||
lowBound = temp + 1;
|
||||
else
|
||||
highBound = temp;
|
||||
}
|
||||
|
||||
if (lowBound != NMAX && table[lowBound << 1] == c)
|
||||
return table[(lowBound << 1) + 1];
|
||||
|
||||
return c;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: Firebird generic routine
|
||||
* MODULE: unicodeUpper.h
|
||||
* DESCRIPTION: Converts unicode character to uppercase.
|
||||
*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Alex Peshkov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2015 Alex Peshkov <peshkoff at mail.ru>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
unsigned short unicodeUpper(unsigned short c);
|
@ -38,6 +38,7 @@
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "../common/gdsassert.h"
|
||||
#include "../common/utils_proto.h"
|
||||
@ -1604,4 +1605,34 @@ const ISC_STATUS* const origen = v;
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* dpbItemUpper(const char* s, FB_SIZE_T l, Firebird::string& buf)
|
||||
{
|
||||
if (l && (s[0] == '"' || s[0] == '\''))
|
||||
{
|
||||
const char end_quote = s[0];
|
||||
// quoted string - strip quotes
|
||||
for (FB_SIZE_T i = 1; i < l; ++i)
|
||||
{
|
||||
if (s[i] == end_quote)
|
||||
{
|
||||
if (++i >= l || s[i] != end_quote)
|
||||
break; // delimited quote, done processing
|
||||
// skiped the escape quote, continue processing
|
||||
}
|
||||
buf += s[i];
|
||||
}
|
||||
return buf.c_str();
|
||||
}
|
||||
|
||||
// non-quoted string - try to uppercase
|
||||
for (FB_SIZE_T i = 0; i < l; ++i)
|
||||
{
|
||||
if (!(s[i] & 0x80))
|
||||
buf += toupper(s[i]);
|
||||
else
|
||||
return NULL; // contains non-ascii data
|
||||
}
|
||||
return buf.c_str();
|
||||
}
|
||||
|
||||
} // namespace fb_utils
|
||||
|
@ -190,6 +190,19 @@ namespace fb_utils
|
||||
|
||||
// Check does vector contain particular code or not
|
||||
bool containsErrorCode(const ISC_STATUS* v, ISC_STATUS code);
|
||||
|
||||
// Uppercase/strip string according to login rules
|
||||
const char* dpbItemUpper(const char* s, FB_SIZE_T l, Firebird::string& buf);
|
||||
|
||||
// Uppercase/strip string according to login rules
|
||||
template <typename STR>
|
||||
void dpbItemUpper(STR& name)
|
||||
{
|
||||
Firebird::string buf;
|
||||
const char* up = dpbItemUpper(name.c_str(), name.length(), buf);
|
||||
if (up)
|
||||
name = up;
|
||||
}
|
||||
} // namespace fb_utils
|
||||
|
||||
#endif // INCLUDE_UTILS_PROTO_H
|
||||
|
@ -9473,7 +9473,6 @@ bool CreateFilterNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
|
||||
void CreateFilterNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScratch*/, jrd_tra* transaction)
|
||||
{
|
||||
MetaName ownerName(tdbb->getAttachment()->att_user->usr_user_name);
|
||||
IntlUtil::toUpper(ownerName);
|
||||
|
||||
// run all statements under savepoint control
|
||||
AutoSavePoint savePoint(tdbb, transaction);
|
||||
@ -9697,7 +9696,6 @@ bool CreateRoleNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
|
||||
void CreateRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
|
||||
{
|
||||
MetaName ownerName(tdbb->getAttachment()->att_user->usr_user_name);
|
||||
IntlUtil::toUpper(ownerName);
|
||||
|
||||
// run all statements under savepoint control
|
||||
AutoSavePoint savePoint(tdbb, transaction);
|
||||
@ -10201,7 +10199,6 @@ bool DropRoleNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
|
||||
void DropRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
|
||||
{
|
||||
MetaName user(tdbb->getAttachment()->att_user->usr_user_name);
|
||||
IntlUtil::toUpper(user);
|
||||
|
||||
// run all statements under savepoint control
|
||||
AutoSavePoint savePoint(tdbb, transaction);
|
||||
@ -10261,9 +10258,7 @@ void DropRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jr
|
||||
|
||||
Firebird::MetaName UserNode::upper(const Firebird::MetaName& str)
|
||||
{
|
||||
Firebird::MetaName tmp(str);
|
||||
IntlUtil::toUpper(tmp);
|
||||
return tmp;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
@ -10335,7 +10330,6 @@ void CreateAlterUserNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
|
||||
(Arg::Gds(isc_random) << "Missing user name for ALTER CURRENT USER").raise();
|
||||
|
||||
text = usr->usr_user_name;
|
||||
IntlUtil::toUpper(text);
|
||||
}
|
||||
|
||||
Firebird::LocalStatus s;
|
||||
@ -10655,12 +10649,10 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
else
|
||||
{
|
||||
userType = obj_user;
|
||||
IntlUtil::toUpper(user);
|
||||
}
|
||||
break;
|
||||
|
||||
case obj_user:
|
||||
IntlUtil::toUpper(user);
|
||||
break;
|
||||
|
||||
case obj_sql_role:
|
||||
@ -10704,8 +10696,6 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
if (grantor && !tdbb->getAttachment()->locksmith())
|
||||
status_exception::raise(Arg::PrivateDyn(252) << SYSDBA_USER_NAME);
|
||||
|
||||
IntlUtil::toUpper(grantorRevoker);
|
||||
|
||||
if (!isGrant && !privs) // REVOKE ALL ON ALL
|
||||
{
|
||||
AutoCacheRequest request(tdbb, drq_e_grant3, DYN_REQUESTS);
|
||||
|
@ -68,6 +68,10 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
// Globals
|
||||
GpreGlobals gpreGlob;
|
||||
|
||||
@ -247,6 +251,11 @@ const UCHAR CHR_DBLQUOTE = 64;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#ifdef HAVE_LOCALE_H
|
||||
// Pick up the system locale to allow SYSTEM<->UTF8 conversions
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
gpre_sym* symbol;
|
||||
// CVC: COUNT + 1 because IN_SW_GPRE_INTERP is repeated in gpre_in_sw_table.
|
||||
sw_tab_t sw_table[IN_SW_GPRE_COUNT + 1];
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include "../common/classes/FpeControl.h"
|
||||
#include "../common/os/path_utils.h"
|
||||
#include "../common/StatusHolder.h"
|
||||
#include "../common/Tokens.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
@ -166,7 +167,6 @@ const int MAX_TERMS = 10; // max # of terms in an interactive cmd
|
||||
const char* ISQL_COUNTERS_SET = "CurrentMemory, MaxMemory, RealTime, UserTime, Buffers, Reads, Writes, Fetches";
|
||||
const int ISQL_COUNTERS = 8;
|
||||
|
||||
|
||||
namespace IcuUtil
|
||||
{
|
||||
// Duplicate from ICU to not need to link ISQL with it. It's used by U8_NEXT_UNSAFE.
|
||||
@ -342,8 +342,6 @@ static bool check_time(const tm& times);
|
||||
static bool check_timestamp(const tm& times, const int msec);
|
||||
static size_t chop_at(char target[], const size_t size);
|
||||
static void col_check(const TEXT*, unsigned*);
|
||||
static void copy_str(Firebird::string&, const TEXT**, bool*, const TEXT* const,
|
||||
const TEXT* const, literal_string_type);
|
||||
static processing_state copy_table(TEXT*, TEXT*, TEXT*);
|
||||
static processing_state create_db(const TEXT*, TEXT*);
|
||||
static void do_isql();
|
||||
@ -362,8 +360,6 @@ static processing_state get_dialect(const char* const dialect_str,
|
||||
char* const bad_dialect_buf, bool& bad_dialect);
|
||||
static processing_state get_statement(TEXT* const, const size_t, const TEXT*);
|
||||
static bool get_numeric(const UCHAR*, USHORT, SSHORT*, SINT64*);
|
||||
static void get_str(const TEXT* const, const TEXT**, const TEXT**,
|
||||
literal_string_type*);
|
||||
static void print_set(const char* str, bool v);
|
||||
static processing_state print_sets();
|
||||
static processing_state help(const TEXT*);
|
||||
@ -3464,106 +3460,6 @@ static void col_check(const TEXT* tabname, unsigned* colnumber)
|
||||
}
|
||||
|
||||
|
||||
static void copy_str(Firebird::string& output_str,
|
||||
const TEXT** input_str,
|
||||
bool* done,
|
||||
const TEXT* const str_begin,
|
||||
const TEXT* const str_end,
|
||||
literal_string_type str_flag)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* c o p y _ s t r
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
*
|
||||
* Copy and/or modify the data in the input buffer and stores it
|
||||
* into output buffer.
|
||||
*
|
||||
* For SINGLE_QUOTED_STRING, copy everything from the begining of the
|
||||
* the input buffer to the end of the string constant
|
||||
*
|
||||
* For DOUBLE_QUOTED_STRING, copy everything from the begining of the
|
||||
* the input buffer to the begining of the string constant
|
||||
*
|
||||
* a. replace double quote string delimited character with single
|
||||
* quote
|
||||
* b. if '""' is found with in the string constant, removes one
|
||||
* extra double quote
|
||||
* c. if a single quote is found with in the string constant,
|
||||
* adds one more single quote
|
||||
* d. replace ending double quote string delimited character with
|
||||
* single quote
|
||||
*
|
||||
* For NO_MORE_STRING, copy everything from the begining of the
|
||||
* the input buffer to the end of input buffer
|
||||
*
|
||||
* Input Arguments:
|
||||
*
|
||||
* 1. address of the output buffer
|
||||
* 2. address of the input buffer
|
||||
* 3. address of the end of processing flag
|
||||
*
|
||||
* Output Arguments:
|
||||
*
|
||||
* 1. pointer to begining of the string constant
|
||||
* 2. pointer to ending of the string constant
|
||||
* 3. string type
|
||||
*
|
||||
**************************************/
|
||||
int slen = 0;
|
||||
const TEXT* b1;
|
||||
|
||||
const TEXT* temp_local_stmt_str = *input_str;
|
||||
|
||||
switch (str_flag)
|
||||
{
|
||||
case SINGLE_QUOTED_STRING:
|
||||
slen = str_end - temp_local_stmt_str;
|
||||
output_str.append(temp_local_stmt_str, slen);
|
||||
*input_str = str_end;
|
||||
break;
|
||||
case DOUBLE_QUOTED_STRING:
|
||||
slen = str_begin - temp_local_stmt_str;
|
||||
output_str.append(temp_local_stmt_str, slen);
|
||||
output_str += SINGLE_QUOTE;
|
||||
b1 = str_begin + 1;
|
||||
while (b1 < str_end)
|
||||
{
|
||||
output_str += *b1;
|
||||
switch (*b1)
|
||||
{
|
||||
case SINGLE_QUOTE:
|
||||
output_str += SINGLE_QUOTE;
|
||||
break;
|
||||
case DBL_QUOTE:
|
||||
b1++;
|
||||
if (*b1 != DBL_QUOTE)
|
||||
{
|
||||
output_str[output_str.length() - 1] = SINGLE_QUOTE;
|
||||
b1--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
b1++;
|
||||
}
|
||||
*input_str = b1;
|
||||
break;
|
||||
case NO_MORE_STRING:
|
||||
output_str += temp_local_stmt_str;
|
||||
*done = true;
|
||||
*input_str = temp_local_stmt_str + strlen(temp_local_stmt_str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static processing_state copy_table(TEXT* source,
|
||||
TEXT* destination,
|
||||
TEXT* otherdb)
|
||||
@ -3674,13 +3570,17 @@ static processing_state copy_table(TEXT* source,
|
||||
}
|
||||
|
||||
|
||||
static void appendClause(Firebird::string& to, const char* label, const TEXT* value)
|
||||
static void appendClause(Firebird::string& to, const char* label, const TEXT* value, char quote = 0)
|
||||
{
|
||||
to += ' ';
|
||||
to += label;
|
||||
to += " \'";
|
||||
to += ' ';
|
||||
if (quote)
|
||||
to += quote;
|
||||
to += value;
|
||||
to += "\' ";
|
||||
if (quote)
|
||||
to += quote;
|
||||
to += ' ';
|
||||
}
|
||||
|
||||
|
||||
@ -3708,6 +3608,48 @@ static processing_state create_db(const TEXT* statement, TEXT* d_name)
|
||||
// Disconnect from the database and cleanup
|
||||
ISQL_disconnect_database(false);
|
||||
|
||||
// Parse statement to tokens
|
||||
const char* quotes = isqlGlob.SQL_dialect == 1 ? "\"'" : "'";
|
||||
Firebird::string nlStatement(statement);
|
||||
nlStatement += '\n';
|
||||
Firebird::Tokens toks(0, nlStatement.c_str(), Firebird::sqlSpaces, quotes, Firebird::sqlComments);
|
||||
|
||||
const unsigned KEY_USER = 0;
|
||||
const unsigned KEY_PASS = 1;
|
||||
const unsigned KEY_ROLE = 2;
|
||||
const unsigned KEY_NAMES = 3;
|
||||
const unsigned KEY_SET = 4;
|
||||
|
||||
struct Key {
|
||||
const char* text;
|
||||
bool has;
|
||||
};
|
||||
Key keys[5] = {
|
||||
{ "USER", false },
|
||||
{ "PASSWORD", false },
|
||||
{ "ROLE", false },
|
||||
{ "NAMES", false },
|
||||
{ "SET", false }
|
||||
};
|
||||
|
||||
for (unsigned t = 0; t < toks.getCount(); ++t)
|
||||
{
|
||||
Firebird::NoCaseString token(toks[t].text, toks[t].length);
|
||||
unsigned k;
|
||||
for (k = 0; k < FB_NELEM(keys); ++k)
|
||||
{
|
||||
if (token == keys[k].text)
|
||||
{
|
||||
if (k != KEY_NAMES || keys[KEY_SET].has)
|
||||
keys[k].has = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (k != KEY_SET)
|
||||
keys[KEY_SET].has = false;
|
||||
}
|
||||
|
||||
for (int createWithoutRole = 0; createWithoutRole < 2; ++createWithoutRole)
|
||||
{
|
||||
ret = SKIP;
|
||||
@ -3715,117 +3657,38 @@ static processing_state create_db(const TEXT* statement, TEXT* d_name)
|
||||
TEXT psw[PASSWORD_LENGTH];
|
||||
TEXT role[ROLE_LENGTH];
|
||||
|
||||
Firebird::string local_statement(statement);
|
||||
Firebird::string modifiedCreateStatement(statement);
|
||||
|
||||
TEXT quote = DBL_QUOTE;
|
||||
const TEXT* p = NULL;
|
||||
|
||||
// If there is a user parameter, we will set it into the create stmt.
|
||||
if (global_usr || global_psw ||
|
||||
// If there is a global parameter, we will set it into the create stmt.
|
||||
if (global_usr || global_role || global_psw ||
|
||||
(*setValues.ISQL_charset && strcmp(setValues.ISQL_charset, DEFCHARSET)))
|
||||
{
|
||||
strip_quotes(isqlGlob.User, usr);
|
||||
strcpy(usr, isqlGlob.User);
|
||||
strip_quotes(Password, psw);
|
||||
strip_quotes(isqlGlob.Role, role);
|
||||
// Look for the quotes on the database name and find the close quotes.
|
||||
// Use '"' first, if not successful try '''.
|
||||
// CVC: Again, this is wrong with embedded quotes.
|
||||
// Maybe IUTILS_remove_and_unescape_quotes coupled with IUTILS_copy_SQL_id could work.
|
||||
const TEXT* q = strchr(statement, quote);
|
||||
if (!q)
|
||||
strcpy(role, isqlGlob.Role);
|
||||
|
||||
Firebird::string clauses;
|
||||
if (global_usr && !keys[KEY_USER].has)
|
||||
appendClause(clauses, keys[KEY_USER].text, usr);
|
||||
if (global_psw && !keys[KEY_PASS].has)
|
||||
appendClause(clauses, keys[KEY_PASS].text, psw, SINGLE_QUOTE);
|
||||
if (global_role && (!keys[KEY_ROLE].has) && createWithoutRole == 0)
|
||||
appendClause(clauses, keys[KEY_ROLE].text, role);
|
||||
if (*setValues.ISQL_charset && strcmp(setValues.ISQL_charset, DEFCHARSET)&& !keys[KEY_NAMES].has)
|
||||
{
|
||||
quote = SINGLE_QUOTE;
|
||||
q = strchr(statement, quote);
|
||||
Firebird::string setNames = keys[KEY_SET].text;
|
||||
setNames += ' ';
|
||||
setNames += keys[KEY_NAMES].text;
|
||||
appendClause(clauses, setNames.c_str(), setValues.ISQL_charset, SINGLE_QUOTE);
|
||||
}
|
||||
|
||||
if (q)
|
||||
{
|
||||
// Set quote to match open quote
|
||||
quote = *q;
|
||||
q++;
|
||||
p = strchr(q, quote);
|
||||
if (p)
|
||||
{
|
||||
p++;
|
||||
const ptrdiff_t slen = p - statement;
|
||||
local_statement.resize(slen);
|
||||
if (isqlGlob.SQL_dialect == 1)
|
||||
{
|
||||
if (global_usr)
|
||||
appendClause(local_statement, "USER", usr);
|
||||
if (global_psw)
|
||||
appendClause(local_statement, "PASSWORD", psw);
|
||||
if (global_role && createWithoutRole == 0)
|
||||
appendClause(local_statement, "ROLE", role);
|
||||
if (*setValues.ISQL_charset && strcmp(setValues.ISQL_charset, DEFCHARSET))
|
||||
appendClause(local_statement, "SET NAMES", setValues.ISQL_charset);
|
||||
local_statement += p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SLONG cnt = 0;
|
||||
if ((isqlGlob.SQL_dialect == 0) || (isqlGlob.SQL_dialect > 1))
|
||||
{
|
||||
const TEXT* q = strchr(statement, SINGLE_QUOTE);
|
||||
while (q)
|
||||
{
|
||||
cnt++;
|
||||
const TEXT* l = q + 1;
|
||||
q = strchr(l, SINGLE_QUOTE);
|
||||
}
|
||||
|
||||
Firebird::string new_local_statement;
|
||||
TEXT errbuf[MSG_LENGTH];
|
||||
|
||||
const TEXT* temp_local_stmt_str = local_statement.c_str();
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
const TEXT* str_begin = NULL;
|
||||
const TEXT* str_end = NULL;
|
||||
literal_string_type str_flag = INIT_STR_FLAG;
|
||||
get_str(temp_local_stmt_str, &str_begin, &str_end, &str_flag);
|
||||
if (str_flag == INCOMPLETE_STRING)
|
||||
{
|
||||
IUTILS_msg_get(INCOMPLETE_STR, errbuf, SafeArg() << "create database statement");
|
||||
STDERROUT(errbuf);
|
||||
return (FAIL);
|
||||
}
|
||||
copy_str(new_local_statement, &temp_local_stmt_str, &done, str_begin, str_end, str_flag);
|
||||
}
|
||||
|
||||
if (global_usr)
|
||||
appendClause(new_local_statement, "USER", usr);
|
||||
if (global_psw)
|
||||
appendClause(new_local_statement, "PASSWORD", psw);
|
||||
if (global_role && createWithoutRole == 0)
|
||||
appendClause(new_local_statement, "ROLE", role);
|
||||
if (*setValues.ISQL_charset && strcmp(setValues.ISQL_charset, DEFCHARSET))
|
||||
appendClause(new_local_statement, "SET NAMES", setValues.ISQL_charset);
|
||||
|
||||
if (p && strlen(p) > 0)
|
||||
{
|
||||
temp_local_stmt_str = p;
|
||||
bool done2 = false;
|
||||
while (!done2)
|
||||
{
|
||||
const TEXT* str_begin = NULL;
|
||||
const TEXT* str_end = NULL;
|
||||
literal_string_type str_flag = INIT_STR_FLAG;
|
||||
get_str(temp_local_stmt_str, &str_begin, &str_end, &str_flag);
|
||||
if (str_flag == INCOMPLETE_STRING)
|
||||
{
|
||||
IUTILS_msg_get(INCOMPLETE_STR, errbuf, SafeArg() << "create database statement");
|
||||
STDERROUT(errbuf);
|
||||
return (FAIL);
|
||||
}
|
||||
copy_str(new_local_statement, &temp_local_stmt_str, &done2, str_begin, str_end, str_flag);
|
||||
}
|
||||
}
|
||||
|
||||
local_statement = new_local_statement;
|
||||
if (toks.getCount() > 3)
|
||||
modifiedCreateStatement.insert(toks[3].origin, clauses);
|
||||
else
|
||||
modifiedCreateStatement += clauses;
|
||||
}
|
||||
|
||||
// execute the create statement
|
||||
@ -3834,8 +3697,8 @@ static processing_state create_db(const TEXT* statement, TEXT* d_name)
|
||||
unsigned dialect =
|
||||
(isqlGlob.SQL_dialect == 0 || isqlGlob.SQL_dialect == SQL_DIALECT_V6_TRANSITION) ?
|
||||
requested_SQL_dialect : isqlGlob.SQL_dialect;
|
||||
DB = Firebird::UtilInterfacePtr()->executeCreateDatabase(fbStatus, local_statement.length(),
|
||||
local_statement.c_str(), dialect, NULL);
|
||||
DB = Firebird::UtilInterfacePtr()->executeCreateDatabase(fbStatus, modifiedCreateStatement.length(),
|
||||
modifiedCreateStatement.c_str(), dialect, NULL);
|
||||
|
||||
if ((!DB) && (createWithoutRole == 0) && (fbStatus->getErrors()[1] == isc_dsql_error))
|
||||
{
|
||||
@ -3863,109 +3726,12 @@ static processing_state create_db(const TEXT* statement, TEXT* d_name)
|
||||
// CVC: Someone may decide to play strange games with undocumented ability
|
||||
// to write crap between CREATE DATABASE and the db name, as described by
|
||||
// Helen on CORE-932. Let's see if we can discover the real db name.
|
||||
size_t db_name_len = MAXPATHLEN - 1;
|
||||
char temp_name[MAXPATHLEN];
|
||||
if (!strncmp(d_name, "/*", 2) || !strncmp(d_name, "--", 2))
|
||||
{
|
||||
const char* target = d_name[0] == '/' ? "/*" : "--";
|
||||
const char* comment = strstr(statement, target);
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
if (target[0] == '/')
|
||||
{
|
||||
// We don't accept recursive comment blocks, so looking for the next *./ is safe.
|
||||
comment = strstr(comment + 2, "*/");
|
||||
// What happens if the comment is not closed or quotes are spoiling the party?
|
||||
// Then the statement is ill-formed and will be rejected by the server anyway.
|
||||
if (comment)
|
||||
{
|
||||
comment += 2;
|
||||
while (*comment && fb_isspace(*comment))
|
||||
++comment;
|
||||
}
|
||||
else
|
||||
break; // no end of block comment, error, do nothing.
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!strncmp(comment, "--", 2))
|
||||
{
|
||||
while (*comment && *comment != '\n')
|
||||
++comment;
|
||||
|
||||
if (*comment == '\n')
|
||||
++comment; // skip the newline
|
||||
|
||||
while (*comment && fb_isspace(*comment))
|
||||
++comment;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!strncmp(comment, "/*", 2))
|
||||
{
|
||||
target = "/*";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strncmp(comment, "--", 2))
|
||||
{
|
||||
target = "--";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Does the advanced user want a charset specification before the name, too?
|
||||
// AFAIK, supported by IB and FB but dsql/preparse.cpp doesn't understand it.
|
||||
/*
|
||||
if (*comment == '_')
|
||||
{
|
||||
while (*comment && !fb_isspace(*comment) && *comment != '"' && *comment != '\'')
|
||||
++comment;
|
||||
|
||||
while (*comment && fb_isspace(*comment))
|
||||
++comment;
|
||||
|
||||
// Include the "continue" loops here for this to work in all cases.
|
||||
// Check that this happens only once, etc.
|
||||
}
|
||||
*/
|
||||
|
||||
if (*comment == '"' || *comment == '\'')
|
||||
{
|
||||
for (const char& newquote = *comment++; *comment; ++comment)
|
||||
{
|
||||
if (*comment != newquote)
|
||||
continue;
|
||||
|
||||
// If we find 'hello ''world''' this is valid.
|
||||
if (comment[1] == newquote)
|
||||
{
|
||||
comment += 2;
|
||||
if (!*comment)
|
||||
break;
|
||||
}
|
||||
|
||||
if (*comment == newquote && comment[1] != newquote)
|
||||
{
|
||||
db_name_len = comment - &newquote + 1;
|
||||
if (db_name_len >= MAXPATHLEN)
|
||||
db_name_len = MAXPATHLEN - 1;
|
||||
|
||||
d_name = temp_name;
|
||||
fb_utils::copy_terminate(d_name, &newquote, db_name_len + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
} // while (true)
|
||||
}
|
||||
|
||||
chop_at(d_name, db_name_len + 1);
|
||||
strip_quotes(d_name, isqlGlob.global_Db_name);
|
||||
Firebird::string s;
|
||||
if (toks.getCount() > 2)
|
||||
s.assign(toks[2].text, toks[2].length);
|
||||
else
|
||||
s = d_name;
|
||||
strip_quotes(s.c_str(), isqlGlob.global_Db_name);
|
||||
|
||||
ISQL_get_version(true);
|
||||
|
||||
@ -5594,104 +5360,6 @@ static processing_state get_statement(TEXT* const statement,
|
||||
}
|
||||
|
||||
|
||||
static void get_str(const TEXT* const input_str,
|
||||
const TEXT** str_begin,
|
||||
const TEXT** str_end,
|
||||
literal_string_type* str_flag)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* g e t _ s t r
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
*
|
||||
* Scanning a string constant from the input buffer. If it found, then
|
||||
* passes back the starting address and ending address of the string
|
||||
* constant. It also marks the type of string constant and passes back.
|
||||
*
|
||||
* string type:
|
||||
*
|
||||
* 1. SINGLE_QUOTED_STRING --- string constant delimited by
|
||||
* single quotes
|
||||
* 2. DOUBLE_QUOTED_STRING --- string constant delimited by
|
||||
* double quotes
|
||||
* 3. NO_MORE_STRING --- no string constant was found
|
||||
*
|
||||
* 4. INCOMPLETE_STRING --- no matching ending quote
|
||||
*
|
||||
* Input Arguments:
|
||||
*
|
||||
* 1. input buffer
|
||||
*
|
||||
* Output Arguments:
|
||||
*
|
||||
* 1. pointer to the input buffer
|
||||
* 2. address to the begining of a string constant
|
||||
* 3. address to the ending of a string constant
|
||||
* 4. address to the string flag
|
||||
*
|
||||
**************************************/
|
||||
const TEXT* b1 = strchr(input_str, SINGLE_QUOTE);
|
||||
const TEXT* b2 = strchr(input_str, DBL_QUOTE);
|
||||
if (!b1 && !b2)
|
||||
*str_flag = NO_MORE_STRING;
|
||||
else
|
||||
{
|
||||
if (b1 && !b2)
|
||||
*str_flag = SINGLE_QUOTED_STRING;
|
||||
else if (!b1 && b2)
|
||||
{
|
||||
*str_flag = DOUBLE_QUOTED_STRING;
|
||||
b1 = b2;
|
||||
}
|
||||
else if (b1 > b2)
|
||||
{
|
||||
*str_flag = DOUBLE_QUOTED_STRING;
|
||||
b1 = b2;
|
||||
}
|
||||
else
|
||||
*str_flag = SINGLE_QUOTED_STRING;
|
||||
|
||||
*str_begin = b1;
|
||||
TEXT delimited_char = *b1;
|
||||
b1++;
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
if (*b1 == delimited_char)
|
||||
{
|
||||
b1++;
|
||||
if (*b1 == delimited_char)
|
||||
b1++;
|
||||
else
|
||||
{
|
||||
done = true;
|
||||
*str_end = b1;
|
||||
}
|
||||
}
|
||||
else
|
||||
b1 = strchr(b1, delimited_char);
|
||||
|
||||
/* In case there is no matching ending quote (single or double)
|
||||
either because of mismatched quotes or simply because user
|
||||
didn't complete the quotes, we cannot find a valid string
|
||||
at all. So we return a special value INCOMPLETE_STRING.
|
||||
In this case str_end is not populated and hence copy_str
|
||||
should not be called after get_str, but instead the caller
|
||||
must process this error & return to it's calling routine
|
||||
- Shailesh */
|
||||
if (b1 == NULL)
|
||||
{
|
||||
*str_flag = INCOMPLETE_STRING;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ISQL_get_version(bool call_by_create_db)
|
||||
{
|
||||
/**************************************
|
||||
@ -6267,32 +5935,19 @@ static processing_state newdb(TEXT* dbname,
|
||||
// Strip quotes if well-intentioned
|
||||
|
||||
strip_quotes(dbname, isqlGlob.global_Db_name);
|
||||
strip_quotes(usr, local_usr);
|
||||
if (usr)
|
||||
strcpy(local_usr, usr);
|
||||
strip_quotes(psw, local_psw);
|
||||
|
||||
// if local user is not specified, see if global options are
|
||||
// specified - don't let a global role setting carry forward if a
|
||||
// specific local user was specified
|
||||
//
|
||||
// Special handling for SQL Roles:
|
||||
// V5 client -- strip the quotes
|
||||
// V6 client -- pass the role name as it is
|
||||
|
||||
if (sql_role_nm)
|
||||
{
|
||||
if (isqlGlob.SQL_dialect == SQL_DIALECT_V5)
|
||||
strip_quotes(sql_role_nm, local_sql_role);
|
||||
else
|
||||
strcpy(local_sql_role, sql_role_nm);
|
||||
}
|
||||
strcpy(local_sql_role, sql_role_nm);
|
||||
|
||||
if (!(strlen(local_sql_role)) && global_role)
|
||||
{
|
||||
if (isqlGlob.SQL_dialect == SQL_DIALECT_V5)
|
||||
strip_quotes(isqlGlob.Role, local_sql_role);
|
||||
else
|
||||
strcpy(local_sql_role, isqlGlob.Role);
|
||||
}
|
||||
strcpy(local_sql_role, isqlGlob.Role);
|
||||
|
||||
if (!(strlen(local_usr)) && global_usr)
|
||||
strcpy(local_usr, isqlGlob.User);
|
||||
|
@ -58,7 +58,6 @@
|
||||
#include "../jrd/IntlManager.h"
|
||||
#include "../jrd/PreparedStatement.h"
|
||||
#include "../jrd/constants.h"
|
||||
#include "../common/IntlUtil.h"
|
||||
|
||||
using namespace Firebird;
|
||||
using namespace Jrd;
|
||||
@ -226,7 +225,7 @@ static const trigger_msg trigger_messages[] =
|
||||
|
||||
|
||||
|
||||
void INI_format(const MetaName& owner, const MetaName& charset)
|
||||
void INI_format(const char* owner, const char* charset)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -243,15 +242,13 @@ void INI_format(const MetaName& owner, const MetaName& charset)
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||
|
||||
fb_assert(owner.hasData());
|
||||
fb_assert(owner && owner[0]);
|
||||
|
||||
// Uppercase owner name
|
||||
MetaName ownerName(owner);
|
||||
IntlUtil::toUpper(ownerName);
|
||||
|
||||
// Uppercase charset name
|
||||
MetaName rdbCharSetName(charset.hasData() ? charset.c_str() : DEFAULT_DB_CHARACTER_SET_NAME);
|
||||
IntlUtil::toUpper(rdbCharSetName);
|
||||
MetaName rdbCharSetName(charset && charset[0] ? charset : DEFAULT_DB_CHARACTER_SET_NAME);
|
||||
|
||||
const int* fld;
|
||||
|
||||
|
@ -29,7 +29,7 @@ namespace Jrd {
|
||||
class dsql_dbb;
|
||||
}
|
||||
|
||||
void INI_format(const Firebird::MetaName&, const Firebird::MetaName&);
|
||||
void INI_format(const char*, const char*);
|
||||
USHORT INI_get_trig_flags(const TEXT*);
|
||||
void INI_init(Jrd::thread_db*);
|
||||
void INI_init2(Jrd::thread_db*);
|
||||
|
@ -1022,7 +1022,6 @@ static void start_transaction(thread_db* tdbb, bool transliterate, jrd_tra** tr
|
||||
Jrd::Attachment* attachment, unsigned int tpb_length, const UCHAR* tpb);
|
||||
static void release_attachment(thread_db*, Jrd::Attachment*);
|
||||
static void rollback(thread_db*, jrd_tra*, const bool);
|
||||
static void strip_quotes(string&);
|
||||
static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsigned flags = 0);
|
||||
static void getUserInfo(UserId&, const DatabaseOptions&, const char*, const char*,
|
||||
const RefPtr<Config>*, bool, ICryptKeyCallback*);
|
||||
@ -1297,38 +1296,15 @@ void JRD_make_role_name(string& userIdRole, const int dialect)
|
||||
switch (dialect)
|
||||
{
|
||||
case SQL_DIALECT_V5:
|
||||
strip_quotes(userIdRole);
|
||||
IntlUtil::toUpper(userIdRole);
|
||||
// Invoke utility twice: first to strip quotes, next to uppercase if needed
|
||||
// For unquoted string nothing bad happens
|
||||
fb_utils::dpbItemUpper(userIdRole);
|
||||
fb_utils::dpbItemUpper(userIdRole);
|
||||
break;
|
||||
|
||||
case SQL_DIALECT_V6_TRANSITION:
|
||||
case SQL_DIALECT_V6:
|
||||
if (userIdRole.hasData() && (userIdRole[0] == DBL_QUOTE || userIdRole[0] == SINGLE_QUOTE))
|
||||
{
|
||||
const char end_quote = userIdRole[0];
|
||||
// remove the delimited quotes and escape quote
|
||||
// from ROLE name
|
||||
userIdRole.erase(0, 1);
|
||||
for (string::iterator p = userIdRole.begin(); p < userIdRole.end(); ++p)
|
||||
{
|
||||
if (*p == end_quote)
|
||||
{
|
||||
if (++p < userIdRole.end() && *p == end_quote)
|
||||
{
|
||||
// skip the escape quote here
|
||||
userIdRole.erase(p--);
|
||||
}
|
||||
else
|
||||
{
|
||||
// delimited done
|
||||
userIdRole.erase(--p, userIdRole.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
IntlUtil::toUpper(userIdRole);
|
||||
|
||||
fb_utils::dpbItemUpper(userIdRole);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2694,7 +2670,9 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
|
||||
if (options.dpb_set_no_reserve)
|
||||
PAG_set_no_reserve(tdbb, options.dpb_no_reserve);
|
||||
|
||||
INI_format(attachment->att_user->usr_user_name.c_str(), options.dpb_set_db_charset.c_str());
|
||||
string dpb_set_db_charset(options.dpb_set_db_charset);
|
||||
fb_utils::dpbItemUpper(dpb_set_db_charset);
|
||||
INI_format(attachment->att_user->usr_user_name.c_str(), dpb_set_db_charset.c_str());
|
||||
|
||||
// If we have not allocated first TIP page, do it now.
|
||||
if (!dbb->dbb_t_pages || !dbb->dbb_t_pages->count())
|
||||
@ -5636,6 +5614,7 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
|
||||
dpb_overwrite = false;
|
||||
dpb_sql_dialect = 99;
|
||||
invalid_client_SQL_dialect = false;
|
||||
dpb_utf8_filename = false;
|
||||
|
||||
if (dpb_length == 0)
|
||||
{
|
||||
@ -5649,12 +5628,14 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
|
||||
ClumpletReader rdr(ClumpletReader::dpbList, dpb, dpb_length, dpbErrorRaise);
|
||||
dumpAuthBlock("DatabaseOptions::get()", &rdr, isc_dpb_auth_block);
|
||||
|
||||
dpb_utf8_filename = rdr.find(isc_dpb_utf8_filename);
|
||||
|
||||
for (rdr.rewind(); !rdr.isEof(); rdr.moveNext())
|
||||
{
|
||||
switch (rdr.getClumpTag())
|
||||
{
|
||||
case isc_dpb_utf8_filename:
|
||||
dpb_utf8_filename = true;
|
||||
break;
|
||||
|
||||
case isc_dpb_working_directory:
|
||||
getPath(rdr, dpb_working_directory);
|
||||
break;
|
||||
@ -6648,39 +6629,6 @@ bool JRD_shutdown_database(Database* dbb, const unsigned flags)
|
||||
}
|
||||
|
||||
|
||||
static void strip_quotes(string& out)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* s t r i p _ q u o t e s
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Get rid of quotes around strings
|
||||
* Quotes in the middle will confuse this routine!
|
||||
*
|
||||
**************************************/
|
||||
if (out.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (out[0] == DBL_QUOTE || out[0] == SINGLE_QUOTE)
|
||||
{
|
||||
// Skip any initial quote
|
||||
const char quote = out[0];
|
||||
out.erase(0, 1);
|
||||
// Search for same quote
|
||||
FB_SIZE_T pos = out.find(quote);
|
||||
if (pos != string::npos)
|
||||
{
|
||||
out.erase(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void JRD_enum_attachments(PathNameList* dbList, ULONG& atts, ULONG& dbs, ULONG& svcs)
|
||||
{
|
||||
/**************************************
|
||||
@ -7147,6 +7095,7 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options,
|
||||
|
||||
if (fb_utils::bootBuild())
|
||||
{
|
||||
auth_method = "bootBuild";
|
||||
wheel = true;
|
||||
}
|
||||
else
|
||||
@ -7155,17 +7104,17 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options,
|
||||
if (options.dpb_trusted_login.hasData())
|
||||
{
|
||||
name = options.dpb_trusted_login;
|
||||
fb_utils::dpbItemUpper(name);
|
||||
}
|
||||
else if (options.dpb_user_name.hasData())
|
||||
{
|
||||
name = options.dpb_user_name;
|
||||
fb_utils::dpbItemUpper(name);
|
||||
}
|
||||
else if (options.dpb_auth_block.hasData())
|
||||
{
|
||||
mapUser(name, trusted_role, &auth_method, &user.usr_auth_block, options.dpb_auth_block,
|
||||
aliasName, dbName, (config ? (*config)->getSecurityDatabase() : NULL), cryptCb);
|
||||
ISC_systemToUtf8(name);
|
||||
ISC_systemToUtf8(trusted_role);
|
||||
|
||||
if (creating && config) // when config is NULL we are in error handler
|
||||
{
|
||||
@ -7185,8 +7134,6 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options,
|
||||
}
|
||||
}
|
||||
|
||||
IntlUtil::toUpper(name);
|
||||
|
||||
// if the name from the user database is defined as SYSDBA,
|
||||
// we define that user id as having system privileges
|
||||
|
||||
|
@ -56,7 +56,6 @@
|
||||
#include "../common/config/config.h"
|
||||
#include "../common/os/os_utils.h"
|
||||
#include "../common/classes/ClumpletWriter.h"
|
||||
#include "../common/IntlUtil.h"
|
||||
|
||||
|
||||
const int UIC_BASE = 10;
|
||||
@ -1008,7 +1007,6 @@ bool SCL_role_granted(thread_db* tdbb, const UserId& usr, const TEXT* sql_role)
|
||||
}
|
||||
|
||||
Firebird::string loginName(usr.usr_user_name);
|
||||
IntlUtil::toUpper(loginName);
|
||||
const TEXT* login_name = loginName.c_str();
|
||||
|
||||
bool found = false;
|
||||
@ -1100,7 +1098,6 @@ void SCL_init(thread_db* tdbb, bool create, const UserId& tempId)
|
||||
if (!create)
|
||||
{
|
||||
Firebird::string loginName(tempId.usr_user_name);
|
||||
IntlUtil::toUpper(loginName);
|
||||
const TEXT* login_name = loginName.c_str();
|
||||
|
||||
AutoCacheRequest request(tdbb, irq_get_role_name, IRQ_REQUESTS);
|
||||
@ -1581,7 +1578,6 @@ static SecurityClass::flags_t walk_acl(thread_db* tdbb,
|
||||
else if (user.usr_sql_role_name != user.usr_trusted_role)
|
||||
{
|
||||
Firebird::string loginName(user.usr_user_name);
|
||||
IntlUtil::toUpper(loginName);
|
||||
const TEXT* login_name = loginName.c_str();
|
||||
bool roleHit = false;
|
||||
AutoCacheRequest request(tdbb, irq_get_role_mem, IRQ_REQUESTS);
|
||||
|
@ -253,7 +253,7 @@ void Service::getOptions(ClumpletReader& spb)
|
||||
{
|
||||
case isc_spb_user_name:
|
||||
spb.getString(svc_username);
|
||||
svc_username.upper();
|
||||
fb_utils::dpbItemUpper(svc_username);
|
||||
break;
|
||||
|
||||
case isc_spb_sql_role_name:
|
||||
@ -686,8 +686,6 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d
|
||||
string trusted_role;
|
||||
mapUser(svc_username, trusted_role, NULL, &svc_auth_block, svc_auth_block,
|
||||
"services manager", NULL, config->getSecurityDatabase(), svc_crypt_callback);
|
||||
|
||||
// to be changed after refsoft special roles patch!!!
|
||||
trusted_role.upper();
|
||||
svc_trusted_role = trusted_role == ADMIN_ROLE;
|
||||
}
|
||||
|
@ -218,65 +218,9 @@ static const UCHAR trigger1[] =
|
||||
blr_leave, 0,
|
||||
blr_end,
|
||||
blr_if,
|
||||
blr_or,
|
||||
blr_eql,
|
||||
blr_field, 1, 13, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R', '_', 'T', 'Y',
|
||||
'P', 'E',
|
||||
blr_literal, blr_long, 0, 0, 0, 0, 0,
|
||||
blr_or,
|
||||
blr_eql,
|
||||
blr_field, 1, 13, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R', '_', 'T', 'Y',
|
||||
'P', 'E',
|
||||
blr_literal, blr_long, 0, 3, 0, 0, 0,
|
||||
blr_or,
|
||||
blr_eql,
|
||||
blr_field, 1, 13, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R', '_', 'T', 'Y',
|
||||
'P', 'E',
|
||||
blr_literal, blr_long, 0, 4, 0, 0, 0,
|
||||
blr_or,
|
||||
blr_eql,
|
||||
blr_field, 1, 13, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R', '_', 'T', 'Y',
|
||||
'P', 'E',
|
||||
blr_literal, blr_long, 0, 6, 0, 0, 0,
|
||||
blr_or,
|
||||
blr_eql,
|
||||
blr_field, 1, 13, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R', '_', 'T', 'Y',
|
||||
'P', 'E',
|
||||
blr_literal, blr_long, 0, 7, 0, 0, 0,
|
||||
blr_or,
|
||||
blr_eql,
|
||||
blr_field, 1, 13, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R', '_', 'T', 'Y',
|
||||
'P', 'E',
|
||||
blr_literal, blr_long, 0, 8, 0, 0, 0,
|
||||
blr_or,
|
||||
blr_eql,
|
||||
blr_field, 1, 13, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R', '_', 'T', 'Y',
|
||||
'P', 'E',
|
||||
blr_literal, blr_long, 0, 9, 0, 0, 0,
|
||||
blr_or,
|
||||
blr_eql,
|
||||
blr_field, 1, 13, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R', '_', 'T', 'Y',
|
||||
'P', 'E',
|
||||
blr_literal, blr_long, 0, 10, 0, 0, 0,
|
||||
blr_or,
|
||||
blr_eql,
|
||||
blr_field, 1, 13, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R', '_', 'T', 'Y',
|
||||
'P', 'E',
|
||||
blr_literal, blr_long, 0, 11, 0, 0, 0,
|
||||
blr_eql,
|
||||
blr_field, 1, 13, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R', '_', 'T', 'Y',
|
||||
'P', 'E',
|
||||
blr_literal, blr_long, 0, 12, 0, 0, 0,
|
||||
blr_assignment,
|
||||
blr_upcase,
|
||||
blr_field, 1, 8, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R',
|
||||
blr_field, 1, 8, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R',
|
||||
blr_end,
|
||||
blr_if,
|
||||
blr_missing,
|
||||
blr_field, 1, 11, 'R', 'D', 'B', '$', 'G', 'R', 'A', 'N', 'T', 'O', 'R',
|
||||
blr_assignment,
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_field, 1, 11, 'R', 'D', 'B', '$', 'G', 'R', 'A', 'N', 'T', 'O', 'R',
|
||||
blr_end,
|
||||
@ -304,7 +248,6 @@ static const UCHAR trigger1[] =
|
||||
blr_eql,
|
||||
blr_field, 6, 14, 'R', 'D', 'B', '$', 'O', 'W', 'N', 'E', 'R', '_', 'N',
|
||||
'A', 'M', 'E',
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_and,
|
||||
blr_eql,
|
||||
@ -317,11 +260,9 @@ static const UCHAR trigger1[] =
|
||||
blr_field, 1, 8, 'R', 'D', 'B', '$', 'U', 'S', 'E', 'R',
|
||||
blr_or,
|
||||
blr_eql,
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_literal, blr_text, 6, 0, 'S', 'Y', 'S', 'D', 'B', 'A',
|
||||
blr_eql,
|
||||
blr_upcase,
|
||||
blr_current_role,
|
||||
blr_literal, blr_text, 9, 0, 'R', 'D', 'B', '$', 'A', 'D', 'M', 'I', 'N',
|
||||
blr_begin,
|
||||
@ -330,7 +271,6 @@ static const UCHAR trigger1[] =
|
||||
blr_neq,
|
||||
blr_field, 6, 14, 'R', 'D', 'B', '$', 'O', 'W', 'N', 'E', 'R', '_', 'N',
|
||||
'A', 'M', 'E',
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_begin,
|
||||
blr_if,
|
||||
@ -444,11 +384,9 @@ static const UCHAR trigger1[] =
|
||||
'A', 'M', 'E',
|
||||
blr_and,
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_literal, blr_text, 6, 0, 'S', 'Y', 'S', 'D', 'B', 'A',
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_current_role,
|
||||
blr_literal, blr_text, 9, 0, 'R', 'D', 'B', '$', 'A', 'D', 'M', 'I', 'N',
|
||||
blr_begin,
|
||||
@ -537,11 +475,9 @@ static const UCHAR trigger1[] =
|
||||
'A', 'M', 'E',
|
||||
blr_and,
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_literal, blr_text, 6, 0, 'S', 'Y', 'S', 'D', 'B', 'A',
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_current_role,
|
||||
blr_literal, blr_text, 9, 0, 'R', 'D', 'B', '$', 'A', 'D', 'M', 'I', 'N',
|
||||
blr_begin,
|
||||
@ -695,15 +631,12 @@ static const UCHAR trigger1[] =
|
||||
blr_neq,
|
||||
blr_field, 18, 14, 'R', 'D', 'B', '$', 'O', 'W', 'N', 'E', 'R', '_', 'N',
|
||||
'A', 'M', 'E',
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_and,
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_literal, blr_text, 6, 0, 'S', 'Y', 'S', 'D', 'B', 'A',
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_current_role,
|
||||
blr_literal, blr_text, 9, 0, 'R', 'D', 'B', '$', 'A', 'D', 'M', 'I', 'N',
|
||||
blr_if,
|
||||
@ -809,15 +742,12 @@ static const UCHAR trigger1[] =
|
||||
blr_neq,
|
||||
blr_field, 26, 14, 'R', 'D', 'B', '$', 'O', 'W', 'N', 'E', 'R', '_', 'N',
|
||||
'A', 'M', 'E',
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_and,
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_literal, blr_text, 6, 0, 'S', 'Y', 'S', 'D', 'B', 'A',
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_current_role,
|
||||
blr_literal, blr_text, 9, 0, 'R', 'D', 'B', '$', 'A', 'D', 'M', 'I', 'N',
|
||||
blr_if,
|
||||
@ -919,15 +849,12 @@ static const UCHAR trigger1[] =
|
||||
blr_neq,
|
||||
blr_field, 22, 14, 'R', 'D', 'B', '$', 'O', 'W', 'N', 'E', 'R', '_', 'N',
|
||||
'A', 'M', 'E',
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_and,
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_literal, blr_text, 6, 0, 'S', 'Y', 'S', 'D', 'B', 'A',
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_current_role,
|
||||
blr_literal, blr_text, 9, 0, 'R', 'D', 'B', '$', 'A', 'D', 'M', 'I', 'N',
|
||||
blr_if,
|
||||
@ -2455,15 +2382,12 @@ static const UCHAR trigger31[] =
|
||||
blr_and,
|
||||
blr_neq,
|
||||
blr_field, 1, 11, 'R', 'D', 'B', '$', 'G', 'R', 'A', 'N', 'T', 'O', 'R',
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_and,
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_literal, blr_text, 6, 0, 'S', 'Y', 'S', 'D', 'B', 'A',
|
||||
blr_neq,
|
||||
blr_upcase,
|
||||
blr_current_role,
|
||||
blr_literal, blr_text, 9, 0, 'R', 'D', 'B', '$', 'A', 'D', 'M', 'I', 'N',
|
||||
blr_begin,
|
||||
@ -2487,7 +2411,6 @@ static const UCHAR trigger31[] =
|
||||
blr_neq,
|
||||
blr_field, 3, 14, 'R', 'D', 'B', '$', 'O', 'W', 'N', 'E', 'R', '_', 'N',
|
||||
'A', 'M', 'E',
|
||||
blr_upcase,
|
||||
blr_user_name,
|
||||
blr_leave, 0,
|
||||
blr_end,
|
||||
|
@ -106,6 +106,10 @@ enum lck_owner_t {
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
@ -277,6 +281,11 @@ int CLIB_ROUTINE main( int argc, char *argv[])
|
||||
* to stdout.
|
||||
*
|
||||
**************************************/
|
||||
#ifdef HAVE_LOCALE_H
|
||||
// Pick up the system locale to allow SYSTEM<->UTF8 conversions
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
OUTFILE outfile = stdout;
|
||||
|
||||
// Perform some special handling when run as a Firebird service. The
|
||||
|
@ -58,6 +58,10 @@
|
||||
#include "../common/classes/Switches.h"
|
||||
#include "../qli/qliswi.h"
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
using MsgFormat::SafeArg;
|
||||
|
||||
|
||||
@ -118,6 +122,11 @@ int CLIB_ROUTINE main(int argc, char** argv)
|
||||
startup_file.append("/.qli_startup");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
// Pick up the system locale to allow SYSTEM<->UTF8 conversions
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
const TEXT* application_file = NULL;
|
||||
ALLQ_init();
|
||||
LEX_init();
|
||||
|
@ -6037,17 +6037,7 @@ static bool get_new_dpb(ClumpletWriter& dpb, const ParametersSet& par)
|
||||
}
|
||||
}
|
||||
|
||||
bool rc = dpb.find(par.user_name);
|
||||
if (rc)
|
||||
{
|
||||
string login;
|
||||
dpb.getString(login);
|
||||
dpb.deleteClumplet();
|
||||
ISC_utf8Upper(login);
|
||||
dpb.insertString(par.user_name, login);
|
||||
}
|
||||
|
||||
return rc;
|
||||
return dpb.find(par.user_name);
|
||||
}
|
||||
|
||||
|
||||
@ -7456,7 +7446,7 @@ static void cleanDpb(Firebird::ClumpletWriter& dpb, const ParametersSet* tags)
|
||||
ClntAuthBlock::ClntAuthBlock(const Firebird::PathName* fileName, Firebird::ClumpletReader* dpb,
|
||||
const ParametersSet* tags)
|
||||
: pluginList(getPool()), serverPluginList(getPool()),
|
||||
userName(getPool()), password(getPool()),
|
||||
cliUserName(getPool()), cliPassword(getPool()), cliOrigUserName(getPool()),
|
||||
dataForPlugin(getPool()), dataFromPlugin(getPool()),
|
||||
cryptKeys(getPool()), dpbConfig(getPool()),
|
||||
hasCryptKey(false), plugins(IPluginManager::TYPE_AUTH_CLIENT),
|
||||
@ -7508,7 +7498,7 @@ void ClntAuthBlock::extractDataFromPluginTo(Firebird::ClumpletWriter& dpb,
|
||||
return;
|
||||
}
|
||||
|
||||
if (REMOTE_legacy_auth(pluginName.c_str(), PROTOCOL_VERSION10)) // dataFromPlugin is encrypted password
|
||||
if (REMOTE_legacy_auth(pluginName.c_str(), PROTOCOL_VERSION10)) // dataFromPlugin is encrypted cliPassword
|
||||
{
|
||||
fb_assert(tags->password_enc);
|
||||
dpb.insertBytes(tags->password_enc, dataFromPlugin.begin(), dataFromPlugin.getCount());
|
||||
@ -7538,22 +7528,24 @@ void ClntAuthBlock::loadClnt(Firebird::ClumpletWriter& dpb, const ParametersSet*
|
||||
const UCHAR t = dpb.getClumpTag();
|
||||
if (t == tags->user_name)
|
||||
{
|
||||
dpb.getString(userName);
|
||||
makeUtfString(uft8Convert, userName);
|
||||
HANDSHAKE_DEBUG(fprintf(stderr, "Cli: loadClnt: Loaded from PB user = %s\n", userName.c_str()));
|
||||
dpb.getString(cliUserName);
|
||||
makeUtfString(uft8Convert, cliUserName);
|
||||
cliOrigUserName = cliUserName;
|
||||
fb_utils::dpbItemUpper(cliUserName);
|
||||
HANDSHAKE_DEBUG(fprintf(stderr, "Cli: loadClnt: Loaded from PB user = %s(was %s)\n", cliUserName.c_str(), cliOrigUserName.c_str()));
|
||||
}
|
||||
else if (t == tags->password)
|
||||
{
|
||||
dpb.getString(password);
|
||||
makeUtfString(uft8Convert, password);
|
||||
dpb.getString(cliPassword);
|
||||
makeUtfString(uft8Convert, cliPassword);
|
||||
HANDSHAKE_DEBUG(fprintf(stderr,
|
||||
"Cli: loadClnt: Loaded from PB password = %s\n", password.c_str()));
|
||||
"Cli: loadClnt: Loaded from PB cliPassword = %s\n", cliPassword.c_str()));
|
||||
}
|
||||
else if (t == tags->encrypt_key)
|
||||
{
|
||||
hasCryptKey = true;
|
||||
HANDSHAKE_DEBUG(fprintf(stderr,
|
||||
"Cli: loadClnt: PB contains crypt key - need encrypted line to pass\n"));
|
||||
"Cli: loadClnt: PB contains crypt key\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -7598,12 +7590,12 @@ void ClntAuthBlock::extractDataFromPluginTo(P_AUTH_CONT* to)
|
||||
|
||||
const char* ClntAuthBlock::getLogin()
|
||||
{
|
||||
return userName.nullStr();
|
||||
return cliUserName.nullStr();
|
||||
}
|
||||
|
||||
const char* ClntAuthBlock::getPassword()
|
||||
{
|
||||
return password.nullStr();
|
||||
return cliPassword.nullStr();
|
||||
}
|
||||
|
||||
const unsigned char* ClntAuthBlock::getData(unsigned int* length)
|
||||
|
@ -890,7 +890,7 @@ Firebird::PathName ClntAuthBlock::getPluginName()
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void addMutliPartConnectParameter(const T& dataToAdd,
|
||||
static void addMultiPartConnectParameter(const T& dataToAdd,
|
||||
Firebird::ClumpletWriter& user_id, UCHAR param)
|
||||
{
|
||||
FB_SIZE_T remaining = dataToAdd.getCount();
|
||||
@ -920,10 +920,10 @@ static void addMutliPartConnectParameter(const T& dataToAdd,
|
||||
void ClntAuthBlock::extractDataFromPluginTo(Firebird::ClumpletWriter& user_id)
|
||||
{
|
||||
// Add user login name
|
||||
if (userName.hasData())
|
||||
if (cliOrigUserName.hasData())
|
||||
{
|
||||
HANDSHAKE_DEBUG(fprintf(stderr, "Cli: extractDataFromPluginTo: userName=%s\n", userName.c_str()));
|
||||
user_id.insertString(CNCT_login, userName);
|
||||
HANDSHAKE_DEBUG(fprintf(stderr, "Cli: extractDataFromPluginTo: cliOrigUserName=%s\n", cliOrigUserName.c_str()));
|
||||
user_id.insertString(CNCT_login, cliOrigUserName);
|
||||
}
|
||||
|
||||
// Add plugin name
|
||||
@ -944,7 +944,7 @@ void ClntAuthBlock::extractDataFromPluginTo(Firebird::ClumpletWriter& user_id)
|
||||
// and we have no ways to override this limit cause it can be sent to any version server.
|
||||
// Therefore divide data into 254-byte parts, leaving first byte for the number of that part.
|
||||
// This appears more reliable than put them in strict order.
|
||||
addMutliPartConnectParameter(dataFromPlugin, user_id, CNCT_specific_data);
|
||||
addMultiPartConnectParameter(dataFromPlugin, user_id, CNCT_specific_data);
|
||||
|
||||
// Client's wirecrypt requested level
|
||||
user_id.insertInt(CNCT_client_crypt, clntConfig->getWireCrypt(WC_CLIENT));
|
||||
|
@ -694,7 +694,8 @@ class ClntAuthBlock FB_FINAL :
|
||||
private:
|
||||
Firebird::PathName pluginList; // To be passed to server
|
||||
Firebird::PathName serverPluginList; // Received from server
|
||||
Firebird::string userName, password; // Used by plugin, taken from DPB
|
||||
Firebird::string cliUserName, cliPassword; // Used by plugin, taken from DPB
|
||||
Firebird::string cliOrigUserName; // Original user anme, passed to server
|
||||
// These two are legacy encrypted password, trusted auth data and so on - what plugin needs
|
||||
Firebird::UCharBuffer dataForPlugin, dataFromPlugin;
|
||||
Firebird::HalfStaticArray<InternalCryptKey*, 1> cryptKeys; // Wire crypt keys that came from plugin(s) last time
|
||||
|
@ -311,7 +311,7 @@ public:
|
||||
if (aPb->find(tags->user_name))
|
||||
{
|
||||
aPb->getString(userName);
|
||||
userName.upper();
|
||||
fb_utils::dpbItemUpper(userName);
|
||||
if (authPort->port_srv_auth_block->getLogin() &&
|
||||
userName != authPort->port_srv_auth_block->getLogin())
|
||||
{
|
||||
@ -6251,7 +6251,7 @@ void SrvAuthBlock::load(Firebird::ClumpletReader& id)
|
||||
if (id.find(CNCT_login))
|
||||
{
|
||||
id.getString(userName);
|
||||
userName.upper();
|
||||
fb_utils::dpbItemUpper(userName);
|
||||
HANDSHAKE_DEBUG(fprintf(stderr, "Srv: AuthBlock: login %s\n", userName.c_str()));
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,10 @@
|
||||
#include "../common/StatusArg.h"
|
||||
#include "../jrd/license.h"
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
using namespace Firebird;
|
||||
|
||||
// Here we define main control structure
|
||||
@ -972,6 +976,11 @@ static void ctrl_c_handler(int signal)
|
||||
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
#ifdef HAVE_LOCALE_H
|
||||
// Pick up the system locale to allow SYSTEM<->UTF8 conversions
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
if (ac < 2 || (ac == 2 && strcmp(av[1], "-?") == 0))
|
||||
{
|
||||
usage(ac == 2);
|
||||
|
@ -35,6 +35,10 @@
|
||||
#include "../../jrd/trace/TraceService.h"
|
||||
#include "../../jrd/ibase.h"
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
class TraceSvcUtil : public TraceSvcIntf
|
||||
@ -320,6 +324,10 @@ int CLIB_ROUTINE main(int argc, char* argv[])
|
||||
* Invoke real trace main function
|
||||
*
|
||||
**************************************/
|
||||
#ifdef HAVE_LOCALE_H
|
||||
// Pick up the system locale to allow SYSTEM<->UTF8 conversions
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
prevCtrlCHandler = signal(SIGINT, ctrl_c_handler);
|
||||
|
||||
|
@ -31,6 +31,10 @@
|
||||
#include "../common/classes/auto.h"
|
||||
#include "../common/SimpleStatusVector.h"
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
|
||||
int CLIB_ROUTINE main(int argc, char* argv[])
|
||||
{
|
||||
@ -44,6 +48,11 @@ int CLIB_ROUTINE main(int argc, char* argv[])
|
||||
* Invoke real gsec main function
|
||||
*
|
||||
**************************************/
|
||||
#ifdef HAVE_LOCALE_H
|
||||
// Pick up the system locale to allow SYSTEM<->UTF8 conversions
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
Firebird::AutoPtr<Firebird::UtilSvc> uSvc(Firebird::UtilSvc::createStandalone(argc, argv));
|
||||
|
@ -31,6 +31,10 @@
|
||||
#include "../common/classes/auto.h"
|
||||
#include "../common/SimpleStatusVector.h"
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
|
||||
int CLIB_ROUTINE main(int argc, char* argv[])
|
||||
{
|
||||
@ -44,6 +48,11 @@ int CLIB_ROUTINE main(int argc, char* argv[])
|
||||
* Invoke real gstat main function
|
||||
*
|
||||
**************************************/
|
||||
#ifdef HAVE_LOCALE_H
|
||||
// Pick up the system locale to allow SYSTEM<->UTF8 conversions
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
Firebird::AutoPtr<Firebird::UtilSvc> uSvc(Firebird::UtilSvc::createStandalone(argc, argv));
|
||||
|
@ -30,6 +30,10 @@
|
||||
#include "../utilities/nbackup/nbk_proto.h"
|
||||
#include "../common/classes/auto.h"
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
|
||||
int CLIB_ROUTINE main(int argc, char* argv[])
|
||||
{
|
||||
@ -43,6 +47,11 @@ int CLIB_ROUTINE main(int argc, char* argv[])
|
||||
* Invoke real nbackup main function
|
||||
*
|
||||
**************************************/
|
||||
#ifdef HAVE_LOCALE_H
|
||||
// Pick up the system locale to allow SYSTEM<->UTF8 conversions
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
Firebird::AutoPtr<Firebird::UtilSvc> uSvc(Firebird::UtilSvc::createStandalone(argc, argv));
|
||||
|
@ -25,12 +25,13 @@
|
||||
#include "firebird.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../dsql/chars.h"
|
||||
//#include "../dsql/chars.h"
|
||||
#include "../yvalve/prepa_proto.h"
|
||||
#include "../yvalve/gds_proto.h"
|
||||
#include "../yvalve/YObjects.h"
|
||||
#include "../common/classes/ClumpletWriter.h"
|
||||
#include "../common/StatusArg.h"
|
||||
#include "../common/Tokens.h"
|
||||
|
||||
#include <firebird/Interface.h>
|
||||
|
||||
@ -52,15 +53,11 @@ enum pp_vals {
|
||||
|
||||
|
||||
const size_t MAX_TOKEN_SIZE = 1024;
|
||||
static void generate_error(Firebird::CheckStatusWrapper*, const Firebird::string&, SSHORT, SSHORT);
|
||||
static SSHORT get_next_token(const SCHAR**, const SCHAR*, Firebird::string&);
|
||||
static SSHORT get_token(Firebird::CheckStatusWrapper*, SSHORT, bool, const SCHAR**, const SCHAR* const,
|
||||
Firebird::string&);
|
||||
static void generate_error(const Firebird::NoCaseString&, SSHORT, char = 0);
|
||||
|
||||
struct pp_table
|
||||
{
|
||||
SCHAR symbol[10];
|
||||
USHORT length;
|
||||
SSHORT code;
|
||||
};
|
||||
|
||||
@ -68,22 +65,23 @@ struct pp_table
|
||||
// Should delete SCHEMA in the future.
|
||||
static const pp_table pp_symbols[] =
|
||||
{
|
||||
{"CREATE", 6, PP_CREATE},
|
||||
{"DATABASE", 8, PP_DATABASE},
|
||||
{"SCHEMA", 6, PP_SCHEMA},
|
||||
{"PAGE_SIZE", 9, PP_PAGE_SIZE},
|
||||
{"USER", 4, PP_USER},
|
||||
{"PASSWORD", 8, PP_PASSWORD},
|
||||
{"PAGESIZE", 8, PP_PAGESIZE},
|
||||
{"LENGTH", 6, PP_LENGTH},
|
||||
{"PAGES", 5, PP_PAGES},
|
||||
{"PAGE", 4, PP_PAGE},
|
||||
{"SET", 3, PP_SET},
|
||||
{"NAMES", 5, PP_NAMES},
|
||||
{"ROLE", 4, PP_ROLE},
|
||||
{"", 0, 0}
|
||||
{"CREATE", PP_CREATE},
|
||||
{"DATABASE", PP_DATABASE},
|
||||
{"SCHEMA", PP_SCHEMA},
|
||||
{"PAGE_SIZE", PP_PAGE_SIZE},
|
||||
{"USER", PP_USER},
|
||||
{"PASSWORD", PP_PASSWORD},
|
||||
{"PAGESIZE", PP_PAGESIZE},
|
||||
{"LENGTH", PP_LENGTH},
|
||||
{"PAGES", PP_PAGES},
|
||||
{"PAGE", PP_PAGE},
|
||||
{"SET", PP_SET},
|
||||
{"NAMES", PP_NAMES},
|
||||
{"ROLE", PP_ROLE},
|
||||
{"", 0}
|
||||
};
|
||||
|
||||
|
||||
// define the tokens
|
||||
|
||||
enum token_vals {
|
||||
@ -96,9 +94,55 @@ enum token_vals {
|
||||
SYMBOL = 259
|
||||
};
|
||||
|
||||
static const char* quotes = "\"\'";
|
||||
|
||||
|
||||
using namespace Firebird;
|
||||
|
||||
|
||||
static NoCaseString getToken(unsigned& pos, const Tokens& toks, int symbol = SYMBOL)
|
||||
{
|
||||
if (pos >= toks.getCount())
|
||||
generate_error("", UNEXPECTED_END_OF_COMMAND);
|
||||
|
||||
NoCaseString curTok(NoCaseString(toks[pos].text, toks[pos].length));
|
||||
|
||||
switch(symbol)
|
||||
{
|
||||
case SYMBOL:
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
if (!strchr(quotes, toks[pos].text[0]))
|
||||
generate_error(curTok, UNEXPECTED_TOKEN);
|
||||
return toks[pos++].stripped().ToNoCaseString();
|
||||
|
||||
case NUMERIC:
|
||||
{
|
||||
const char* const end = &toks[pos].text[toks[pos].length];
|
||||
for (const char* ptr = toks[pos].text; ptr < end; ++ptr)
|
||||
{
|
||||
if (*ptr < '0' || *ptr > '9')
|
||||
generate_error(curTok, UNEXPECTED_TOKEN);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (symbol > 0 && symbol <= 127) // good ascii symbol
|
||||
{
|
||||
if (toks[pos].length != 1 || toks[pos].text[0] != symbol)
|
||||
generate_error(curTok, UNEXPECTED_TOKEN);
|
||||
}
|
||||
fb_assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
++pos;
|
||||
return curTok;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
PREPARSE_execute
|
||||
@ -126,31 +170,21 @@ bool PREPARSE_execute(CheckStatusWrapper* status, Why::YAttachment** ptrAtt,
|
||||
Arg::Gds(isc_command_end_err).raise();
|
||||
}
|
||||
|
||||
if (!stmt_length)
|
||||
stmt_length = static_cast<USHORT>(strlen(stmt));
|
||||
const char* const stmt_end = stmt + stmt_length;
|
||||
string token;
|
||||
Tokens tks(stmt_length, stmt, sqlSpaces, quotes, sqlComments);
|
||||
unsigned pos = 0;
|
||||
|
||||
if (get_token(status, SYMBOL, false, &stmt, stmt_end, token) ||
|
||||
token.length() != pp_symbols[PP_CREATE].length || token != pp_symbols[PP_CREATE].symbol)
|
||||
if (getToken(pos, tks) != pp_symbols[PP_CREATE].symbol)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (get_token(status, SYMBOL, false, &stmt, stmt_end, token) ||
|
||||
(token.length() != pp_symbols[PP_DATABASE].length &&
|
||||
token.length() != pp_symbols[PP_SCHEMA].length) ||
|
||||
(token != pp_symbols[PP_DATABASE].symbol && token != pp_symbols[PP_SCHEMA].symbol))
|
||||
NoCaseString token(getToken(pos, tks));
|
||||
if (token != pp_symbols[PP_DATABASE].symbol && token != pp_symbols[PP_SCHEMA].symbol)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (get_token(status, STRING, false, &stmt, stmt_end, token))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
PathName file_name(token.ToPathName());
|
||||
PathName file_name(getToken(pos, tks, STRING).ToPathName());
|
||||
*stmt_eaten = false;
|
||||
ClumpletWriter dpb(ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1);
|
||||
|
||||
@ -160,22 +194,21 @@ bool PREPARSE_execute(CheckStatusWrapper* status, Why::YAttachment** ptrAtt,
|
||||
SLONG page_size = 0;
|
||||
bool matched;
|
||||
do {
|
||||
const SSHORT result = get_next_token(&stmt, stmt_end, token);
|
||||
if (result == NO_MORE_TOKENS)
|
||||
try
|
||||
{
|
||||
token = getToken(pos, tks);
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
*stmt_eaten = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (result < 0)
|
||||
break;
|
||||
|
||||
matched = false;
|
||||
for (int i = 3; pp_symbols[i].length && !matched; i++)
|
||||
for (int i = 3; pp_symbols[i].symbol[0] && !matched; i++)
|
||||
{
|
||||
if (token.length() == pp_symbols[i].length && token == pp_symbols[i].symbol)
|
||||
if (token == pp_symbols[i].symbol)
|
||||
{
|
||||
bool get_out = false;
|
||||
// CVC: What's strange, this routine doesn't check token.length()
|
||||
// but it proceeds blindly, trying to exhaust the token itself.
|
||||
|
||||
@ -183,74 +216,52 @@ bool PREPARSE_execute(CheckStatusWrapper* status, Why::YAttachment** ptrAtt,
|
||||
{
|
||||
case PP_PAGE_SIZE:
|
||||
case PP_PAGESIZE:
|
||||
if (get_token(status, '=', true, &stmt, stmt_end, token) ||
|
||||
get_token(status, NUMERIC, false, &stmt, stmt_end, token))
|
||||
{
|
||||
get_out = true;
|
||||
break;
|
||||
}
|
||||
token = getToken(pos, tks);
|
||||
if (token == "=")
|
||||
token = getToken(pos, tks, NUMERIC);
|
||||
|
||||
page_size = atol(token.c_str());
|
||||
dpb.insertInt(isc_dpb_page_size, page_size);
|
||||
matched = true;
|
||||
break;
|
||||
|
||||
case PP_USER:
|
||||
if (get_token(status, STRING, false, &stmt, stmt_end, token))
|
||||
{
|
||||
get_out = true;
|
||||
break;
|
||||
}
|
||||
token = getToken(pos, tks);
|
||||
|
||||
dpb.insertString(isc_dpb_user_name, token);
|
||||
dpb.insertString(isc_dpb_user_name, token.ToString());
|
||||
matched = true;
|
||||
break;
|
||||
|
||||
case PP_PASSWORD:
|
||||
if (get_token(status, STRING, false, &stmt, stmt_end, token))
|
||||
{
|
||||
get_out = true;
|
||||
break;
|
||||
}
|
||||
token = getToken(pos, tks, STRING);
|
||||
|
||||
dpb.insertString(isc_dpb_password, token);
|
||||
dpb.insertString(isc_dpb_password, token.ToString());
|
||||
matched = true;
|
||||
break;
|
||||
|
||||
case PP_ROLE:
|
||||
if (get_token(status, STRING, false, &stmt, stmt_end, token))
|
||||
{
|
||||
get_out = true;
|
||||
break;
|
||||
}
|
||||
token = getToken(pos, tks);
|
||||
|
||||
dpb.insertString(isc_dpb_sql_role_name, token);
|
||||
dpb.insertString(isc_dpb_sql_role_name, token.ToString());
|
||||
matched = true;
|
||||
break;
|
||||
|
||||
case PP_SET:
|
||||
if (get_token(status, SYMBOL, false, &stmt, stmt_end, token) ||
|
||||
token.length() != pp_symbols[PP_NAMES].length ||
|
||||
token != pp_symbols[PP_NAMES].symbol ||
|
||||
get_token(status, STRING, false, &stmt, stmt_end, token))
|
||||
{
|
||||
get_out = true;
|
||||
break;
|
||||
}
|
||||
token = getToken(pos, tks);
|
||||
if (token != pp_symbols[PP_NAMES].symbol)
|
||||
generate_error(token, UNEXPECTED_TOKEN);
|
||||
token = getToken(pos, tks, STRING);
|
||||
|
||||
dpb.insertString(isc_dpb_lc_ctype, token);
|
||||
dpb.insertString(isc_dpb_lc_ctype, token.ToString());
|
||||
matched = true;
|
||||
break;
|
||||
|
||||
case PP_LENGTH:
|
||||
token = getToken(pos, tks);
|
||||
if (token == "=")
|
||||
token = getToken(pos, tks, NUMERIC);
|
||||
|
||||
// Skip a token for value
|
||||
|
||||
if (get_token(status, '=', true, &stmt, stmt_end, token) ||
|
||||
get_token(status, NUMERIC, false, &stmt, stmt_end, token))
|
||||
{
|
||||
get_out = true;
|
||||
break;
|
||||
}
|
||||
|
||||
matched = true;
|
||||
break;
|
||||
|
||||
@ -258,14 +269,9 @@ bool PREPARSE_execute(CheckStatusWrapper* status, Why::YAttachment** ptrAtt,
|
||||
case PP_PAGES:
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (get_out) {
|
||||
return true;
|
||||
}
|
||||
} // switch
|
||||
} // if
|
||||
} // for
|
||||
|
||||
} while (matched);
|
||||
|
||||
RefPtr<Why::Dispatcher> dispatcher(new Why::Dispatcher);
|
||||
@ -294,7 +300,7 @@ bool PREPARSE_execute(CheckStatusWrapper* status, Why::YAttachment** ptrAtt,
|
||||
@param result
|
||||
|
||||
**/
|
||||
static void generate_error(CheckStatusWrapper* status, const string& token, SSHORT error, SSHORT result)
|
||||
static void generate_error(const NoCaseString& token, SSHORT error, char result)
|
||||
{
|
||||
string err_string;
|
||||
|
||||
@ -316,12 +322,12 @@ static void generate_error(CheckStatusWrapper* status, const string& token, SSHO
|
||||
case TOKEN_TOO_LONG:
|
||||
if (result)
|
||||
{
|
||||
err_string.assign(1, (TEXT) result);
|
||||
err_string += token;
|
||||
err_string += (TEXT) result;
|
||||
err_string = result;
|
||||
err_string += token.ToString();
|
||||
err_string += result;
|
||||
}
|
||||
else
|
||||
err_string = token;
|
||||
err_string = token.ToString();
|
||||
temp_status[5] = isc_token_err;
|
||||
temp_status[6] = isc_arg_gds;
|
||||
temp_status[7] = isc_random;
|
||||
@ -331,201 +337,5 @@ static void generate_error(CheckStatusWrapper* status, const string& token, SSHO
|
||||
break;
|
||||
}
|
||||
|
||||
status->setErrors(temp_status);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
get_next_token
|
||||
|
||||
@brief
|
||||
|
||||
@param stmt
|
||||
@param stmt_end
|
||||
@param token
|
||||
|
||||
**/
|
||||
static SSHORT get_next_token(const SCHAR** stmt, const SCHAR* stmt_end, string& token)
|
||||
{
|
||||
UCHAR c, char_class = 0;
|
||||
|
||||
token.erase();
|
||||
const SCHAR* s = *stmt;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (s >= stmt_end)
|
||||
{
|
||||
*stmt = s;
|
||||
return NO_MORE_TOKENS;
|
||||
}
|
||||
|
||||
c = *s++;
|
||||
|
||||
if (c == '/' && s < stmt_end && *s == '*')
|
||||
{
|
||||
s++;
|
||||
while (s < stmt_end)
|
||||
{
|
||||
c = *s++;
|
||||
if (c == '*' && s < stmt_end && *s == '/')
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// CVC: Dmitry told me to leave this in peace, but if somebody wants
|
||||
// to experiment ignoring single line comments, here's an idea.
|
||||
if (c == '-' && s < stmt_end && *s == '-')
|
||||
{
|
||||
s++;
|
||||
while (s < stmt_end)
|
||||
{
|
||||
c = *s++;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// CVC: End modification.
|
||||
|
||||
char_class = classes(c);
|
||||
if (!(char_class & CHR_WHITE))
|
||||
break;
|
||||
}
|
||||
|
||||
// At this point c contains character and class contains character class.
|
||||
// s is pointing to next character.
|
||||
|
||||
const SCHAR* const start_of_token = s - 1;
|
||||
|
||||
// In here we handle only 4 cases, STRING, INTEGER, arbitrary
|
||||
// SYMBOL and single character punctuation.
|
||||
|
||||
if (char_class & CHR_QUOTE)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (s >= stmt_end)
|
||||
return UNEXPECTED_END_OF_COMMAND;
|
||||
|
||||
// *s is quote - if next != quote we're at the end
|
||||
|
||||
if ((*s == c) && ((++s == stmt_end) || (*s != c)))
|
||||
break;
|
||||
token += *s++;
|
||||
}
|
||||
*stmt = s;
|
||||
if (token.length() > MAX_TOKEN_SIZE)
|
||||
{
|
||||
// '=' used as then there is no place for null termination
|
||||
token.erase(MAX_TOKEN_SIZE);
|
||||
return TOKEN_TOO_LONG;
|
||||
}
|
||||
return STRING;
|
||||
}
|
||||
|
||||
// Is it an integer?
|
||||
|
||||
if (char_class & CHR_DIGIT)
|
||||
{
|
||||
for (; s < stmt_end && (classes(c = *s) & CHR_DIGIT); ++s); // empty body
|
||||
fb_assert(s >= start_of_token);
|
||||
const FB_SIZE_T length = static_cast<FB_SIZE_T>(s - start_of_token);
|
||||
*stmt = s;
|
||||
if (length > MAX_TOKEN_SIZE)
|
||||
{
|
||||
token.assign(start_of_token, MAX_TOKEN_SIZE);
|
||||
return TOKEN_TOO_LONG;
|
||||
}
|
||||
token.assign(start_of_token, length);
|
||||
return NUMERIC;
|
||||
}
|
||||
|
||||
// Is is a symbol?
|
||||
|
||||
if (char_class & CHR_LETTER)
|
||||
{
|
||||
token += UPPER(c);
|
||||
for (; s < stmt_end && (classes(*s) & CHR_IDENT); s++) {
|
||||
token += UPPER(*s);
|
||||
}
|
||||
|
||||
*stmt = s;
|
||||
if (token.length() > MAX_TOKEN_SIZE)
|
||||
{
|
||||
token.erase(MAX_TOKEN_SIZE);
|
||||
return TOKEN_TOO_LONG;
|
||||
}
|
||||
return SYMBOL;
|
||||
}
|
||||
|
||||
// What remains at this point for us is the single character punctuation.
|
||||
|
||||
*stmt = s;
|
||||
|
||||
return (c == ';' ? NO_MORE_TOKENS : c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
get_token
|
||||
|
||||
@brief
|
||||
|
||||
@param status
|
||||
@param token_type
|
||||
@param optional
|
||||
@param stmt
|
||||
@param stmt_end
|
||||
@param token
|
||||
|
||||
**/
|
||||
static SSHORT get_token(CheckStatusWrapper* status,
|
||||
SSHORT token_type,
|
||||
bool optional,
|
||||
const SCHAR** stmt,
|
||||
const SCHAR* const stmt_end,
|
||||
string& token)
|
||||
{
|
||||
const SCHAR* temp_stmt = *stmt;
|
||||
const SSHORT result = get_next_token(&temp_stmt, stmt_end, token);
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case NO_MORE_TOKENS:
|
||||
*stmt = temp_stmt;
|
||||
generate_error(status, token, UNEXPECTED_END_OF_COMMAND, 0);
|
||||
return FB_FAILURE;
|
||||
|
||||
case UNEXPECTED_END_OF_COMMAND:
|
||||
case TOKEN_TOO_LONG:
|
||||
*stmt = temp_stmt;
|
||||
|
||||
// generate error here
|
||||
|
||||
generate_error(status, token, result, 0);
|
||||
return FB_FAILURE;
|
||||
}
|
||||
|
||||
// Some token was found
|
||||
|
||||
if (result == token_type)
|
||||
{
|
||||
*stmt = temp_stmt;
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
if (optional)
|
||||
return FB_SUCCESS;
|
||||
|
||||
// generate error here and return failure;
|
||||
|
||||
*stmt = temp_stmt;
|
||||
generate_error(status, token, UNEXPECTED_TOKEN,
|
||||
(result == STRING) ? *(temp_stmt - 1) : 0);
|
||||
return FB_FAILURE;
|
||||
Arg::StatusVector(temp_status).raise();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user