diff options
author | Wez Furlong <wez@php.net> | 2003-04-19 12:54:17 +0000 |
---|---|---|
committer | Wez Furlong <wez@php.net> | 2003-04-19 12:54:17 +0000 |
commit | ff0d6adda4baaf6559f63861687c17896ea7b55e (patch) | |
tree | 2707ffe7b775652ddcbd4f56a0e34c0368c8cdd5 /ext/sqlite/sqlite.c | |
parent | de7874e11fbaebcfb8cde13d53bc756166b7c71a (diff) | |
download | php-git-ff0d6adda4baaf6559f63861687c17896ea7b55e.tar.gz |
Transparently decode binary encoded data.
Add a test-case for that process.
When encoding binary data, we mark the string with \x01 as its first character.
When returning data via sqlite_fetch_array(), if the first character is \x01,
then we decode the encoding. This behaviour can be turned off by the optional
last parameter to sqlite_fetch_array(), for compatibility with databases
created with other applications.
Diffstat (limited to 'ext/sqlite/sqlite.c')
-rw-r--r-- | ext/sqlite/sqlite.c | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/ext/sqlite/sqlite.c b/ext/sqlite/sqlite.c index da712c1cb1..5ca2b78f08 100644 --- a/ext/sqlite/sqlite.c +++ b/ext/sqlite/sqlite.c @@ -36,6 +36,10 @@ #include <sqlite.h> +extern int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out); +extern int sqlite_decode_binary(const unsigned char *in, unsigned char *out); + + static unsigned char arg3_force_ref[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE }; static int le_sqlite_db, le_sqlite_result, le_sqlite_pdb; @@ -686,7 +690,7 @@ next_row: } /* }}} */ -/* {{{ proto array sqlite_fetch_array(resource result [, int result_type]) +/* {{{ proto array sqlite_fetch_array(resource result [, int result_type, bool decode_binary]) Fetches the next row from a result set as an array */ PHP_FUNCTION(sqlite_fetch_array) { @@ -696,8 +700,9 @@ PHP_FUNCTION(sqlite_fetch_array) int j, ret; const char **rowdata, **colnames; char *errtext = NULL; + zend_bool decode_binary = 1; - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zres, &mode)) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) { return; } @@ -750,20 +755,38 @@ PHP_FUNCTION(sqlite_fetch_array) array_init(return_value); for (j = 0; j < res->ncolumns; j++) { + char *decoded = NULL; + int decoded_len; + + if (decode_binary && rowdata[j] != NULL && rowdata[j][0] == '\x01') { + int l = strlen(rowdata[j]); + decoded = do_alloca(l); + decoded_len = sqlite_decode_binary(rowdata[j]+1, decoded); + } else { + decoded = (char*)rowdata[j]; + if (decoded) { + decoded_len = strlen(decoded); + } + } + if (mode & PHPSQLITE_NUM) { - if (rowdata[j] == NULL) { + if (decoded == NULL) { add_index_null(return_value, j); } else { - add_index_string(return_value, j, (char*)rowdata[j], 1); + add_index_stringl(return_value, j, decoded, decoded_len, 1); } } if (mode & PHPSQLITE_ASSOC) { - if (rowdata[j] == NULL) { + if (decoded == NULL) { add_assoc_null(return_value, (char*)colnames[j]); } else { - add_assoc_string(return_value, (char*)colnames[j], (char*)rowdata[j], 1); + add_assoc_stringl(return_value, (char*)colnames[j], decoded, decoded_len, 1); } } + + if (decode_binary && rowdata[j] != NULL && rowdata[j][0] == '\x01') { + free_alloca(decoded); + } } /* advance the row pointer */ @@ -933,7 +956,7 @@ PHP_FUNCTION(sqlite_seek) Escapes a string for use as a query parameter */ PHP_FUNCTION(sqlite_escape_string) { - char *string; + char *string = NULL; long stringlen; char *ret; @@ -941,11 +964,21 @@ PHP_FUNCTION(sqlite_escape_string) return; } - ret = sqlite_mprintf("%q", string); - - if (ret) { - RETVAL_STRING(ret, 1); - sqlite_freemem(ret); + if (stringlen && (string[0] == '\x01' || memchr(string, '\0', stringlen) != NULL)) { + /* binary string */ + int enclen; + + ret = emalloc( 1 + ((256 * stringlen + 1262) / 253) ); + ret[0] = '\x01'; + enclen = sqlite_encode_binary((const unsigned char*)string, stringlen, ret+1); + RETVAL_STRINGL(ret, enclen+1, 0); + + } else { + ret = sqlite_mprintf("%q", string); + if (ret) { + RETVAL_STRING(ret, 1); + sqlite_freemem(ret); + } } } /* }}} */ |