]> granicus.if.org Git - php/commitdiff
Transparently decode binary encoded data.
authorWez Furlong <wez@php.net>
Sat, 19 Apr 2003 12:54:17 +0000 (12:54 +0000)
committerWez Furlong <wez@php.net>
Sat, 19 Apr 2003 12:54:17 +0000 (12:54 +0000)
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.

ext/sqlite/config.m4
ext/sqlite/sqlite.c
ext/sqlite/tests/sqlite_004.phpt [new file with mode: 0644]

index 7e70077aa4e2e0de471033015ea229ac0b09966c..4f362ed0e9d8eba3ec2374bb23e83a5d4eb361b6 100644 (file)
@@ -42,7 +42,7 @@ if test "$PHP_SQLITE" != "no"; then
        ])
  
        PHP_SUBST(SQLITE_SHARED_LIBADD)
-       PHP_NEW_EXTENSION(sqlite, sqlite.c, $ext_shared)
+       PHP_NEW_EXTENSION(sqlite, sqlite.c libsqlite/src/encode.c, $ext_shared)
   else
        # use bundled library
        sources="libsqlite/src/opcodes.c
index da712c1cb14bff2f475e2be3953a208b5c42a4ca..5ca2b78f089c15e9103c73fbd756916661f09be5 100644 (file)
 
 #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);
+               }
        }
 }
 /* }}} */
diff --git a/ext/sqlite/tests/sqlite_004.phpt b/ext/sqlite/tests/sqlite_004.phpt
new file mode 100644 (file)
index 0000000..a605573
--- /dev/null
@@ -0,0 +1,44 @@
+--TEST--
+sqlite: binary encoding
+--SKIPIF--
+<?php # vim:ft=php
+if (!extension_loaded("sqlite")) print "skip"; ?>
+--FILE--
+<?php 
+include "blankdb.inc";
+
+$strings = array(
+       "hello",
+       "hello\x01o",
+       "\x01hello there",
+       "hello\x00there",
+       ""
+);
+
+sqlite_query("CREATE TABLE strings(a)", $db);
+
+foreach ($strings as $str) {
+       sqlite_query("INSERT INTO strings VALUES('" . sqlite_escape_string($str) . "')", $db);
+}
+
+$i = 0;
+$r = sqlite_query("SELECT * from strings", $db);
+while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
+       if ($row[0] !== $strings[$i]) {
+               echo "FAIL!\n";
+               var_dump($row[0]);
+               var_dump($strings[$i]);
+       } else {
+               echo "OK!\n";
+       }
+       $i++;
+}
+echo "DONE!\n";
+?>
+--EXPECT--
+OK!
+OK!
+OK!
+OK!
+OK!
+DONE!