Implement an auto-escaping Format native for SQL query construction
This commit is contained in:
parent
272655f340
commit
700ec92a9a
@ -32,6 +32,7 @@
|
||||
#include "common_logic.h"
|
||||
#include "Database.h"
|
||||
#include "ExtensionSys.h"
|
||||
#include "sprintf.h"
|
||||
#include "stringutil.h"
|
||||
#include "ISourceMod.h"
|
||||
#include "AutoHandleRooter.h"
|
||||
@ -732,6 +733,24 @@ static cell_t SQL_QuoteString(IPluginContext *pContext, const cell_t *params)
|
||||
return s ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t SQL_FormatQuery(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IDatabase *db = NULL;
|
||||
HandleError err;
|
||||
|
||||
if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
|
||||
}
|
||||
|
||||
g_FormatEscapeDatabase = db;
|
||||
cell_t result = InternalFormat(pContext, params, 1);
|
||||
g_FormatEscapeDatabase = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static cell_t SQL_FastQuery(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
IDatabase *db = NULL;
|
||||
@ -1814,6 +1833,7 @@ REGISTER_NATIVES(dbNatives)
|
||||
{"Database.Driver.get", Database_Driver_get},
|
||||
{"Database.SetCharset", SQL_SetCharset},
|
||||
{"Database.Escape", SQL_QuoteString},
|
||||
{"Database.Format", SQL_FormatQuery},
|
||||
{"Database.IsSameConnection", SQL_IsSameConnection},
|
||||
{"Database.Execute", SQL_ExecuteTransaction},
|
||||
|
||||
@ -1827,6 +1847,7 @@ REGISTER_NATIVES(dbNatives)
|
||||
{"SQL_Connect", SQL_Connect},
|
||||
{"SQL_ConnectEx", SQL_ConnectEx},
|
||||
{"SQL_EscapeString", SQL_QuoteString},
|
||||
{"SQL_FormatQuery", SQL_FormatQuery},
|
||||
{"SQL_Execute", SQL_Execute},
|
||||
{"SQL_FastQuery", SQL_FastQuery},
|
||||
{"SQL_FetchFloat", SQL_FetchFloat},
|
||||
|
@ -30,15 +30,19 @@
|
||||
#include "sprintf.h"
|
||||
#include <am-float.h>
|
||||
#include <am-string.h>
|
||||
#include <IDBDriver.h>
|
||||
#include <ITranslator.h>
|
||||
#include <bridge/include/IScriptManager.h>
|
||||
#include <bridge/include/CoreProvider.h>
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
IDatabase *g_FormatEscapeDatabase = NULL;
|
||||
|
||||
#define LADJUST 0x00000001 /* left adjustment */
|
||||
#define ZEROPAD 0x00000002 /* zero (as opposed to blank) pad */
|
||||
#define UPPERDIGITS 0x00000004 /* make alpha digits uppercase */
|
||||
#define NOESCAPE 0x00000008 /* do not escape strings (they are only escaped if a database connection is provided) */
|
||||
#define to_digit(c) ((c) - '0')
|
||||
#define is_digit(c) ((unsigned)to_digit(c) <= 9)
|
||||
|
||||
@ -158,6 +162,7 @@ bool AddString(char **buf_p, size_t &maxlen, const char *string, int width, int
|
||||
{
|
||||
string = nlstr;
|
||||
prec = -1;
|
||||
flags |= NOESCAPE;
|
||||
}
|
||||
|
||||
if (prec >= 0)
|
||||
@ -181,12 +186,44 @@ bool AddString(char **buf_p, size_t &maxlen, const char *string, int width, int
|
||||
size = maxlen;
|
||||
}
|
||||
|
||||
maxlen -= size;
|
||||
width -= size;
|
||||
|
||||
while (size--)
|
||||
if (g_FormatEscapeDatabase && (flags & NOESCAPE) == 0)
|
||||
{
|
||||
*buf++ = *string++;
|
||||
char *tempBuffer = NULL;
|
||||
if (prec != -1)
|
||||
{
|
||||
// I doubt anyone will ever do this, so just allocate.
|
||||
tempBuffer = new char[maxlen + 1];
|
||||
memcpy(tempBuffer, string, size);
|
||||
tempBuffer[size] = '\0';
|
||||
}
|
||||
|
||||
size_t newSize;
|
||||
bool ret = g_FormatEscapeDatabase->QuoteString(tempBuffer ? tempBuffer : string, buf, maxlen + 1, &newSize);
|
||||
|
||||
if (tempBuffer)
|
||||
{
|
||||
delete[] tempBuffer;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
maxlen -= newSize;
|
||||
buf += newSize;
|
||||
size = 0; // Consistency.
|
||||
}
|
||||
else
|
||||
{
|
||||
maxlen -= size;
|
||||
|
||||
while (size--)
|
||||
{
|
||||
*buf++ = *string++;
|
||||
}
|
||||
}
|
||||
|
||||
while ((width-- > 0) && maxlen)
|
||||
@ -213,7 +250,7 @@ void AddFloat(char **buf_p, size_t &maxlen, double fval, int width, int prec, in
|
||||
|
||||
if (ke::IsNaN(fval))
|
||||
{
|
||||
AddString(buf_p, maxlen, "NaN", width, prec, flags);
|
||||
AddString(buf_p, maxlen, "NaN", width, prec, flags | NOESCAPE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1031,6 +1068,11 @@ reswitch:
|
||||
flags |= LADJUST;
|
||||
goto rflag;
|
||||
}
|
||||
case '!':
|
||||
{
|
||||
flags |= NOESCAPE;
|
||||
goto rflag;
|
||||
}
|
||||
case '.':
|
||||
{
|
||||
n = 0;
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <sp_vm_api.h>
|
||||
|
||||
namespace SourceMod {
|
||||
class IDatabase;
|
||||
class IPhraseCollection;
|
||||
}
|
||||
|
||||
@ -57,4 +58,6 @@ bool gnprintf(char *buffer,
|
||||
size_t *pOutLength,
|
||||
const char **pFailPhrase);
|
||||
|
||||
extern SourceMod::IDatabase *g_FormatEscapeDatabase;
|
||||
|
||||
#endif // _include_sourcemod_core_logic_sprintf_h_
|
||||
|
@ -380,6 +380,16 @@ methodmap Database < Handle
|
||||
// The buffer must be at least 2*strlen(string)+1.
|
||||
public native bool Escape(const char[] string, char[] buffer, int maxlength, int &written=0);
|
||||
|
||||
// Formats a string according to the SourceMod format rules (see documentation).
|
||||
// All format specifiers are escaped (see SQL_EscapeString) unless the '!' flag is used.
|
||||
//
|
||||
// @param buffer Destination string buffer.
|
||||
// @param maxlength Maximum length of output string buffer.
|
||||
// @param format Formatting rules.
|
||||
// @param ... Variable number of format parameters.
|
||||
// @return Number of cells written.
|
||||
public native int Format(const char[] buffer, int maxlength, const char[] format, any ...);
|
||||
|
||||
// Returns whether a database is the same connection as another database.
|
||||
public native bool IsSameConnection(Database other);
|
||||
|
||||
@ -641,6 +651,19 @@ native bool SQL_EscapeString(Handle database,
|
||||
int maxlength,
|
||||
int &written=0);
|
||||
|
||||
/**
|
||||
* Formats a string according to the SourceMod format rules (see documentation).
|
||||
* All format specifiers are escaped (see SQL_EscapeString) unless the '!' flag is used.
|
||||
*
|
||||
* @param database A database Handle.
|
||||
* @param buffer Destination string buffer.
|
||||
* @param maxlength Maximum length of output string buffer.
|
||||
* @param format Formatting rules.
|
||||
* @param ... Variable number of format parameters.
|
||||
* @return Number of cells written.
|
||||
*/
|
||||
native int SQL_FormatQuery(Handle database, const char[] buffer, int maxlength, const char[] format, any ...);
|
||||
|
||||
/**
|
||||
* This is a backwards compatibility stock. You should use SQL_EscapeString()
|
||||
* instead, as this function will probably be deprecated in SourceMod 1.1.
|
||||
|
Loading…
Reference in New Issue
Block a user