Thank you!

--
Yasuo Ohgaki
yohg...@ohgaki.net



2011/11/25 Stanislav Malyshev <s...@php.net>:
> Commit:    655245afef75613551929610873d0ba09754777f
> Author:    Yasuo Ohgaki <yohg...@php.net>         Fri, 25 Nov 2011 02:21:01 
> +0000
> Committer: Stanislav Malyshev <s...@php.net>      Thu, 19 Apr 2012 13:40:24 
> -0700
> Parents:   106e0a2e688f3e5c97e49760b9c3c99eea714ae8
> Branches:  PHP-5.4
>
> Link:       
> http://git.php.net/?p=php-src.git;a=commitdiff;h=655245afef75613551929610873d0ba09754777f
>
> Log:
> add pg_escape_identifier/pg_escape_literal
>
> Changed paths:
>  M  ext/pgsql/config.m4
>  M  ext/pgsql/pgsql.c
>  M  ext/pgsql/php_pgsql.h
>  M  ext/pgsql/tests/08escape.phpt
>
>
> Diff:
> diff --git a/ext/pgsql/config.m4 b/ext/pgsql/config.m4
> index 2710796..bddb77a 100644
> --- a/ext/pgsql/config.m4
> +++ b/ext/pgsql/config.m4
> @@ -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, 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, PQescapeLiteral, 
> AC_DEFINE(HAVE_PQESCAPELITERAL,1,[PostgreSQL 9.0 or later]))
>   LIBS=$old_LIBS
>   LDFLAGS=$old_LDFLAGS
>
> diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
> index 54a86a8..ad66779 100644
> --- a/ext/pgsql/pgsql.c
> +++ b/ext/pgsql/pgsql.c
> @@ -422,6 +422,17 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_unescape_bytea, 0, 0, 
> 1)
>  ZEND_END_ARG_INFO()
>  #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_ARG_INFO(0, result)
>  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_bytea,         arginfo_pg_escape_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
>  #if HAVE_PQSETERRORVERBOSITY
>        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();
>        if (! PGG(ignore_notices)) {
>                notice = (php_pgsql_notice *)emalloc(sizeof(php_pgsql_notice));
> -               notice->message = _php_pgsql_trim_message(message, 
> &notice->len);
> +               notice->message = _php_pgsql_trim_message(message, (int 
> *)&notice->len);
>                if (PGG(log_notices)) {
>                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s", 
> notice->message);
>                }
> @@ -4206,6 +4219,130 @@ 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, *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)
>    Get error message associated with result */
>  PHP_FUNCTION(pg_result_error)
> diff --git a/ext/pgsql/php_pgsql.h b/ext/pgsql/php_pgsql.h
> index b247456..8b6abbf 100644
> --- a/ext/pgsql/php_pgsql.h
> +++ b/ext/pgsql/php_pgsql.h
> @@ -172,6 +172,8 @@ PHP_FUNCTION(pg_set_error_verbosity);
>  PHP_FUNCTION(pg_escape_string);
>  PHP_FUNCTION(pg_escape_bytea);
>  PHP_FUNCTION(pg_unescape_bytea);
> +PHP_FUNCTION(pg_escape_literal);
> +PHP_FUNCTION(pg_escape_identifier);
>  #endif
>
>  /* misc functions */
> diff --git a/ext/pgsql/tests/08escape.phpt b/ext/pgsql/tests/08escape.phpt
> index cf23b50..90b4ed8 100644
> --- a/ext/pgsql/tests/08escape.phpt
> +++ b/ext/pgsql/tests/08escape.phpt
> @@ -11,8 +11,9 @@ define('FILE_NAME', dirname(__FILE__) . '/php.gif');
>  // pg_escape_string() test
>  $before = "ABC\\ABC\'";
>  $expect  = "ABC\\\\ABC\\'";
> +$expect2  = "ABC\\\\ABC\\\\''"; //the way escape string differs from 
> PostgreSQL 9.0
>  $after = pg_escape_string($before);
> -if ($expect === $after) {
> +if ($expect === $after || $expect2 === $after) {
>        echo "pg_escape_string() is Ok\n";
>  }
>  else {
> @@ -58,11 +59,37 @@ else {
>        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--
> -pg_escape_string() is NOT Ok
> -string(9) "ABC\ABC\'"
> -string(12) "ABC\\ABC\\''"
> -string(10) "ABC\\ABC\'"
> +pg_escape_string() is Ok
>  pg_escape_bytea() is Ok
>  pg_escape_bytea() actually works with database
> +pg_escape_literal() is Ok
> +pg_escape_identifier() is Ok
> \ No newline at end of file
>
>
> --
> PHP CVS Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>

--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to