mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Refactor and cleanup. WS is cleaned up. Use -b if it is needed.
Added compatibility macros, PQescapeStringConn, PGSQLescapeLiteral/Identifier, PGSQLfree.
This commit is contained in:
parent
5cc851e83e
commit
832c21cabf
2 changed files with 268 additions and 285 deletions
|
@ -746,6 +746,104 @@ ZEND_GET_MODULE(pgsql)
|
|||
|
||||
static int le_link, le_plink, le_result, le_lofp, le_string;
|
||||
|
||||
/* Compatibility definitions */
|
||||
|
||||
#ifndef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
|
||||
#define pg_encoding_to_char(x) "SQL_ASCII"
|
||||
#endif
|
||||
|
||||
#if !HAVE_PQESCAPE_CONN
|
||||
#define PQescapeStringConn(conn, to, form, len, error) PQescapeString(to, from, len)
|
||||
#endif
|
||||
|
||||
#if HAVE_PQESCAPELITERAL
|
||||
#define PGSQLescapeLiteral(conn, str, len) PQescapeLiteral(conn, str, len)
|
||||
#define PGSQLescapeIdentifier(conn, str, len) PQescapeIdentifier(conn, str, len)
|
||||
#define PGSQLfree(a) PQfreemem(a)
|
||||
#else
|
||||
#define PGSQLescapeLiteral(conn, str, len) php_pgsql_PQescapeInternal(conn, str, len, 1, 0)
|
||||
#define PGSQLescapeLiteral2(conn, str, len) php_pgsql_PQescapeInternal(conn, str, len, 1, 1)
|
||||
#define PGSQLescapeIdentifier(conn, str, len) php_pgsql_PQescapeInternal(conn, str, len, 0, 0)
|
||||
#define PGSQLfree(a) efree(a)
|
||||
|
||||
/* emulate libpq's PQescapeInternal() 9.0 or later */
|
||||
static char* php_pgsql_PQescapeInternal(PGconn *conn, const char *str, size_t len, int escape_literal, int safe) {
|
||||
char *result, *rp, *s;
|
||||
size_t tmp_len;
|
||||
|
||||
if (!conn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* allocate enough memory */
|
||||
rp = result = (char *)safe_emalloc(len, 2, 5); /* leading " E" needs extra 2 bytes + quote_chars on both end for 2 bytes + NULL */
|
||||
|
||||
if (escape_literal) {
|
||||
size_t new_len;
|
||||
|
||||
if (safe) {
|
||||
char *tmp = (char *)safe_emalloc(len, 2, 1);
|
||||
*rp++ = '\'';
|
||||
/* PQescapeString does not escape \, but it handles multibyte chars safely.
|
||||
This escape is incompatible with PQescapeLiteral. */
|
||||
new_len = PQescapeStringConn(conn, tmp, str, len, NULL);
|
||||
strncpy(rp, tmp, new_len);
|
||||
efree(tmp);
|
||||
rp += new_len;
|
||||
} else {
|
||||
char *encoding;
|
||||
/* This is compatible with PQescapeLiteral, but it cannot handle multbyte chars
|
||||
such as SJIS, BIG5. Raise warning and return NULL by checking
|
||||
client_encoding. XXX: Black list could be wrong. False positive. */
|
||||
encoding = (char *) pg_encoding_to_char(PQclientEncoding(conn));
|
||||
if (!strncmp(encoding, "SJIS", sizeof("SJIS")-1) ||
|
||||
!strncmp(encoding, "SHIFT_JIS_2004", sizeof("SHIFT_JIS_2004")-1) ||
|
||||
!strncmp(encoding, "WIN874", sizeof("WIN874")-1) ||
|
||||
!strncmp(encoding, "WIN1258", sizeof("WIN1258")-1) ||
|
||||
!strncmp(encoding, "BIG5", sizeof("BIG5")-1) ||
|
||||
!strncmp(encoding, "GBK", sizeof("GBK")-1) ||
|
||||
!strncmp(encoding, "JOHAB", sizeof("JOHAB")-1) ||
|
||||
!strncmp(encoding, "UHC", sizeof("UHC")-1) ) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsafe encoding is used. Do not use '%s' encoding or use PostgreSQL 9.0 or later libpq.", encoding);
|
||||
}
|
||||
/* check backslashes */
|
||||
tmp_len = strspn(str, "\\");
|
||||
if (tmp_len != len) {
|
||||
/* add " E" for escaping slashes */
|
||||
*rp++ = ' ';
|
||||
*rp++ = 'E';
|
||||
}
|
||||
*rp++ = '\'';
|
||||
for (s = (char *)str; s - str < len; ++s) {
|
||||
if (*s == '\'' || *s == '\\') {
|
||||
*rp++ = *s;
|
||||
*rp++ = *s;
|
||||
} else {
|
||||
*rp++ = *s;
|
||||
}
|
||||
}
|
||||
}
|
||||
*rp++ = '\'';
|
||||
} else {
|
||||
/* Identifier escape. */
|
||||
*rp++ = '"';
|
||||
for (s = (char *)str; s - str < len; ++s) {
|
||||
if (*s == '"') {
|
||||
*rp++ = '"';
|
||||
*rp++ = '"';
|
||||
} else {
|
||||
*rp++ = *s;
|
||||
}
|
||||
}
|
||||
*rp++ = '"';
|
||||
}
|
||||
*rp = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* {{{ _php_pgsql_trim_message */
|
||||
static char * _php_pgsql_trim_message(const char *message, int *len)
|
||||
{
|
||||
|
@ -944,36 +1042,6 @@ static int _php_pgsql_detect_identifier_escape(const char *identifier, size_t le
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
#if !HAVE_PQESCAPELITERAL
|
||||
/* {{{ _php_pgsql_escape_identifier
|
||||
* Since PQescapeIdentifier() is unavailable (PostgreSQL 9.0 <), idenfifers
|
||||
* should be escaped by pgsql module.
|
||||
* Note: this function does not care for encoding. Therefore users should not
|
||||
* use this with SJIS/BIG5 etc. (i.e. Encoding base injection may possible with
|
||||
* before PostgreSQL 9.0)
|
||||
*/
|
||||
static char *_php_pgsql_escape_identifier(const char *field, size_t field_len)
|
||||
{
|
||||
ulong field_escaped_len = field_len*2 + 3;
|
||||
ulong i, j = 0;
|
||||
char *field_escaped;
|
||||
|
||||
field_escaped = (char *)malloc(field_escaped_len);
|
||||
field_escaped[j++] = '"';
|
||||
for (i = 0; i < field_len; i++) {
|
||||
if (field[i] == '"') {
|
||||
field_escaped[j++] = '"';
|
||||
field_escaped[j++] = '"';
|
||||
} else {
|
||||
field_escaped[j++] = field[i];
|
||||
}
|
||||
}
|
||||
field_escaped[j++] = '"';
|
||||
field_escaped[j] = '\0';
|
||||
return field_escaped;
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
/* {{{ _php_pgsql_strndup, no strndup should be used */
|
||||
static char *_php_pgsql_strndup(const char *s, size_t len)
|
||||
|
@ -1457,6 +1525,7 @@ PHP_FUNCTION(pg_close)
|
|||
#define PHP_PG_HOST 6
|
||||
#define PHP_PG_VERSION 7
|
||||
|
||||
|
||||
/* {{{ php_pgsql_get_link_info
|
||||
*/
|
||||
static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
|
||||
|
@ -2266,7 +2335,6 @@ PHP_FUNCTION(pg_field_table)
|
|||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (return_oid) {
|
||||
#if UINT_MAX > LONG_MAX /* Oid is unsigned int, we don't need this code, where LONG is wider */
|
||||
if (oid > LONG_MAX) {
|
||||
|
@ -2296,7 +2364,6 @@ PHP_FUNCTION(pg_field_table)
|
|||
smart_str_append_unsigned(&querystr, oid);
|
||||
smart_str_0(&querystr);
|
||||
|
||||
|
||||
if ((tmp_res = PQexec(pg_result->conn, querystr.c)) == NULL || PQresultStatus(tmp_res) != PGRES_TUPLES_OK) {
|
||||
if (tmp_res) {
|
||||
PQclear(tmp_res);
|
||||
|
@ -3053,7 +3120,7 @@ PHP_FUNCTION(pg_lo_create)
|
|||
|
||||
if (oid) {
|
||||
#ifndef HAVE_PG_LO_CREATE
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "OID value passing not supported");
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Passing OID value is not supported. Upgrade your PostgreSQL");
|
||||
#else
|
||||
switch (Z_TYPE_P(oid)) {
|
||||
case IS_STRING:
|
||||
|
@ -3734,10 +3801,6 @@ PHP_FUNCTION(pg_client_encoding)
|
|||
|
||||
/* Just do the same as found in PostgreSQL sources... */
|
||||
|
||||
#ifndef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
|
||||
#define pg_encoding_to_char(x) "SQL_ASCII"
|
||||
#endif
|
||||
|
||||
Z_STRVAL_P(return_value) = (char *) pg_encoding_to_char(PQclientEncoding(pgsql));
|
||||
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
||||
Z_STRVAL_P(return_value) = (char *) estrdup(Z_STRVAL_P(return_value));
|
||||
|
@ -4114,7 +4177,6 @@ PHP_FUNCTION(pg_escape_string)
|
|||
}
|
||||
|
||||
to = (char *) safe_emalloc(from_len, 2, 1);
|
||||
|
||||
#ifdef HAVE_PQESCAPE_CONN
|
||||
if (pgsql_link != NULL || id != -1) {
|
||||
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
|
||||
|
@ -4302,61 +4364,13 @@ PHP_FUNCTION(pg_unescape_bytea)
|
|||
#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;
|
||||
zval *pgsql_link = NULL;
|
||||
PGconn *pgsql;
|
||||
int from_len;
|
||||
int id = -1;
|
||||
char *tmp;
|
||||
|
||||
switch (ZEND_NUM_ARGS()) {
|
||||
case 1:
|
||||
|
@ -4384,30 +4398,18 @@ static void php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAMETERS, int escape_l
|
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot get pgsql link");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
#ifdef HAVE_PQESCAPELITERAL
|
||||
/* Use a block with a local var to avoid unused variable warnings */
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
if (escape_literal) {
|
||||
tmp = PQescapeLiteral(pgsql, from, (size_t)from_len);
|
||||
tmp = PGSQLescapeLiteral(pgsql, from, (size_t)from_len);
|
||||
} else {
|
||||
tmp = PQescapeIdentifier(pgsql, from, (size_t)from_len);
|
||||
tmp = PGSQLescapeIdentifier(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
|
||||
PGSQLfree(tmp);
|
||||
|
||||
RETURN_STRING(to, 0);
|
||||
}
|
||||
|
@ -4455,6 +4457,7 @@ PHP_FUNCTION(pg_result_error)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
#if HAVE_PQRESULTERRORFIELD
|
||||
/* {{{ proto string pg_result_error_field(resource result, int fieldcode)
|
||||
Get error message field associated with result */
|
||||
|
@ -4500,6 +4503,7 @@ PHP_FUNCTION(pg_result_error_field)
|
|||
/* }}} */
|
||||
#endif
|
||||
|
||||
|
||||
/* {{{ proto int pg_connection_status(resource connection)
|
||||
Get connection status */
|
||||
PHP_FUNCTION(pg_connection_status)
|
||||
|
@ -4520,6 +4524,7 @@ PHP_FUNCTION(pg_connection_status)
|
|||
|
||||
/* }}} */
|
||||
|
||||
|
||||
#if HAVE_PGTRANSACTIONSTATUS
|
||||
/* {{{ proto int pg_transaction_status(resource connection)
|
||||
Get transaction status */
|
||||
|
@ -4542,6 +4547,7 @@ PHP_FUNCTION(pg_transaction_status)
|
|||
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto bool pg_connection_reset(resource connection)
|
||||
Reset connection (reconnect) */
|
||||
PHP_FUNCTION(pg_connection_reset)
|
||||
|
@ -4563,12 +4569,13 @@ PHP_FUNCTION(pg_connection_reset)
|
|||
}
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
|
||||
#define PHP_PG_ASYNC_IS_BUSY 1
|
||||
#define PHP_PG_ASYNC_REQUEST_CANCEL 2
|
||||
|
||||
|
||||
/* {{{ php_pgsql_flush_query
|
||||
*/
|
||||
static int php_pgsql_flush_query(PGconn *pgsql TSRMLS_DC)
|
||||
|
@ -4589,6 +4596,7 @@ static int php_pgsql_flush_query(PGconn *pgsql TSRMLS_DC)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ php_pgsql_do_async
|
||||
*/
|
||||
static void php_pgsql_do_async(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
|
||||
|
@ -5126,25 +5134,17 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z
|
|||
"FROM pg_class as c, pg_attribute a, pg_type t, pg_namespace n "
|
||||
"WHERE a.attnum > 0 AND a.attrelid = c.oid AND c.relname = '");
|
||||
escaped = (char *)safe_emalloc(strlen(tmp_name2), 2, 1);
|
||||
#if HAVE_PQESCAPE_CONN
|
||||
new_len = PQescapeStringConn(pg_link, escaped, tmp_name2, strlen(tmp_name2), NULL);
|
||||
#else
|
||||
new_len = PQescapeString(escaped, tmp_name2, strlen(tmp_name2));
|
||||
#endif
|
||||
if (new_len) {
|
||||
smart_str_appends(&querystr, escaped);
|
||||
smart_str_appendl(&querystr, escaped, new_len);
|
||||
}
|
||||
efree(escaped);
|
||||
|
||||
smart_str_appends(&querystr, "' AND c.relnamespace = n.oid AND n.nspname = '");
|
||||
escaped = (char *)safe_emalloc(strlen(tmp_name), 2, 1);
|
||||
#if HAVE_PQESCAPE_CONN
|
||||
new_len = PQescapeStringConn(pg_link, escaped, tmp_name, strlen(tmp_name), NULL);
|
||||
#else
|
||||
new_len = PQescapeString(escaped, tmp_name, strlen(tmp_name));
|
||||
#endif
|
||||
if (new_len) {
|
||||
smart_str_appends(&querystr, escaped);
|
||||
smart_str_appendl(&querystr, escaped, new_len);
|
||||
}
|
||||
efree(escaped);
|
||||
|
||||
|
@ -5234,6 +5234,7 @@ PHP_FUNCTION(pg_meta_data)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ php_pgsql_get_data_type
|
||||
*/
|
||||
static php_pgsql_data_type php_pgsql_get_data_type(const char *type_name, size_t len)
|
||||
|
@ -5641,17 +5642,11 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
|
|||
}
|
||||
}
|
||||
else {
|
||||
Z_TYPE_P(new_val) = IS_STRING;
|
||||
#if HAVE_PQESCAPE_CONN
|
||||
{
|
||||
char *tmp;
|
||||
Z_TYPE_P(new_val) = IS_STRING;
|
||||
tmp = (char *)safe_emalloc(Z_STRLEN_PP(val), 2, 1);
|
||||
Z_STRLEN_P(new_val) = (int)PQescapeStringConn(pg_link, tmp, Z_STRVAL_PP(val), Z_STRLEN_PP(val), NULL);
|
||||
Z_STRVAL_P(new_val) = tmp;
|
||||
}
|
||||
#else
|
||||
Z_STRVAL_P(new_val) = (int)PQescapeString(Z_STRVAL_PP(val), Z_STRLEN_PP(val), &Z_STRLEN_P(new_val), 0 TSRMLS_CC);
|
||||
#endif
|
||||
php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
|
||||
}
|
||||
break;
|
||||
|
@ -6043,16 +6038,12 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
|
|||
size_t field_len = strlen(field);
|
||||
|
||||
if (_php_pgsql_detect_identifier_escape(field, field_len) == SUCCESS) {
|
||||
escaped = _php_pgsql_strndup(field, field_len);
|
||||
add_assoc_zval(result, field, new_val);
|
||||
} else {
|
||||
#if HAVE_PQESCAPELITERAL
|
||||
escaped = PQescapeIdentifier(pg_link, field, field_len);
|
||||
#else
|
||||
escaped = _php_pgsql_escape_identifier(field, field_len);
|
||||
#endif
|
||||
}
|
||||
escaped = PGSQLescapeIdentifier(pg_link, field, field_len);
|
||||
add_assoc_zval(result, escaped, new_val);
|
||||
free(escaped);
|
||||
PGSQLfree(escaped);
|
||||
}
|
||||
}
|
||||
} /* for */
|
||||
zval_dtor(meta);
|
||||
|
@ -6139,29 +6130,21 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const c
|
|||
if (_php_pgsql_detect_identifier_escape(token, len) == SUCCESS) {
|
||||
escaped = _php_pgsql_strndup(token, len);
|
||||
} else {
|
||||
#if HAVE_PQESCAPELITERAL
|
||||
escaped = PQescapeIdentifier(pg_link, token, len);
|
||||
#else
|
||||
escaped = _php_pgsql_escape_identifier(token, len);
|
||||
#endif
|
||||
escaped = PGSQLescapeIdentifier(pg_link, token, len);
|
||||
}
|
||||
smart_str_appends(querystr, escaped);
|
||||
free(escaped);
|
||||
PGSQLfree(escaped);
|
||||
if (tmp && *tmp) {
|
||||
len = strlen(tmp);
|
||||
/* "schema"."table" format */
|
||||
if (_php_pgsql_detect_identifier_escape(tmp, len) == SUCCESS) {
|
||||
escaped = _php_pgsql_strndup(tmp, len);
|
||||
} else {
|
||||
#if HAVE_PQESCAPELITERAL
|
||||
escaped = PQescapeIdentifier(pg_link, tmp, len);
|
||||
#else
|
||||
escaped = _php_pgsql_escape_identifier(tmp, len);
|
||||
#endif
|
||||
escaped = PGSQLescapeIdentifier(pg_link, tmp, len);
|
||||
}
|
||||
smart_str_appendc(querystr, '.');
|
||||
smart_str_appends(querystr, escaped);
|
||||
free(escaped);
|
||||
PGSQLfree(escaped);
|
||||
}
|
||||
efree(table_copy);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue