mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
add pg_escape_identifier/pg_escape_literal
This commit is contained in:
parent
106e0a2e68
commit
655245afef
@ -94,6 +94,7 @@ if test "$PHP_PGSQL" != "no"; then
|
|||||||
AC_CHECK_LIB(pq, pg_encoding_to_char,AC_DEFINE(HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT,1,[Whether libpq is compiled with --enable-multibyte]))
|
AC_CHECK_LIB(pq, pg_encoding_to_char,AC_DEFINE(HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT,1,[Whether libpq is compiled with --enable-multibyte]))
|
||||||
AC_CHECK_LIB(pq, lo_create, AC_DEFINE(HAVE_PG_LO_CREATE,1,[PostgreSQL 8.1 or later]))
|
AC_CHECK_LIB(pq, lo_create, AC_DEFINE(HAVE_PG_LO_CREATE,1,[PostgreSQL 8.1 or later]))
|
||||||
AC_CHECK_LIB(pq, lo_import_with_oid, AC_DEFINE(HAVE_PG_LO_IMPORT_WITH_OID,1,[PostgreSQL 8.4 or later]))
|
AC_CHECK_LIB(pq, lo_import_with_oid, AC_DEFINE(HAVE_PG_LO_IMPORT_WITH_OID,1,[PostgreSQL 8.4 or later]))
|
||||||
|
AC_CHECK_LIB(pq, PQescapeLiteral, AC_DEFINE(HAVE_PQESCAPELITERAL,1,[PostgreSQL 9.0 or later]))
|
||||||
LIBS=$old_LIBS
|
LIBS=$old_LIBS
|
||||||
LDFLAGS=$old_LDFLAGS
|
LDFLAGS=$old_LDFLAGS
|
||||||
|
|
||||||
|
@ -422,6 +422,17 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_unescape_bytea, 0, 0, 1)
|
|||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_PQESCAPE
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_literal, 0, 0, 0)
|
||||||
|
ZEND_ARG_INFO(0, connection)
|
||||||
|
ZEND_ARG_INFO(0, data)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_identifier, 0, 0, 0)
|
||||||
|
ZEND_ARG_INFO(0, connection)
|
||||||
|
ZEND_ARG_INFO(0, data)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
#endif
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_error, 0, 0, 1)
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_error, 0, 0, 1)
|
||||||
ZEND_ARG_INFO(0, result)
|
ZEND_ARG_INFO(0, result)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
@ -652,6 +663,8 @@ const zend_function_entry pgsql_functions[] = {
|
|||||||
PHP_FE(pg_escape_string, arginfo_pg_escape_string)
|
PHP_FE(pg_escape_string, arginfo_pg_escape_string)
|
||||||
PHP_FE(pg_escape_bytea, arginfo_pg_escape_bytea)
|
PHP_FE(pg_escape_bytea, arginfo_pg_escape_bytea)
|
||||||
PHP_FE(pg_unescape_bytea, arginfo_pg_unescape_bytea)
|
PHP_FE(pg_unescape_bytea, arginfo_pg_unescape_bytea)
|
||||||
|
PHP_FE(pg_escape_literal, arginfo_pg_escape_literal)
|
||||||
|
PHP_FE(pg_escape_identifier, arginfo_pg_escape_identifier)
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_PQSETERRORVERBOSITY
|
#if HAVE_PQSETERRORVERBOSITY
|
||||||
PHP_FE(pg_set_error_verbosity, arginfo_pg_set_error_verbosity)
|
PHP_FE(pg_set_error_verbosity, arginfo_pg_set_error_verbosity)
|
||||||
@ -815,7 +828,7 @@ static void _php_pgsql_notice_handler(void *resource_id, const char *message)
|
|||||||
TSRMLS_FETCH();
|
TSRMLS_FETCH();
|
||||||
if (! PGG(ignore_notices)) {
|
if (! PGG(ignore_notices)) {
|
||||||
notice = (php_pgsql_notice *)emalloc(sizeof(php_pgsql_notice));
|
notice = (php_pgsql_notice *)emalloc(sizeof(php_pgsql_notice));
|
||||||
notice->message = _php_pgsql_trim_message(message, ¬ice->len);
|
notice->message = _php_pgsql_trim_message(message, (int *)¬ice->len);
|
||||||
if (PGG(log_notices)) {
|
if (PGG(log_notices)) {
|
||||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s", notice->message);
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s", notice->message);
|
||||||
}
|
}
|
||||||
@ -4206,6 +4219,130 @@ PHP_FUNCTION(pg_unescape_bytea)
|
|||||||
/* }}} */
|
/* }}} */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PQESCAPE
|
||||||
|
#if !HAVE_PQESCAPELITERAL
|
||||||
|
/* emulate libpq's PQescapeInternal() 9.0 or later */
|
||||||
|
static char* php_pgsql_PQescapeInternal(PGconn *conn, const char *str, size_t len, int escape_literal) {
|
||||||
|
char *result, *rp;
|
||||||
|
const char *s;
|
||||||
|
size_t tmp_len;
|
||||||
|
int input_len = len;
|
||||||
|
char quote_char = escape_literal ? '\'' : '"';
|
||||||
|
|
||||||
|
if (!conn) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: multibyte strings that could cointain slashes should be considered.
|
||||||
|
* (e.g. SJIS, BIG5) However, it cannot be done without valid PGconn and mbstring.
|
||||||
|
* Therefore, this function does not support such encodings currently.
|
||||||
|
* FIXME: add encoding check and skip multibyte char bytes if there is vaild PGconn.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* allocate enough memory */
|
||||||
|
rp = result = (char *)emalloc(len*2 + 5); /* leading " E" needs extra 2 bytes + quote_chars on both end for 2 bytes + NULL */
|
||||||
|
|
||||||
|
if (escape_literal) {
|
||||||
|
/* check backslashes */
|
||||||
|
tmp_len = strspn(str, "\\");
|
||||||
|
if (tmp_len != len) {
|
||||||
|
/* add " E" for escaping slashes */
|
||||||
|
*rp++ = ' ';
|
||||||
|
*rp++ = 'E';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* open quote */
|
||||||
|
*rp++ = quote_char;
|
||||||
|
for (s = str; s - str < input_len; ++s) {
|
||||||
|
if (*s == quote_char || (escape_literal && *s == '\\')) {
|
||||||
|
*rp++ = *s;
|
||||||
|
*rp++ = *s;
|
||||||
|
} else {
|
||||||
|
*rp++ = *s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*rp++ = quote_char;
|
||||||
|
*rp = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAMETERS, int escape_literal) {
|
||||||
|
char *from = NULL, *to = NULL, *tmp = NULL;
|
||||||
|
zval *pgsql_link = NULL;
|
||||||
|
PGconn *pgsql;
|
||||||
|
int to_len;
|
||||||
|
int from_len;
|
||||||
|
int id = -1;
|
||||||
|
|
||||||
|
switch (ZEND_NUM_ARGS()) {
|
||||||
|
case 1:
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &from, &from_len) == FAILURE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pgsql_link = NULL;
|
||||||
|
id = PGG(default_link);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &from, &from_len) == FAILURE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pgsql_link == NULL && id == -1) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
||||||
|
if (pgsql == NULL) {
|
||||||
|
php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot get default pgsql link");
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_PQESCAPELITERAL
|
||||||
|
if (escape_literal) {
|
||||||
|
tmp = PQescapeLiteral(pgsql, from, (size_t)from_len);
|
||||||
|
} else {
|
||||||
|
tmp = PQescapeIdentifier(pgsql, from, (size_t)from_len);
|
||||||
|
}
|
||||||
|
if (!tmp) {
|
||||||
|
php_error_docref(NULL TSRMLS_CC, E_WARNING,"Failed to escape");
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
to = estrdup(tmp);
|
||||||
|
PQfreemem(tmp);
|
||||||
|
#else
|
||||||
|
to = php_pgsql_PQescapeInternal(pgsql, from, (size_t)from_len, escape_literal);
|
||||||
|
if (!to) {
|
||||||
|
php_error_docref(NULL TSRMLS_CC, E_WARNING,"Failed to escape");
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RETURN_STRING(to, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* {{{ proto string pg_escape_literal([resource connection,] string data)
|
||||||
|
Escape parameter as string literal (i.e. parameter) */
|
||||||
|
PHP_FUNCTION(pg_escape_literal)
|
||||||
|
{
|
||||||
|
php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ proto string pg_escape_identifier([resource connection,] string data)
|
||||||
|
Escape identifier (i.e. table name, field name) */
|
||||||
|
PHP_FUNCTION(pg_escape_identifier)
|
||||||
|
{
|
||||||
|
php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* {{{ proto string pg_result_error(resource result)
|
/* {{{ proto string pg_result_error(resource result)
|
||||||
Get error message associated with result */
|
Get error message associated with result */
|
||||||
PHP_FUNCTION(pg_result_error)
|
PHP_FUNCTION(pg_result_error)
|
||||||
|
@ -172,6 +172,8 @@ PHP_FUNCTION(pg_set_error_verbosity);
|
|||||||
PHP_FUNCTION(pg_escape_string);
|
PHP_FUNCTION(pg_escape_string);
|
||||||
PHP_FUNCTION(pg_escape_bytea);
|
PHP_FUNCTION(pg_escape_bytea);
|
||||||
PHP_FUNCTION(pg_unescape_bytea);
|
PHP_FUNCTION(pg_unescape_bytea);
|
||||||
|
PHP_FUNCTION(pg_escape_literal);
|
||||||
|
PHP_FUNCTION(pg_escape_identifier);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* misc functions */
|
/* misc functions */
|
||||||
|
@ -11,8 +11,9 @@ define('FILE_NAME', dirname(__FILE__) . '/php.gif');
|
|||||||
// pg_escape_string() test
|
// pg_escape_string() test
|
||||||
$before = "ABC\\ABC\'";
|
$before = "ABC\\ABC\'";
|
||||||
$expect = "ABC\\\\ABC\\'";
|
$expect = "ABC\\\\ABC\\'";
|
||||||
|
$expect2 = "ABC\\\\ABC\\\\''"; //the way escape string differs from PostgreSQL 9.0
|
||||||
$after = pg_escape_string($before);
|
$after = pg_escape_string($before);
|
||||||
if ($expect === $after) {
|
if ($expect === $after || $expect2 === $after) {
|
||||||
echo "pg_escape_string() is Ok\n";
|
echo "pg_escape_string() is Ok\n";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -58,11 +59,37 @@ else {
|
|||||||
echo "pg_escape_bytea() is broken\n";
|
echo "pg_escape_bytea() is broken\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pg_escape_literal/pg_escape_identifier
|
||||||
|
$before = "ABC\\ABC\'";
|
||||||
|
$expect = " E'ABC\\\\ABC\\\\'''";
|
||||||
|
$after = pg_escape_literal($before);
|
||||||
|
if ($expect === $after) {
|
||||||
|
echo "pg_escape_literal() is Ok\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo "pg_escape_literal() is NOT Ok\n";
|
||||||
|
var_dump($before);
|
||||||
|
var_dump($after);
|
||||||
|
var_dump($expect);
|
||||||
|
}
|
||||||
|
|
||||||
|
$before = "ABC\\ABC\'";
|
||||||
|
$expect = "\"ABC\ABC\'\"";
|
||||||
|
$after = pg_escape_identifier($before);
|
||||||
|
if ($expect === $after) {
|
||||||
|
echo "pg_escape_identifier() is Ok\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo "pg_escape_identifier() is NOT Ok\n";
|
||||||
|
var_dump($before);
|
||||||
|
var_dump($after);
|
||||||
|
var_dump($expect);
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
pg_escape_string() is NOT Ok
|
pg_escape_string() is Ok
|
||||||
string(9) "ABC\ABC\'"
|
|
||||||
string(12) "ABC\\ABC\\''"
|
|
||||||
string(10) "ABC\\ABC\'"
|
|
||||||
pg_escape_bytea() is Ok
|
pg_escape_bytea() is Ok
|
||||||
pg_escape_bytea() actually works with database
|
pg_escape_bytea() actually works with database
|
||||||
|
pg_escape_literal() is Ok
|
||||||
|
pg_escape_identifier() is Ok
|
Loading…
Reference in New Issue
Block a user