From: Yasuo Ohgaki Date: Wed, 2 Oct 2002 04:03:21 +0000 (+0000) Subject: Added pg_unescape_bytea(). Fixed pg_data_seek(). X-Git-Tag: MODERN_SYMMETRIC_SESSION_BEHAVIOUR_20021003~26 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=69957c56b3df50e132ddcd5a494f5830ff9af36c;p=php Added pg_unescape_bytea(). Fixed pg_data_seek(). php_pgsql_unescape_bytea(PQunescapeBytea) is shamelessly stolen from PostgreSQL 7.3 :) --- diff --git a/NEWS b/NEWS index 75bc5c0cbc..dd4f8479c1 100644 --- a/NEWS +++ b/NEWS @@ -8,7 +8,8 @@ PHP 4 NEWS - Fixed output buffering implicit flush. (Yasuo) - Added getopt() for parsing command line options and arguments. (Jon) - Added pg_fetch_assoc(), pg_fetch_all(), pg_ping(), pg_meta_data(), pg_convert(), - pg_insert(), pg_select(), pg_update(), pg_delete() and pg_data_seek(). (Yasuo) + pg_insert(), pg_select(), pg_update(), pg_delete(), pg_data_seek() and + pg_unescape_bytea(). (Yasuo) - Fixed bug #17281 (Sanity checks for encoding sessions). (Ilia) - Fixed bug #16995 and #19392 (Prevent crash if $HTTP_SESSION_VARS != ARRAY). (Ilia) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index d24876594a..3b3990917d 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -1423,7 +1423,6 @@ PHP_FUNCTION(pg_data_seek) { zval *result; int row; - PGresult *pgsql_result; pgsql_result_handle *pg_result; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", @@ -1438,7 +1437,7 @@ PHP_FUNCTION(pg_data_seek) /* if (ZEND_NUM_ARGS() == 1) */ /* RETURN_LONG(pg_result->row); */ - if (row < 0 || row >= PQntuples(pg_result)) + if (row < 0 || row >= PQntuples(pg_result->result)) RETURN_FALSE; /* seek to offset */ @@ -2616,6 +2615,133 @@ PHP_FUNCTION(pg_escape_bytea) free(to); } /* }}} */ + +/* PQunescapeBytea() from PostgreSQL 7.3 to provide bytea unescape feature to 7.2 users. + Renamed to php_pgsql_unescape_bytea() */ +/* + * PQunescapeBytea - converts the null terminated string representation + * of a bytea, strtext, into binary, filling a buffer. It returns a + * pointer to the buffer which is NULL on error, and the size of the + * buffer in retbuflen. The pointer may subsequently be used as an + * argument to the function free(3). It is the reverse of PQescapeBytea. + * + * The following transformations are reversed: + * '\0' == ASCII 0 == \000 + * '\'' == ASCII 39 == \' + * '\\' == ASCII 92 == \\ + * + * States: + * 0 normal 0->1->2->3->4 + * 1 \ 1->5 + * 2 \0 1->6 + * 3 \00 + * 4 \000 + * 5 \' + * 6 \\ + */ +static unsigned char * php_pgsql_unescape_bytea(unsigned char *strtext, size_t *retbuflen) +{ + size_t buflen; + unsigned char *buffer, + *sp, + *bp; + unsigned int state = 0; + + if (strtext == NULL) + return NULL; + buflen = strlen(strtext); /* will shrink, also we discover if + * strtext */ + buffer = (unsigned char *) malloc(buflen); /* isn't NULL terminated */ + if (buffer == NULL) + return NULL; + for (bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++) + { + switch (state) + { + case 0: + if (*sp == '\\') + state = 1; + *bp = *sp; + break; + case 1: + if (*sp == '\'') /* state=5 */ + { /* replace \' with 39 */ + bp--; + *bp = '\''; + buflen--; + state = 0; + } + else if (*sp == '\\') /* state=6 */ + { /* replace \\ with 92 */ + bp--; + *bp = '\\'; + buflen--; + state = 0; + } + else + { + if (isdigit(*sp)) + state = 2; + else + state = 0; + *bp = *sp; + } + break; + case 2: + if (isdigit(*sp)) + state = 3; + else + state = 0; + *bp = *sp; + break; + case 3: + if (isdigit(*sp)) /* state=4 */ + { + int v; + + bp -= 3; + sscanf(sp - 2, "%03o", &v); + *bp = v; + buflen -= 3; + state = 0; + } + else + { + *bp = *sp; + state = 0; + } + break; + } + } + buffer = realloc(buffer, buflen); + if (buffer == NULL) + return NULL; + + *retbuflen = buflen; + return buffer; +} + +/* {{{ proto string pg_unescape_bytea(string data) + Unescape binary for bytea type */ +PHP_FUNCTION(pg_unescape_bytea) +{ + char *from = NULL, *to = NULL; + size_t from_len, to_len; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", + &from, &from_len) == FAILURE) { + return; + } + + to = (char *)php_pgsql_unescape_bytea((unsigned char*)from, from_len); + if (!to) { + RETVAL_FALSE; + } + else { + RETVAL_STRINGL(to, to_len-1, 1); /* to_len includes addtional '\0' */ + } + free(to); +} +/* }}} */ #endif /* {{{ proto string pg_result_error(resource result)